]>
Commit | Line | Data |
---|---|---|
c6ce1e7e MT |
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 | |
d54a2ce4 | 4 | Subject: [PATCH 65/78] 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 | ||
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 |