1 |
killerfox 09/03/01 09:40:26 |
2 |
|
3 |
Added: CVE2008-4392_0002-dnscache-cache-soa-records.patch |
4 |
CVE2008-4392_0001-dnscache-merge-similar-outgoing-queries.patch |
5 |
Log: |
6 |
Fix CVE2008-4392 |
7 |
(Portage version: 2.1.6.4/cvs/Linux 2.6.28.4 x86_64) |
8 |
|
9 |
Revision Changes Path |
10 |
1.1 net-dns/djbdns/files/CVE2008-4392_0002-dnscache-cache-soa-records.patch |
11 |
|
12 |
file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-dns/djbdns/files/CVE2008-4392_0002-dnscache-cache-soa-records.patch?rev=1.1&view=markup |
13 |
plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-dns/djbdns/files/CVE2008-4392_0002-dnscache-cache-soa-records.patch?rev=1.1&content-type=text/plain |
14 |
|
15 |
Index: CVE2008-4392_0002-dnscache-cache-soa-records.patch |
16 |
=================================================================== |
17 |
diff --git a/query.c b/query.c |
18 |
index 46cdc00..4574e97 100644 |
19 |
--- a/query.c |
20 |
+++ b/query.c |
21 |
@@ -319,6 +319,29 @@ static int doit(struct query *z,int state) |
22 |
} |
23 |
} |
24 |
|
25 |
+ if (typematch(DNS_T_SOA,dtype)) { |
26 |
+ byte_copy(key,2,DNS_T_SOA); |
27 |
+ cached = cache_get(key,dlen + 2,&cachedlen,&ttl); |
28 |
+ if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) { |
29 |
+ log_cachedanswer(d,DNS_T_SOA); |
30 |
+ if (!rqa(z)) goto DIE; |
31 |
+ pos = 0; |
32 |
+ while (pos = dns_packet_copy(cached,cachedlen,pos,misc,20)) { |
33 |
+ pos = dns_packet_getname(cached,cachedlen,pos,&t2); |
34 |
+ if (!pos) break; |
35 |
+ pos = dns_packet_getname(cached,cachedlen,pos,&t3); |
36 |
+ if (!pos) break; |
37 |
+ if (!response_rstart(d,DNS_T_SOA,ttl)) goto DIE; |
38 |
+ if (!response_addname(t2)) goto DIE; |
39 |
+ if (!response_addname(t3)) goto DIE; |
40 |
+ if (!response_addbytes(misc,20)) goto DIE; |
41 |
+ response_rfinish(RESPONSE_ANSWER); |
42 |
+ } |
43 |
+ cleanup(z); |
44 |
+ return 1; |
45 |
+ } |
46 |
+ } |
47 |
+ |
48 |
if (typematch(DNS_T_A,dtype)) { |
49 |
byte_copy(key,2,DNS_T_A); |
50 |
cached = cache_get(key,dlen + 2,&cachedlen,&ttl); |
51 |
@@ -351,7 +374,7 @@ static int doit(struct query *z,int state) |
52 |
} |
53 |
} |
54 |
|
55 |
- if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) { |
56 |
+ if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype) && !typematch(DNS_T_SOA,dtype)) { |
57 |
byte_copy(key,2,dtype); |
58 |
cached = cache_get(key,dlen + 2,&cachedlen,&ttl); |
59 |
if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) { |
60 |
@@ -585,15 +608,24 @@ static int doit(struct query *z,int state) |
61 |
else if (byte_equal(type,2,DNS_T_AXFR)) |
62 |
; |
63 |
else if (byte_equal(type,2,DNS_T_SOA)) { |
64 |
+ int non_authority = 0; |
65 |
+ save_start(); |
66 |
while (i < j) { |
67 |
pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE; |
68 |
pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE; |
69 |
pos = dns_packet_getname(buf,len,pos,&t3); if (!pos) goto DIE; |
70 |
pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) goto DIE; |
71 |
- if (records[i] < posauthority) |
72 |
+ if (records[i] < posauthority) { |
73 |
log_rrsoa(whichserver,t1,t2,t3,misc,ttl); |
74 |
+ save_data(misc,20); |
75 |
+ save_data(t2,dns_domain_length(t2)); |
76 |
+ save_data(t3,dns_domain_length(t3)); |
77 |
+ non_authority++; |
78 |
+ } |
79 |
++i; |
80 |
} |
81 |
+ if (non_authority) |
82 |
+ save_finish(DNS_T_SOA,t1,ttl); |
83 |
} |
84 |
else if (byte_equal(type,2,DNS_T_CNAME)) { |
85 |
pos = dns_packet_skipname(buf,len,records[j - 1]); if (!pos) goto DIE; |
86 |
|
87 |
|
88 |
|
89 |
|
90 |
1.1 net-dns/djbdns/files/CVE2008-4392_0001-dnscache-merge-similar-outgoing-queries.patch |
91 |
|
92 |
file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-dns/djbdns/files/CVE2008-4392_0001-dnscache-merge-similar-outgoing-queries.patch?rev=1.1&view=markup |
93 |
plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-dns/djbdns/files/CVE2008-4392_0001-dnscache-merge-similar-outgoing-queries.patch?rev=1.1&content-type=text/plain |
94 |
|
95 |
Index: CVE2008-4392_0001-dnscache-merge-similar-outgoing-queries.patch |
96 |
=================================================================== |
97 |
diff --git a/Makefile b/Makefile |
98 |
index 1429643..bc047c0 100644 |
99 |
--- a/Makefile |
100 |
+++ b/Makefile |
101 |
@@ -318,11 +318,11 @@ stralloc.h iopause.h taia.h tai.h uint64.h taia.h |
102 |
./compile dns_txt.c |
103 |
|
104 |
dnscache: \ |
105 |
-load dnscache.o droproot.o okclient.o log.o cache.o query.o \ |
106 |
+load dnscache.o droproot.o okclient.o log.o cache.o query.o qmerge.o \ |
107 |
response.o dd.o roots.o iopause.o prot.o dns.a env.a alloc.a buffer.a \ |
108 |
libtai.a unix.a byte.a socket.lib |
109 |
./load dnscache droproot.o okclient.o log.o cache.o \ |
110 |
- query.o response.o dd.o roots.o iopause.o prot.o dns.a \ |
111 |
+ query.o qmerge.o response.o dd.o roots.o iopause.o prot.o dns.a \ |
112 |
env.a alloc.a buffer.a libtai.a unix.a byte.a `cat \ |
113 |
socket.lib` |
114 |
|
115 |
@@ -343,7 +343,7 @@ compile dnscache.c env.h exit.h scan.h strerr.h error.h ip4.h \ |
116 |
uint16.h uint64.h socket.h uint16.h dns.h stralloc.h gen_alloc.h \ |
117 |
iopause.h taia.h tai.h uint64.h taia.h taia.h byte.h roots.h fmt.h \ |
118 |
iopause.h query.h dns.h uint32.h alloc.h response.h uint32.h cache.h \ |
119 |
-uint32.h uint64.h ndelay.h log.h uint64.h okclient.h droproot.h |
120 |
+uint32.h uint64.h ndelay.h log.h uint64.h okclient.h droproot.h maxclient.h |
121 |
./compile dnscache.c |
122 |
|
123 |
dnsfilter: \ |
124 |
@@ -687,11 +687,16 @@ qlog.o: \ |
125 |
compile qlog.c buffer.h qlog.h uint16.h |
126 |
./compile qlog.c |
127 |
|
128 |
+qmerge.o: \ |
129 |
+compile qmerge.c qmerge.h dns.h stralloc.h gen_alloc.h iopause.h \ |
130 |
+taia.h tai.h uint64.h log.h maxclient.h |
131 |
+ ./compile qmerge.c |
132 |
+ |
133 |
query.o: \ |
134 |
compile query.c error.h roots.h log.h uint64.h case.h cache.h \ |
135 |
uint32.h uint64.h byte.h dns.h stralloc.h gen_alloc.h iopause.h \ |
136 |
taia.h tai.h uint64.h taia.h uint64.h uint32.h uint16.h dd.h alloc.h \ |
137 |
-response.h uint32.h query.h dns.h uint32.h |
138 |
+response.h uint32.h query.h dns.h uint32.h qmerge.h |
139 |
./compile query.c |
140 |
|
141 |
random-ip: \ |
142 |
diff --git a/dnscache.c b/dnscache.c |
143 |
index 8c899a3..5ccb16a 100644 |
144 |
--- a/dnscache.c |
145 |
+++ b/dnscache.c |
146 |
@@ -22,6 +22,7 @@ |
147 |
#include "log.h" |
148 |
#include "okclient.h" |
149 |
#include "droproot.h" |
150 |
+#include "maxclient.h" |
151 |
|
152 |
static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qclass[2],char id[2]) |
153 |
{ |
154 |
@@ -54,7 +55,6 @@ uint64 numqueries = 0; |
155 |
|
156 |
static int udp53; |
157 |
|
158 |
-#define MAXUDP 200 |
159 |
static struct udpclient { |
160 |
struct query q; |
161 |
struct taia start; |
162 |
@@ -131,7 +131,6 @@ void u_new(void) |
163 |
|
164 |
static int tcp53; |
165 |
|
166 |
-#define MAXTCP 20 |
167 |
struct tcpclient { |
168 |
struct query q; |
169 |
struct taia start; |
170 |
diff --git a/log.c b/log.c |
171 |
index c43e8b0..b8cd7ce 100644 |
172 |
--- a/log.c |
173 |
+++ b/log.c |
174 |
@@ -150,6 +150,13 @@ void log_tx(const char *q,const char qtype[2],const char *control,const char ser |
175 |
line(); |
176 |
} |
177 |
|
178 |
+void log_tx_piggyback(const char *q, const char qtype[2], const char *control) |
179 |
+{ |
180 |
+ string("txpb "); |
181 |
+ logtype(qtype); space(); name(q); space(); name(control); |
182 |
+ line(); |
183 |
+} |
184 |
+ |
185 |
void log_cachedanswer(const char *q,const char type[2]) |
186 |
{ |
187 |
string("cached "); logtype(type); space(); |
188 |
diff --git a/log.h b/log.h |
189 |
index fe62fa3..d9a829b 100644 |
190 |
--- a/log.h |
191 |
+++ b/log.h |
192 |
@@ -18,6 +18,7 @@ extern void log_cachednxdomain(const char *); |
193 |
extern void log_cachedns(const char *,const char *); |
194 |
|
195 |
extern void log_tx(const char *,const char *,const char *,const char *,unsigned int); |
196 |
+extern void log_tx_piggyback(const char *,const char *,const char *); |
197 |
|
198 |
extern void log_nxdomain(const char *,const char *,unsigned int); |
199 |
extern void log_nodata(const char *,const char *,const char *,unsigned int); |
200 |
diff --git a/maxclient.h b/maxclient.h |
201 |
new file mode 100644 |
202 |
index 0000000..e52fcd1 |
203 |
--- /dev/null |
204 |
+++ b/maxclient.h |
205 |
@@ -0,0 +1,7 @@ |
206 |
+#ifndef MAXCLIENT_H |
207 |
+#define MAXCLIENT_H |
208 |
+ |
209 |
+#define MAXUDP 200 |
210 |
+#define MAXTCP 20 |
211 |
+ |
212 |
+#endif /* MAXCLIENT_H */ |
213 |
diff --git a/qmerge.c b/qmerge.c |
214 |
new file mode 100644 |
215 |
index 0000000..7c92299 |
216 |
--- /dev/null |
217 |
+++ b/qmerge.c |
218 |
@@ -0,0 +1,115 @@ |
219 |
+#include "qmerge.h" |
220 |
+#include "byte.h" |
221 |
+#include "log.h" |
222 |
+#include "maxclient.h" |
223 |
+ |
224 |
+#define QMERGE_MAX (MAXUDP+MAXTCP) |
225 |
+struct qmerge inprogress[QMERGE_MAX]; |
226 |
+ |
227 |
+static |
228 |
+int qmerge_key_init(struct qmerge_key *qmk, const char *q, const char qtype[2], |
229 |
+ const char *control) |
230 |
+{ |
231 |
+ if (!dns_domain_copy(&qmk->q, q)) return 0; |
232 |
+ byte_copy(qmk->qtype, 2, qtype); |
233 |
+ if (!dns_domain_copy(&qmk->control, control)) return 0; |
234 |
+ return 1; |
235 |
+} |
236 |
+ |
237 |
+static |
238 |
+int qmerge_key_equal(struct qmerge_key *a, struct qmerge_key *b) |
239 |
+{ |
240 |
+ return |
241 |
+ byte_equal(a->qtype, 2, b->qtype) && |
242 |
+ dns_domain_equal(a->q, b->q) && |
243 |
+ dns_domain_equal(a->control, b->control); |
244 |
+} |
245 |
+ |
246 |
+static |
247 |
+void qmerge_key_free(struct qmerge_key *qmk) |
248 |
+{ |
249 |
+ dns_domain_free(&qmk->q); |
250 |
+ dns_domain_free(&qmk->control); |
251 |
+} |
252 |
+ |
253 |
+void qmerge_free(struct qmerge **x) |
254 |
+{ |
255 |
+ struct qmerge *qm; |
256 |
+ |
257 |
+ qm = *x; |
258 |
+ *x = 0; |
259 |
+ if (!qm || !qm->active) return; |
260 |
+ |
261 |
+ qm->active--; |
262 |
+ if (!qm->active) { |
263 |
+ qmerge_key_free(&qm->key); |
264 |
+ dns_transmit_free(&qm->dt); |
265 |
+ } |
266 |
+} |
267 |
+ |
268 |
+int qmerge_start(struct qmerge **qm, const char servers[64], int flagrecursive, |
269 |
+ const char *q, const char qtype[2], const char localip[4], |
270 |
+ const char *control) |
271 |
+{ |
272 |
+ struct qmerge_key k; |
273 |
+ int i; |
274 |
+ int r; |
275 |
+ |
276 |
+ qmerge_free(qm); |
277 |
+ |
278 |
+ byte_zero(&k, sizeof k); |
279 |
+ if (!qmerge_key_init(&k, q, qtype, control)) return -1; |
280 |
+ for (i = 0; i < QMERGE_MAX; i++) { |
281 |
+ if (!inprogress[i].active) continue; |
282 |
+ if (!qmerge_key_equal(&k, &inprogress[i].key)) continue; |
283 |
+ log_tx_piggyback(q, qtype, control); |
284 |
+ inprogress[i].active++; |
285 |
+ *qm = &inprogress[i]; |
286 |
+ qmerge_key_free(&k); |
287 |
+ return 0; |
288 |
+ } |
289 |
+ |
290 |
+ for (i = 0; i < QMERGE_MAX; i++) |
291 |
+ if (!inprogress[i].active) |
292 |
+ break; |
293 |
+ if (i == QMERGE_MAX) return -1; |
294 |
+ |
295 |
+ log_tx(q, qtype, control, servers, 0); |
296 |
+ r = dns_transmit_start(&inprogress[i].dt, servers, flagrecursive, q, qtype, localip); |
297 |
+ if (r == -1) { qmerge_key_free(&k); return -1; } |
298 |
+ inprogress[i].active++; |
299 |
+ inprogress[i].state = 0; |
300 |
+ qmerge_key_free(&inprogress[i].key); |
301 |
+ byte_copy(&inprogress[i].key, sizeof k, &k); |
302 |
+ *qm = &inprogress[i]; |
303 |
+ return 0; |
304 |
+} |
305 |
+ |
306 |
+void qmerge_io(struct qmerge *qm, iopause_fd *io, struct taia *deadline) |
307 |
+{ |
308 |
+ if (qm->state == 0) { |
309 |
+ dns_transmit_io(&qm->dt, io, deadline); |
310 |
+ qm->state = 1; |
311 |
+ } |
312 |
+ else { |
313 |
+ io->fd = -1; |
314 |
+ io->events = 0; |
315 |
+ } |
316 |
+} |
317 |
+ |
318 |
+int qmerge_get(struct qmerge **x, const iopause_fd *io, const struct taia *when) |
319 |
+{ |
320 |
+ int r; |
321 |
+ struct qmerge *qm; |
322 |
+ |
323 |
+ qm = *x; |
324 |
+ if (qm->state == -1) return -1; /* previous error */ |
325 |
+ if (qm->state == 0) return 0; /* no packet */ |
326 |
+ if (qm->state == 2) return 1; /* already got packet */ |
327 |
+ |
328 |
+ r = dns_transmit_get(&qm->dt, io, when); |
329 |
+ if (r == -1) { qm->state = -1; return -1; } /* error */ |
330 |
+ if (r == 0) { qm->state = 0; return 0; } /* must wait for i/o */ |
331 |
+ if (r == 1) { qm->state = 2; return 1; } /* got packet */ |
332 |
+ return -1; /* bug */ |
333 |
+} |
334 |
diff --git a/qmerge.h b/qmerge.h |
335 |
new file mode 100644 |
336 |
index 0000000..9a58157 |
337 |
--- /dev/null |
338 |
+++ b/qmerge.h |
339 |
@@ -0,0 +1,24 @@ |
340 |
+#ifndef QMERGE_H |
341 |
+#define QMERGE_H |
342 |
+ |
343 |
+#include "dns.h" |
344 |
+ |
345 |
+struct qmerge_key { |
346 |
+ char *q; |
347 |
+ char qtype[2]; |
348 |
+ char *control; |
349 |
+}; |
350 |
+ |
351 |
+struct qmerge { |
352 |
+ int active; |
353 |
+ struct qmerge_key key; |
354 |
+ struct dns_transmit dt; |
355 |
+ int state; /* -1 = error, 0 = need io, 1 = need get, 2 = got packet */ |
356 |
+}; |
357 |
+ |
358 |
+extern int qmerge_start(struct qmerge **,const char *,int,const char *,const char *,const char *,const char *); |
359 |
+extern void qmerge_io(struct qmerge *,iopause_fd *,struct taia *); |
360 |
+extern int qmerge_get(struct qmerge **,const iopause_fd *,const struct taia *); |
361 |
+extern void qmerge_free(struct qmerge **); |
362 |
+ |
363 |
+#endif /* QMERGE_H */ |
364 |
diff --git a/query.c b/query.c |
365 |
index 46cdc00..f091fdd 100644 |
366 |
--- a/query.c |
367 |
+++ b/query.c |
368 |
@@ -81,7 +81,7 @@ static void cleanup(struct query *z) |
369 |
int j; |
370 |
int k; |
371 |
|
372 |
- dns_transmit_free(&z->dt); |
373 |
+ qmerge_free(&z->qm); |
374 |
for (j = 0;j < QUERY_MAXALIAS;++j) |
375 |
dns_domain_free(&z->alias[j]); |
376 |
for (j = 0;j < QUERY_MAXLEVEL;++j) { |
377 |
@@ -429,14 +429,8 @@ static int doit(struct query *z,int state) |
378 |
if (j == 64) goto SERVFAIL; |
379 |
|
380 |
dns_sortip(z->servers[z->level],64); |
381 |
- if (z->level) { |
382 |
- log_tx(z->name[z->level],DNS_T_A,z->control[z->level],z->servers[z->level],z->level); |
383 |
- if (dns_transmit_start(&z->dt,z->servers[z->level],flagforwardonly,z->name[z->level],DNS_T_A,z->localip) == -1) goto DIE; |
384 |
- } |
385 |
- else { |
386 |
- log_tx(z->name[0],z->type,z->control[0],z->servers[0],0); |
387 |
- if (dns_transmit_start(&z->dt,z->servers[0],flagforwardonly,z->name[0],z->type,z->localip) == -1) goto DIE; |
388 |
- } |
389 |
+ dtype = z->level ? DNS_T_A : z->type; |
390 |
+ if (qmerge_start(&z->qm,z->servers[z->level],flagforwardonly,z->name[z->level],dtype,z->localip,z->control[z->level]) == -1) goto DIE; |
391 |
return 0; |
392 |
|
393 |
|
394 |
@@ -450,10 +444,10 @@ static int doit(struct query *z,int state) |
395 |
|
396 |
HAVEPACKET: |
397 |
if (++z->loop == 100) goto DIE; |
398 |
- buf = z->dt.packet; |
399 |
- len = z->dt.packetlen; |
400 |
+ buf = z->qm->dt.packet; |
401 |
+ len = z->qm->dt.packetlen; |
402 |
|
403 |
- whichserver = z->dt.servers + 4 * z->dt.curserver; |
404 |
+ whichserver = z->qm->dt.servers + 4 * z->qm->dt.curserver; |
405 |
control = z->control[z->level]; |
406 |
d = z->name[z->level]; |
407 |
dtype = z->level ? DNS_T_A : z->type; |
408 |
@@ -836,7 +830,7 @@ int query_start(struct query *z,char *dn,char type[2],char class[2],char localip |
409 |
|
410 |
int query_get(struct query *z,iopause_fd *x,struct taia *stamp) |
411 |
{ |
412 |
- switch(dns_transmit_get(&z->dt,x,stamp)) { |
413 |
+ switch(qmerge_get(&z->qm,x,stamp)) { |
414 |
case 1: |
415 |
return doit(z,1); |
416 |
case -1: |
417 |
@@ -847,5 +841,5 @@ int query_get(struct query *z,iopause_fd *x,struct taia *stamp) |
418 |
|
419 |
void query_io(struct query *z,iopause_fd *x,struct taia *deadline) |
420 |
{ |
421 |
- dns_transmit_io(&z->dt,x,deadline); |
422 |
+ qmerge_io(z->qm,x,deadline); |
423 |
} |
424 |
diff --git a/query.h b/query.h |
425 |
index eff68b2..06feab4 100644 |
426 |
--- a/query.h |
427 |
+++ b/query.h |
428 |
@@ -1,7 +1,7 @@ |
429 |
#ifndef QUERY_H |
430 |
#define QUERY_H |
431 |
|
432 |
-#include "dns.h" |
433 |
+#include "qmerge.h" |
434 |
#include "uint32.h" |
435 |
|
436 |
#define QUERY_MAXLEVEL 5 |
437 |
@@ -20,7 +20,7 @@ struct query { |
438 |
char localip[4]; |
439 |
char type[2]; |
440 |
char class[2]; |
441 |
- struct dns_transmit dt; |
442 |
+ struct qmerge *qm; |
443 |
} ; |
444 |
|
445 |
extern int query_start(struct query *,char *,char *,char *,char *); |