Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-6]: src/dist/bind/bin/named Pull up revision 1.5 (requested by ...
details: https://anonhg.NetBSD.org/src/rev/40728d4f6b12
branches: netbsd-1-6
changeset: 528149:40728d4f6b12
user: lukem <lukem%NetBSD.org@localhost>
date: Fri Jun 28 11:34:35 2002 +0000
description:
Pull up revision 1.5 (requested by itojun in ticket #387):
Update to BIND 8.3.3. Fixes buffer overrun in resolver code.
diffstat:
dist/bind/bin/named/ns_req.c | 568 +++++++++++++++++++++++++++++++++---------
1 files changed, 446 insertions(+), 122 deletions(-)
diffs (truncated from 970 to 300 lines):
diff -r 94f7c6053502 -r 40728d4f6b12 dist/bind/bin/named/ns_req.c
--- a/dist/bind/bin/named/ns_req.c Fri Jun 28 11:34:16 2002 +0000
+++ b/dist/bind/bin/named/ns_req.c Fri Jun 28 11:34:35 2002 +0000
@@ -1,8 +1,8 @@
-/* $NetBSD: ns_req.c,v 1.4 2001/05/17 22:59:40 itojun Exp $ */
+/* $NetBSD: ns_req.c,v 1.4.2.1 2002/06/28 11:34:35 lukem Exp $ */
#if !defined(lint) && !defined(SABER)
static const char sccsid[] = "@(#)ns_req.c 4.47 (Berkeley) 7/1/91";
-static const char rcsid[] = "Id: ns_req.c,v 8.138.2.1 2001/04/27 07:44:05 marka Exp";
+static const char rcsid[] = "Id: ns_req.c,v 8.169 2002/05/12 23:41:52 marka Exp";
#endif /* not lint */
/*
@@ -155,11 +155,11 @@
int *buflenp, int *msglenp,
u_char *msg, int dfd, int *ra,
struct sockaddr_in from,
- struct tsig_record *in_tsig);
+ struct tsig_record *in_tsig,
+ u_int16_t udpsize);
static enum req_action req_iquery(HEADER *hp, u_char **cpp, u_char *eom,
- int *buflenp, u_char *msg,
- struct sockaddr_in from);
+ int *buflenp, struct sockaddr_in from);
#ifdef BIND_NOTIFY
static enum req_action req_notify(HEADER *hp, u_char **cpp, u_char *eom,
@@ -167,6 +167,118 @@
#endif
/*
+ * See if there is a OPT record at the end of the message.
+ *
+ * Results:
+ * -1 FORMERR
+ * 0 last RR is not a OPT record
+ * n>0 lenght of OPT record
+ */
+int
+ns_get_opt(u_char *msg, u_char *eom,
+ u_int8_t *versionp, u_int16_t *rcodep, u_int16_t *flagp,
+ u_int16_t *bufsizep, u_char **optionsp, size_t *optsizep)
+{
+ HEADER *hp = (HEADER *) msg;
+ u_char *start, *options, *cp;
+ u_int8_t version;
+ u_int16_t rdlen, type, bufsize, flags, optsize, rcode;
+ int i, n, root;
+
+ if (msg == NULL || eom == NULL || (msg + HFIXEDSZ) > eom)
+ return (-1);
+
+ if (ntohs(hp->arcount) == 0)
+ return (0);
+
+ cp = msg + HFIXEDSZ;
+ n = ns_skiprr(cp, eom, ns_s_qd, ntohs(hp->qdcount));
+ if (n < 0)
+ return (-1);
+ cp += n;
+ n = ns_skiprr(cp, eom, ns_s_an, ntohs(hp->ancount));
+ if (n < 0)
+ return (-1);
+ cp += n;
+ n = ns_skiprr(cp, eom, ns_s_ns, ntohs(hp->nscount));
+ if (n < 0)
+ return (-1);
+ cp += n;
+ i = ntohs(hp->arcount);
+ while (i-- > 0) {
+ start = cp;
+ if (cp >= eom)
+ return (-1);
+ root = (*cp == 0);
+ n = dn_skipname(cp, eom);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + (2 + 2 + 4 + 2) > eom)
+ return (-1);
+ GETSHORT(type, cp);
+ if (type != ns_t_opt) {
+ cp += INT16SZ + INT32SZ; /* class, ttl */
+ GETSHORT(rdlen, cp);
+ if (cp + rdlen > eom)
+ return (-1);
+ cp += rdlen;
+ continue;
+ }
+ /* We have the OPT record. Check it out in detail. */
+ if (!root)
+ return (-1);
+ GETSHORT(bufsize, cp);
+ rcode = (*cp++ <<4) + hp->rcode ;
+ version = *cp++;
+ GETSHORT(flags, cp);
+ GETSHORT(rdlen, cp);
+ if (cp + rdlen > eom)
+ return (-1);
+ options = cp;
+ optsize = rdlen;
+ if (versionp != NULL)
+ *versionp = version;
+ if (rcodep != NULL)
+ *rcodep = rcode;
+ if (flagp != NULL)
+ *flagp = flags;
+ if (bufsizep != NULL)
+ *bufsizep = bufsize;
+ if (optionsp != NULL)
+ *optionsp = options;
+ if (optsizep != NULL)
+ *optsizep = optsize;
+ return (cp - start);
+ }
+ /* OPT not found */
+ return (0);
+}
+
+int
+ns_add_opt(u_char *msg, u_char *cp, size_t buflen, u_int8_t version,
+ u_int16_t rcode, u_int16_t size, u_int16_t flags,
+ u_char *options, size_t optlen)
+{
+ HEADER *hp = (HEADER *) msg;
+
+ if ((cp + 1 + 2 + 2 + 4 + 2 + optlen) > (msg + buflen))
+ return (-1);
+
+ *cp++ = 0; /* "." */
+ PUTSHORT(ns_t_opt, cp); /* type */
+ PUTSHORT(size, cp); /* class (udp size) */
+ *cp++ = (rcode >> 4) & 0xff; /* ttl (rcode + version + flags) */
+ hp->rcode = rcode & 0xf;
+ *cp++ = version;
+ PUTSHORT(flags, cp);
+ PUTSHORT(optlen, cp); /* rdlen */
+ memcpy(cp, options, optlen); /* options */
+ hp->arcount = htons(ntohs(hp->arcount) + 1);
+ return (1 + 2 + 2 + 4 + 2 + optlen);
+}
+
+/*
* Process request using database; assemble and send response.
*/
void
@@ -175,8 +287,8 @@
{
HEADER *hp = (HEADER *) msg;
u_char *cp, *eom;
- enum req_action action;
- int n, ra, has_tsig, tsig_size, sig2len;
+ enum req_action action = Return;
+ int n, ra, has_tsig, tsig_size = 0, opt_size = 0, sig2len;
u_char *tsigstart;
u_char sig[TSIG_SIG_SIZE], sig2[TSIG_SIG_SIZE];
struct tsig_record *in_tsig = NULL;
@@ -184,8 +296,14 @@
int msglen_orig = msglen;
int buflen_orig = buflen;
int siglen = sizeof sig;
- DST_KEY *key;
+ DST_KEY *key = NULL;
time_t tsig_time;
+ int opt = 0;
+ u_int8_t version = 0;
+ u_int16_t rcode = ns_r_noerror;
+ u_int16_t udpsize = 0;
+ int drop;
+ int tsig_adjust = 0;
#ifdef DEBUG
if (debug > 3) {
@@ -194,18 +312,30 @@
}
#endif
+ drop = drop_port(ntohs(from.sin_port));
+ if (qsp == NULL && drop == 1)
+ return;
+
tsigstart = ns_find_tsig(msg, msg + msglen);
if (tsigstart == NULL)
has_tsig = 0;
else {
char buf[MAXDNAME];
+ u_char tmp[NS_MAXCDNAME];
has_tsig = 1;
- n = dn_expand(msg, msg + msglen, tsigstart, buf, sizeof buf);
+ n = ns_name_unpack(msg, msg + msglen, tsigstart,
+ tmp, sizeof tmp);
+ if (n > 0) {
+ tsig_adjust = dn_skipname(tmp, tmp + sizeof(tmp)) - n;
+ if (ns_name_ntop(tmp, buf, sizeof buf) == -1)
+ n = -1;
+ else if (buf[0] == '.')
+ buf[0] = '\0';
+ }
if (n < 0) {
ns_debug(ns_log_default, 1,
- "ns_req: bad TSIG key name",
- buf);
+ "ns_req: bad TSIG key name");
error = ns_r_formerr;
hp->rcode = ns_r_formerr;
key = NULL;
@@ -263,6 +393,8 @@
in_tsig->siglen = siglen;
memcpy(in_tsig->sig, sig, siglen);
tsig_size = msglen_orig - msglen;
+ /* AXFR/IXFR need the uncompressed tsig size. */
+ in_tsig->tsig_size = tsig_size + tsig_adjust;
} else if (has_tsig) {
action = Finish;
in_tsig = memget(sizeof(struct tsig_record));
@@ -271,6 +403,7 @@
in_tsig->key = NULL;
in_tsig->siglen = 0;
tsig_size = msg + msglen - tsigstart;
+ in_tsig->tsig_size = tsig_size;
msglen = tsigstart - msg;
}
@@ -278,6 +411,30 @@
nsid_hash((u_char *)&tt, sizeof(tt));
nsid_hash(msg, (msglen > 512) ? 512 : msglen);
+ if (error == NOERROR) {
+
+ opt = ns_get_opt(msg, msg + msglen, &version,
+ NULL, NULL, &udpsize, NULL, NULL);
+ if (opt < 0) {
+ rcode = ns_r_formerr;
+ action = Finish;
+ } else if (opt == 0) {
+ if (qsp == NULL && buflen > PACKETSZ)
+ buflen_orig = buflen = PACKETSZ;
+ } else if (opt > 0) {
+ if (version != 0) {
+ rcode = ns_r_badvers;
+ action = Finish;
+ }
+ opt_size = 11;
+ if (udpsize < 512)
+ udpsize = 512;
+ if (qsp == NULL && buflen > udpsize)
+ buflen_orig = buflen = udpsize;
+ }
+ } else if (qsp == NULL && buflen > PACKETSZ)
+ buflen_orig = buflen = PACKETSZ;
+
/*
* It's not a response so these bits have no business
* being set. will later simplify work if we can
@@ -293,6 +450,8 @@
if (error == NOERROR)
hp->rcode = ns_r_noerror;
+ if (rcode == ns_r_noerror)
+ rcode = hp->rcode;
cp = msg + HFIXEDSZ;
eom = msg + msglen;
buflen -= HFIXEDSZ;
@@ -300,16 +459,17 @@
free_addinfo(); /* sets addcount to zero */
dnptrs[0] = NULL;
- if (error == NOERROR) {
+ if (error == NOERROR && rcode == ns_r_noerror) {
switch (hp->opcode) {
case ns_o_query:
action = req_query(hp, &cp, eom, qsp,
&buflen, &msglen,
- msg, dfd, &ra, from, in_tsig);
+ msg, dfd, &ra, from,
+ in_tsig, udpsize);
break;
case ns_o_iquery:
- action = req_iquery(hp, &cp, eom, &buflen, msg, from);
+ action = req_iquery(hp, &cp, eom, &buflen, from);
break;
#ifdef BIND_NOTIFY
@@ -320,8 +480,7 @@
#ifdef BIND_UPDATE
case ns_o_update:
- action = req_update(hp, cp, eom, msg, qsp, dfd, from,
- in_tsig);
+ action = req_update(hp, cp, eom, msg, from, in_tsig);
break;
#endif /* BIND_UPDATE */
@@ -337,6 +496,7 @@
hp->rcode = ns_r_notimpl;
action = Finish;
Home |
Main Index |
Thread Index |
Old Index