From e0a6abbdb983849f73da5047849a7ae7f3005c48 Mon Sep 17 00:00:00 2001 From: schmonz Date: Wed, 22 Apr 2009 04:48:13 +0000 Subject: Add DJB's patch to fix the axfrdns bug reported by Matthew Dempsky, described here: http://article.gmane.org/gmane.network.djbdns/13864 Add mutually exclusive options, both by Jeff King, to address the dnscache poisoning weaknesses described in CVE-2008-4392: * "djbdns-qmerge1" (from http://www.your.org/dnscache/) * "djbdns-qmerge2" (from http://article.gmane.org/gmane.network.djbdns/13965) Both options are included because qmerge1 is better tested but has known shortcomings, while qmerge2 is probably more correct but (as yet) less well tested. Bump PKGREVISION. --- net/djbdns/files/patch-qmerge2 | 254 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 net/djbdns/files/patch-qmerge2 (limited to 'net/djbdns/files') diff --git a/net/djbdns/files/patch-qmerge2 b/net/djbdns/files/patch-qmerge2 new file mode 100644 index 00000000000..c78e2d1a126 --- /dev/null +++ b/net/djbdns/files/patch-qmerge2 @@ -0,0 +1,254 @@ +--- clients.h.orig 2009-04-21 23:43:02.000000000 -0400 ++++ clients.h +@@ -0,0 +1,7 @@ ++#ifndef CLIENTS_H ++#define CLIENTS_H ++ ++#define MAXUDP 200 ++#define MAXTCP 20 ++ ++#endif /* CLIENTS_H */ +--- dns.h.orig 2001-02-11 16:11:45.000000000 -0500 ++++ dns.h +@@ -4,6 +4,7 @@ + #include "stralloc.h" + #include "iopause.h" + #include "taia.h" ++#include "clients.h" + + #define DNS_C_IN "\0\1" + #define DNS_C_ANY "\0\377" +@@ -37,8 +38,14 @@ struct dns_transmit { + const char *servers; + char localip[4]; + char qtype[2]; ++ struct dns_transmit *master; ++ struct dns_transmit *slaves[MAXUDP]; ++ int nslaves; + } ; + ++extern void dns_enable_merge(void (*logger)(const char *, const char *, ++ const char *)); ++ + extern void dns_random_init(const char *); + extern unsigned int dns_random(unsigned int); + +--- dns_transmit.c.orig 2001-02-11 16:11:45.000000000 -0500 ++++ dns_transmit.c +@@ -7,6 +7,61 @@ + #include "byte.h" + #include "uint16.h" + #include "dns.h" ++#include "strerr.h" ++ ++static int merge_enable; ++static void (*merge_logger)(const char *, const char *, const char *); ++void dns_enable_merge(void (*f)(const char *, const char *, const char *)) ++{ ++ merge_enable = 1; ++ merge_logger = f; ++} ++ ++static int merge_equal(struct dns_transmit *a, struct dns_transmit *b) ++{ ++ const char *ip1 = a->servers + 4 * a->curserver; ++ const char *ip2 = b->servers + 4 * b->curserver; ++ return ++ byte_equal(ip1, 4, ip2) && ++ byte_equal(a->qtype, 2, b->qtype) && ++ dns_domain_equal(a->query + 14, b->query + 14); ++} ++ ++struct dns_transmit *inprogress[MAXUDP]; ++ ++static int try_merge(struct dns_transmit *d) ++{ ++ int i; ++ for (i = 0; i < MAXUDP; i++) { ++ if (!inprogress[i]) continue; ++ if (!merge_equal(d, inprogress[i])) continue; ++ d->master = inprogress[i]; ++ inprogress[i]->slaves[inprogress[i]->nslaves++] = d; ++ return 1; ++ } ++ return 0; ++} ++ ++static void register_inprogress(struct dns_transmit *d) ++{ ++ int i; ++ for (i = 0; i < MAXUDP; i++) { ++ if (!inprogress[i]) { ++ inprogress[i] = d; ++ return; ++ } ++ } ++ strerr_die1x(100, "BUG: out of inprogress slots"); ++} ++ ++static void unregister_inprogress(struct dns_transmit *d) ++{ ++ int i; ++ for (i = 0; i < MAXUDP; i++) { ++ if (inprogress[i] == d) ++ inprogress[i] = 0; ++ } ++} + + static int serverwantstcp(const char *buf,unsigned int len) + { +@@ -59,8 +114,28 @@ static void packetfree(struct dns_transm + d->packet = 0; + } + ++static void mergefree(struct dns_transmit *d) ++{ ++ int i; ++ if (merge_enable) ++ unregister_inprogress(d); ++ /* unregister us from our master */ ++ if (d->master) { ++ for (i = 0; i < d->master->nslaves; i++) ++ if (d->master->slaves[i] == d) ++ d->master->slaves[i] = 0; ++ } ++ /* and unregister all of our slaves from us */ ++ for (i = 0; i < d->nslaves; i++) { ++ if (d->slaves[i]) ++ d->slaves[i]->master = NULL; ++ } ++ d->nslaves = 0; ++} ++ + static void queryfree(struct dns_transmit *d) + { ++ mergefree(d); + if (!d->query) return; + alloc_free(d->query); + d->query = 0; +@@ -99,11 +174,18 @@ static int thisudp(struct dns_transmit * + const char *ip; + + socketfree(d); ++ mergefree(d); + + while (d->udploop < 4) { + for (;d->curserver < 16;++d->curserver) { + ip = d->servers + 4 * d->curserver; + if (byte_diff(ip,4,"\0\0\0\0")) { ++ if (merge_enable && try_merge(d)) { ++ if (merge_logger) ++ merge_logger(ip, d->qtype, d->query + 14); ++ return 0; ++ } ++ + d->query[2] = dns_random(256); + d->query[3] = dns_random(256); + +@@ -118,6 +200,8 @@ static int thisudp(struct dns_transmit * + taia_uint(&d->deadline,timeouts[d->udploop]); + taia_add(&d->deadline,&d->deadline,&now); + d->tcpstate = 0; ++ if (merge_enable) ++ register_inprogress(d); + return 0; + } + +@@ -226,8 +310,12 @@ void dns_transmit_io(struct dns_transmit + x->fd = d->s1 - 1; + + switch(d->tcpstate) { +- case 0: case 3: case 4: case 5: +- x->events = IOPAUSE_READ; ++ case 0: ++ if (d->master) return; ++ if (d->packet) { taia_now(deadline); return; } ++ /* otherwise, fall through */ ++ case 3: case 4: case 5: ++ x->events = IOPAUSE_READ; + break; + case 1: case 2: + x->events = IOPAUSE_WRITE; +@@ -244,10 +332,14 @@ int dns_transmit_get(struct dns_transmit + unsigned char ch; + int r; + int fd; ++ int i; + + errno = error_io; + fd = d->s1 - 1; + ++ if (d->tcpstate == 0 && d->master) return 0; ++ if (d->tcpstate == 0 && d->packet) return 1; ++ + if (!x->revents) { + if (taia_less(when,&d->deadline)) return 0; + errno = error_timeout; +@@ -279,6 +371,15 @@ have sent query to curserver on UDP sock + d->packet = alloc(d->packetlen); + if (!d->packet) { dns_transmit_free(d); return -1; } + byte_copy(d->packet,d->packetlen,udpbuf); ++ ++ for (i = 0; i < d->nslaves; i++) { ++ if (!d->slaves[i]) continue; ++ d->slaves[i]->packetlen = d->packetlen; ++ d->slaves[i]->packet = alloc(d->packetlen); ++ if (!d->slaves[i]->packet) { dns_transmit_free(d->slaves[i]); continue; } ++ byte_copy(d->slaves[i]->packet,d->packetlen,udpbuf); ++ } ++ + queryfree(d); + return 1; + } +--- dnscache.c.orig 2001-02-11 16:11:45.000000000 -0500 ++++ dnscache.c +@@ -54,7 +54,6 @@ uint64 numqueries = 0; + + static int udp53; + +-#define MAXUDP 200 + static struct udpclient { + struct query q; + struct taia start; +@@ -131,7 +130,6 @@ void u_new(void) + + static int tcp53; + +-#define MAXTCP 20 + struct tcpclient { + struct query q; + struct taia start; +@@ -435,6 +433,8 @@ int main() + response_hidettl(); + if (env_get("FORWARDONLY")) + query_forwardonly(); ++ if (env_get("MERGEQUERIES")) ++ dns_enable_merge(log_merge); + + if (!roots_init()) + strerr_die2sys(111,FATAL,"unable to read servers: "); +--- log.c.orig 2001-02-11 16:11:45.000000000 -0500 ++++ log.c +@@ -150,6 +150,12 @@ void log_tx(const char *q,const char qty + line(); + } + ++void log_merge(const char *addr, const char qtype[2], const char *q) ++{ ++ string("merge "); ip(addr); space(); logtype(qtype); space(); name(q); ++ line(); ++} ++ + void log_cachedanswer(const char *q,const char type[2]) + { + string("cached "); logtype(type); space(); +--- log.h.orig 2001-02-11 16:11:45.000000000 -0500 ++++ log.h +@@ -18,6 +18,7 @@ extern void log_cachednxdomain(const cha + extern void log_cachedns(const char *,const char *); + + extern void log_tx(const char *,const char *,const char *,const char *,unsigned int); ++extern void log_merge(const char *, const char *, const char *); + + extern void log_nxdomain(const char *,const char *,unsigned int); + extern void log_nodata(const char *,const char *,const char *,unsigned int); -- cgit v1.2.3