]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/dnsmasq/0065-Allow-control-characters-in-names-in-the-cache-handl.patch
a9b6f400b7ccb5ae3ba07a01312daf8758e6837f
[ipfire-2.x.git] / src / patches / dnsmasq / 0065-Allow-control-characters-in-names-in-the-cache-handl.patch
1 From 394ff492da6af5da7e7d356be9586683bc5fc011 Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Sun, 29 Mar 2015 22:17:14 +0100
4 Subject: [PATCH 65/78] Allow control characters in names in the cache, handle
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
13 diff --git a/src/cache.c b/src/cache.c
14 index 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)
58 diff --git a/src/dnssec.c b/src/dnssec.c
59 index 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);
212 diff --git a/src/rfc1035.c b/src/rfc1035.c
213 index 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 --
245 2.1.0
246