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/lib/irs Pull up revisions 1.3-1.4 (requested ...



details:   https://anonhg.NetBSD.org/src/rev/e11237027144
branches:  netbsd-1-6
changeset: 528195:e11237027144
user:      lukem <lukem%NetBSD.org@localhost>
date:      Fri Jun 28 11:46:16 2002 +0000

description:
Pull up revisions 1.3-1.4 (requested by itojun in ticket #387):
Update to BIND 8.3.3.  Fixes buffer overrun in resolver code.

diffstat:

 dist/bind/lib/irs/dns_ho.c |  1175 +++++++++++++++++++++++++++++++++++++++----
 1 files changed, 1056 insertions(+), 119 deletions(-)

diffs (truncated from 1515 to 300 lines):

diff -r 327681b6d89d -r e11237027144 dist/bind/lib/irs/dns_ho.c
--- a/dist/bind/lib/irs/dns_ho.c        Fri Jun 28 11:46:06 2002 +0000
+++ b/dist/bind/lib/irs/dns_ho.c        Fri Jun 28 11:46:16 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dns_ho.c,v 1.2 2001/01/27 07:22:03 itojun Exp $        */
+/*     $NetBSD: dns_ho.c,v 1.2.2.1 2002/06/28 11:46:16 lukem Exp $     */
 
 /*
  * Copyright (c) 1985, 1988, 1993
@@ -54,7 +54,7 @@
 /* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "Id: dns_ho.c,v 1.28 2000/04/20 07:47:54 vixie Exp";
+static const char rcsid[] = "Id: dns_ho.c,v 1.39 2002/06/27 03:56:32 marka Exp";
 #endif /* LIBC_SCCS and not lint */
 
 /* Imports. */
@@ -76,6 +76,7 @@
 #include <resolv.h>
 #include <stdio.h>
 #include <string.h>
+#include <syslog.h>
 
 #include <isc/memcluster.h>
 #include <irs.h>
@@ -96,11 +97,7 @@
 #define        MAXALIASES      35
 #define        MAXADDRS        35
 
-#if PACKETSZ > 1024
-#define        MAXPACKET       PACKETSZ
-#else
-#define        MAXPACKET       1024
-#endif
+#define MAXPACKET (1024*64)
 
 #define BOUNDS_CHECK(ptr, count) \
        if ((ptr) + (count) > eom) { \
@@ -108,6 +105,26 @@
                continue; \
        } else (void)0
 
+typedef union {
+       HEADER hdr;
+       u_char buf[MAXPACKET];
+} querybuf;
+
+struct dns_res_target {
+       struct dns_res_target *next;
+       querybuf qbuf;          /* query buffer */
+       u_char *answer;         /* buffer to put answer */
+       int anslen;             /* size of answer buffer */
+       int qclass, qtype;      /* class and type of query */
+       int action;             /* condition whether query is really issued */
+       char qname[MAXDNAME +1]; /* domain name */
+#if 0
+       int n;                  /* result length */
+#endif
+};
+enum {RESTGT_DOALWAYS, RESTGT_AFTERFAILURE, RESTGT_IGNORE};
+enum {RESQRY_SUCCESS, RESQRY_FAIL};
+
 struct pvt {
        struct hostent  host;
        char *          h_addr_ptrs[MAXADDRS + 1];
@@ -143,14 +160,29 @@
 static void            ho_res_set(struct irs_ho *this,
                                   struct __res_state *res,
                                   void (*free_res)(void *));
+static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name,
+                                    const struct addrinfo *pai);
 
 static void            map_v4v6_hostent(struct hostent *hp, char **bp,
-                                        int *len);
+                                        char *ep);
 static void            addrsort(res_state, char **, int);
 static struct hostent *        gethostans(struct irs_ho *this,
                                   const u_char *ansbuf, int anslen,
                                   const char *qname, int qtype,
-                                  int af, int size);
+                                  int af, int size,
+                                  struct addrinfo **ret_aip,
+                                  const struct addrinfo *pai);
+static int add_hostent(struct pvt *pvt, char *bp, char **hap,
+                      struct addrinfo *ai);
+static const u_char * ar_head(const u_char *, int, const u_char *,
+                             const u_char *, struct pvt *,
+                             int (*)(const char *));
+static struct addrinfo * a6_expand(const u_char *, const u_char *, int,
+                                  const u_char *, const u_char *,
+                                  const struct in6_addr *, int,
+                                  const struct addrinfo *,
+                                  struct pvt *, int (*)(const char *), int *);
+static const char *dname_subst(const char *, const char *, const char *);
 static int             init(struct irs_ho *this);
 
 /* Exports. */
@@ -160,6 +192,8 @@
        struct irs_ho *ho;
        struct pvt *pvt;
 
+       UNUSED(this);
+
        if (!(pvt = memget(sizeof *pvt))) {
                errno = ENOMEM;
                return (NULL);
@@ -182,6 +216,7 @@
        ho->minimize = ho_minimize;
        ho->res_get = ho_res_get;
        ho->res_set = ho_res_set;
+       ho->addrinfo = ho_addrinfo;
        return (ho);
 }
 
@@ -216,29 +251,63 @@
 }
 
 static struct hostent *
