]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/dnsmasq/0065-Allow-control-characters-in-names-in-the-cache-handl.patch
dnsmasq: Import patches from upstream
[ipfire-2.x.git] / src / patches / dnsmasq / 0065-Allow-control-characters-in-names-in-the-cache-handl.patch
CommitLineData
c6ce1e7e
MT
1From 394ff492da6af5da7e7d356be9586683bc5fc011 Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Sun, 29 Mar 2015 22:17:14 +0100
efbd3a9a 4Subject: [PATCH 65/98] Allow control characters in names in the cache, handle
c6ce1e7e
MT
5 when logging.
6
7---
8 src/cache.c | 19 +++++++++++++++++--
9 src/dnssec.c | 34 +++++++++++++++++-----------------
10 src/rfc1035.c | 7 +++----
11 3 files changed, 37 insertions(+), 23 deletions(-)
12
13diff --git a/src/cache.c b/src/cache.c
14index c95624c42b1c..873c5779044c 100644
15--- a/src/cache.c
16+++ b/src/cache.c
17@@ -1399,6 +1399,19 @@ int cache_make_stat(struct txt_record *t)
18 return 1;
19 }
20
21+/* There can be names in the cache containing control chars, don't
22+ mess up logging or open security holes. */
23+static char *sanitise(char *name)
24+{
25+ unsigned char *r;
26+ for (r = (unsigned char *)name; *r; r++)
27+ if (!isprint((int)*r))
28+ return "<name unprintable>";
29+
30+ return name;
31+}
32+
33+
34 void dump_cache(time_t now)
35 {
36 struct server *serv, *serv1;
37@@ -1452,9 +1465,9 @@ void dump_cache(time_t now)
38 *a = 0;
39 if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
40 n = "<Root>";
41- p += sprintf(p, "%-30.30s ", n);
42+ p += sprintf(p, "%-30.30s ", sanitise(n));
43 if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
44- a = cache_get_cname_target(cache);
45+ a = sanitise(cache_get_cname_target(cache));
46 #ifdef HAVE_DNSSEC
47 else if (cache->flags & F_DS)
48 {
49@@ -1587,6 +1600,8 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
50 if (!option_bool(OPT_LOG))
51 return;
52
53+ name = sanitise(name);
54+
55 if (addr)
56 {
57 if (flags & F_KEYTAG)
58diff --git a/src/dnssec.c b/src/dnssec.c
59index 8bd5294ce773..14bae7e9bf75 100644
60--- a/src/dnssec.c
61+++ b/src/dnssec.c
62@@ -552,7 +552,7 @@ static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end,
63
64 (*desc)++;
65
66- if (d == 0 && extract_name(header, plen, p, buff, 2, 0))
67+ if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
68 /* domain-name, canonicalise */
69 return to_wire(buff);
70 else
71@@ -811,7 +811,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
72 GETLONG(sig_inception, p);
73 GETSHORT(key_tag, p);
74
75- if (!extract_name(header, plen, &p, keyname, 2, 0))
76+ if (!extract_name(header, plen, &p, keyname, 1, 0))
77 return STAT_BOGUS;
78
79 /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
80@@ -866,7 +866,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
81 u16 len, *dp;
82
83 p = rrset[i];
84- if (!extract_name(header, plen, &p, name, 2, 10))
85+ if (!extract_name(header, plen, &p, name, 1, 10))
86 return STAT_BOGUS;
87
88 name_start = name;
89@@ -923,7 +923,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
90
91 /* namebuff used for workspace above, restore to leave unchanged on exit */
92 p = (unsigned char*)(rrset[0]);
93- extract_name(header, plen, &p, name, 2, 0);
94+ extract_name(header, plen, &p, name, 1, 0);
95
96 if (key)
97 {
98@@ -963,7 +963,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
99 struct all_addr a;
100
101 if (ntohs(header->qdcount) != 1 ||
102- !extract_name(header, plen, &p, name, 2, 4))
103+ !extract_name(header, plen, &p, name, 1, 4))
104 return STAT_BOGUS;
105
106 GETSHORT(qtype, p);
107@@ -1202,7 +1202,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
108 val = STAT_BOGUS;
109
110 p = (unsigned char *)(header+1);
111- extract_name(header, plen, &p, name, 2, 4);
112+ extract_name(header, plen, &p, name, 1, 4);
113 p += 4; /* qtype, qclass */
114
115 if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
116@@ -1419,12 +1419,12 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
117 for (i = 0; i < nsec_count; i++)
118 {
119 p = nsecs[i];
120- if (!extract_name(header, plen, &p, workspace1, 2, 10))
121+ if (!extract_name(header, plen, &p, workspace1, 1, 10))
122 return STAT_BOGUS;
123 p += 8; /* class, type, TTL */
124 GETSHORT(rdlen, p);
125 psave = p;
126- if (!extract_name(header, plen, &p, workspace2, 2, 10))
127+ if (!extract_name(header, plen, &p, workspace2, 1, 10))
128 return STAT_BOGUS;
129
130 rc = hostname_cmp(workspace1, name);
131@@ -1553,7 +1553,7 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
132 for (i = 0; i < nsec_count; i++)
133 if ((p = nsecs[i]))
134 {
135- if (!extract_name(header, plen, &p, workspace1, 2, 0) ||
136+ if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
137 !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
138 return 0;
139
140@@ -1730,7 +1730,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
141 for (i = 0; i < nsec_count; i++)
142 if ((p = nsecs[i]))
143 {
144- if (!extract_name(header, plen, &p, workspace1, 2, 0) ||
145+ if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
146 !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
147 return STAT_BOGUS;
148
149@@ -1796,7 +1796,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
150
151 qname = p1 = (unsigned char *)(header+1);
152
153- if (!extract_name(header, plen, &p1, name, 2, 4))
154+ if (!extract_name(header, plen, &p1, name, 1, 4))
155 return STAT_BOGUS;
156
157 GETSHORT(qtype, p1);
158@@ -1836,7 +1836,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
159 qname = p1;
160
161 /* looped CNAMES */
162- if (!cname_count-- || !extract_name(header, plen, &p1, name, 2, 0))
163+ if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
164 return STAT_BOGUS;
165
166 p1 = ans_start;
167@@ -1857,7 +1857,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
168
169 for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
170 {
171- if (!extract_name(header, plen, &p1, name, 2, 10))
172+ if (!extract_name(header, plen, &p1, name, 1, 10))
173 return STAT_BOGUS; /* bad packet */
174
175 GETSHORT(type1, p1);
176@@ -2039,7 +2039,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
177 an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
178
179 /* Get name of missing answer */
180- if (!extract_name(header, plen, &qname, name, 2, 0))
181+ if (!extract_name(header, plen, &qname, name, 1, 0))
182 return STAT_BOGUS;
183
184 if (nsec_type == T_NSEC)
185@@ -2061,7 +2061,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
186 int cname_count = CNAME_CHAIN;
187
188 /* Get question */
189- if (!extract_name(header, plen, &p, name, 2, 4))
190+ if (!extract_name(header, plen, &p, name, 1, 4))
191 return STAT_BOGUS;
192
193 p +=2; /* type */
194@@ -2102,7 +2102,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
195
196 /* Loop down CNAME chain/ */
197 if (!cname_count-- ||
198- !extract_name(header, plen, &p, name, 2, 0) ||
199+ !extract_name(header, plen, &p, name, 1, 0) ||
200 !(p = skip_questions(header, plen)))
201 return STAT_BOGUS;
202
203@@ -2419,7 +2419,7 @@ unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name
204
205 for (q = ntohs(header->qdcount); q != 0; q--)
206 {
207- if (!extract_name(header, plen, &p, name, 2, 4))
208+ if (!extract_name(header, plen, &p, name, 1, 4))
209 break; /* bad packet */
210
211 len = to_wire(name);
212diff --git a/src/rfc1035.c b/src/rfc1035.c
213index 10832a3d5d2e..7a07b0cee906 100644
214--- a/src/rfc1035.c
215+++ b/src/rfc1035.c
216@@ -16,7 +16,6 @@
217
218 #include "dnsmasq.h"
219
220-/* isExtract == 2 -> DNSSEC mode, no bitstrings, no ascii checks. */
221 int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
222 char *name, int isExtract, int extrabytes)
223 {
224@@ -87,7 +86,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
225 if ((l & 0x3f) != 1)
226 return 0; /* we only understand bitstrings */
227
228- if (isExtract != 1)
229+ if (!isExtract)
230 return 0; /* Cannot compare bitsrings */
231
232 count = *p++;
233@@ -129,8 +128,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
234 if (isExtract)
235 {
236 unsigned char c = *p;
237- if ((isExtract == 2 || (isascii(c) && !iscntrl(c))) && c != '.')
238- *cp++ = *p;
239+ if (c != 0 && c != '.')
240+ *cp++ = c;
241 else
242 return 0;
243 }
244--
2452.1.0
246