-ho_byname2(struct irs_ho *this, const char *name, int af) {
+ho_byname2(struct irs_ho *this, const char *name, int af)
+{
        struct pvt *pvt = (struct pvt *)this->private;
-       int n, size, type;
-       u_char buf[MAXPACKET];
+       struct hostent *hp = NULL;
+       int n, size;
        char tmp[NS_MAXDNAME];
        const char *cp;
+       struct addrinfo ai;
+       struct dns_res_target *q, *q2, *p;
+       int querystate = RESQRY_FAIL;
 
        if (init(this) == -1)
                return (NULL);
 
+       q = memget(sizeof(*q));
+       q2 = memget(sizeof(*q2));
+       if (q == NULL || q2 == NULL) {
+               RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+               errno = ENOMEM;
+               goto cleanup;
+       }
+       memset(q, 0, sizeof(q));
+       memset(q2, 0, sizeof(q2));
+
        switch (af) {
        case AF_INET:
                size = INADDRSZ;
-               type = T_A;
+               q->qclass = C_IN;
+               q->qtype = T_A;
+               q->answer = q->qbuf.buf;
+               q->anslen = sizeof(q->qbuf);
+               q->action = RESTGT_DOALWAYS;
                break;
        case AF_INET6:
                size = IN6ADDRSZ;
-               type = T_AAAA;
+               q->qclass = C_IN;
+               q->qtype = ns_t_a6;
+               q->answer = q->qbuf.buf;
+               q->anslen = sizeof(q->qbuf);
+               q->next = q2;
+#ifdef RES_USE_A6
+               if ((pvt->res->options & RES_USE_A6) == 0)
+                       q->action = RESTGT_IGNORE;
+               else
+#endif
+                       q->action = RESTGT_DOALWAYS;
+               q2->qclass = C_IN;
+               q2->qtype = T_AAAA;
+               q2->answer = q2->qbuf.buf;
+               q2->anslen = sizeof(q2->qbuf);
+               q2->action = RESTGT_AFTERFAILURE;
                break;
        default:
                RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
                errno = EAFNOSUPPORT;
-               return (NULL);
+               hp = NULL;
+               goto cleanup;
        }
 
        /*
@@ -250,30 +319,74 @@
                                                      tmp, sizeof tmp)))
                name = cp;
 
-       if ((n = res_nsearch(pvt->res, name, C_IN, type,
-                            buf, sizeof buf)) < 0)
-               return (NULL);
-       return (gethostans(this, buf, n, name, type, af, size));
+       for (p = q; p; p = p->next) {
+               switch(p->action) {
+               case RESTGT_DOALWAYS:
+                       break;
+               case RESTGT_AFTERFAILURE:
+                       if (querystate == RESQRY_SUCCESS)
+                               continue;
+                       break;
+               case RESTGT_IGNORE:
+                       continue;
+               }
+
+               if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype,
+                                    p->answer, p->anslen)) < 0) {
+                       querystate = RESQRY_FAIL;
+                       continue;
+               }
+
+               memset(&ai, 0, sizeof(ai));
+               ai.ai_family = af;
+               if ((hp = gethostans(this, p->answer, n, name, p->qtype,
+                                    af, size, NULL,
+                                    (const struct addrinfo *)&ai)) != NULL)
+                       goto cleanup;   /* no more loop is necessary */
+
+               querystate = RESQRY_FAIL;
+               continue;
+       }
+
+ cleanup:
+       if (q != NULL)
+               memput(q, sizeof(*q));
+       if (q2 != NULL)
+               memput(q2, sizeof(*q2));
+       return(hp);
 }
 
 static struct hostent *
-ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
+ho_byaddr(struct irs_ho *this, const void *addr, int len, int af)
+{
        struct pvt *pvt = (struct pvt *)this->private;
        const u_char *uaddr = addr;
-       char qbuf[MAXDNAME+1], *qp;
-       u_char buf[MAXPACKET];
-       struct hostent *hp;
+       char *qp;
+       struct hostent *hp = NULL;
+       struct addrinfo ai;
+       struct dns_res_target *q, *q2, *p;
        int n, size;
+       int querystate = RESQRY_FAIL;
        
        if (init(this) == -1)
                return (NULL);
 
+       q = memget(sizeof(*q));
+       q2 = memget(sizeof(*q2));
+       if (q == NULL || q2 == NULL) {
+               RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
+               errno = ENOMEM;
+               goto cleanup;
+       }
+       memset(q, 0, sizeof(q));
+       memset(q2, 0, sizeof(q2));
+
        if (af == AF_INET6 && len == IN6ADDRSZ &&
            (!memcmp(uaddr, mapped, sizeof mapped) ||
            (!memcmp(uaddr, tunnelled, sizeof tunnelled) &&
             memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) {
                /* Unmap. */
-               addr = (char *)addr + sizeof mapped;
+               addr = (const char *)addr + sizeof mapped;
                uaddr += sizeof mapped;
                af = AF_INET;
                len = INADDRSZ;
@@ -281,65 +394,137 @@
        switch (af) {
        case AF_INET:
                size = INADDRSZ;
+               q->qclass = C_IN;
+               q->qtype = T_PTR;
+               q->answer = q->qbuf.buf;
+               q->anslen = sizeof(q->qbuf);
+               q->action = RESTGT_DOALWAYS;
                break;
        case AF_INET6:
                size = IN6ADDRSZ;
+               q->qclass = C_IN;
+               q->qtype = T_PTR;
+               q->answer = q->qbuf.buf;
+               q->anslen = sizeof(q->qbuf);
+               q->next = q2;
+               q->action = RESTGT_DOALWAYS;
+               q2->qclass = C_IN;
+               q2->qtype = T_PTR;
+               q2->answer = q2->qbuf.buf;
+               q2->anslen = sizeof(q2->qbuf);
+               if ((pvt->res->options & RES_NO_NIBBLE2) != 0)
+                       q2->action = RESTGT_IGNORE;
+               else
+                       q2->action = RESTGT_AFTERFAILURE;
                break;
        default:
                errno = EAFNOSUPPORT;
                RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
-               return (NULL);



Home | Main Index | Thread Index | Old Index