From 557072655748be14a747242135f1b34eff9f735f Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 9 May 1996 15:59:18 +0000 Subject: * resolv: Code updated from BIND-4.9.3P2C3. --- resolv/gethnamaddr.c | 24 +++++++++++---- resolv/getnetbyaddr.c | 2 +- resolv/getnetent.c | 21 +++++++------ resolv/getnetnamadr.c | 6 ++-- resolv/netdb.h | 2 +- resolv/res_comp.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++-- resolv/res_debug.c | 37 ++++++++++++++-------- resolv/res_send.c | 27 +++++++++++++--- resolv/resolv.h | 6 +++- 9 files changed, 167 insertions(+), 43 deletions(-) (limited to 'resolv') diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c index 41be4fc10d..6872be0b7e 100644 --- a/resolv/gethnamaddr.c +++ b/resolv/gethnamaddr.c @@ -158,10 +158,21 @@ getanswer(answer, anslen, qname, qclass, qtype) int toobig = 0; char tbuf[MAXDNAME+1]; const char *tname; + int (*name_ok) __P((const char *)); tname = qname; host.h_name = NULL; eom = answer->buf + anslen; + switch (qtype) { + case T_A: + name_ok = res_hnok; + break; + case T_PTR: + name_ok = dn_isvalid; + break; + default: + abort(); + } /* * find first satisfactory answer */ @@ -175,7 +186,8 @@ getanswer(answer, anslen, qname, qclass, qtype) h_errno = NO_RECOVERY; return (NULL); } - if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) { + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if ((n < 0) || !(*name_ok)(bp)) { h_errno = NO_RECOVERY; return (NULL); } @@ -204,7 +216,7 @@ getanswer(answer, anslen, qname, qclass, qtype) had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { n = dn_expand(answer->buf, eom, cp, bp, buflen); - if (n < 0) { + if ((n < 0) || !(*name_ok)(bp)) { had_error++; continue; } @@ -224,7 +236,7 @@ getanswer(answer, anslen, qname, qclass, qtype) if (ap >= &host_aliases[MAXALIASES-1]) continue; n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); - if (n < 0) { + if ((n < 0) || !(*name_ok)(tbuf)) { had_error++; continue; } @@ -254,7 +266,7 @@ getanswer(answer, anslen, qname, qclass, qtype) } if (qtype == T_PTR && type == T_CNAME) { n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); - if (n < 0) { + if ((n < 0) || !res_hnok(tbuf)) { had_error++; continue; } @@ -288,7 +300,7 @@ getanswer(answer, anslen, qname, qclass, qtype) continue; /* XXX - had_error++ ? */ } n = dn_expand(answer->buf, eom, cp, bp, buflen); - if (n < 0) { + if ((n < 0) || !res_hnok(bp)) { had_error++; break; } @@ -517,7 +529,7 @@ gethostbyaddr(addr, len, type) h_errno = NETDB_INTERNAL; return (NULL); } - if (type != AF_INET) { + if (type != AF_INET || len != INADDRSZ) { errno = EAFNOSUPPORT; h_errno = NETDB_INTERNAL; return (NULL); diff --git a/resolv/getnetbyaddr.c b/resolv/getnetbyaddr.c index 3bc01addb6..32513cc387 100644 --- a/resolv/getnetbyaddr.c +++ b/resolv/getnetbyaddr.c @@ -42,7 +42,7 @@ extern int _net_stayopen; struct netent * _getnetbyaddr(net, type) - register long net; + register unsigned long net; register int type; { register struct netent *p; diff --git a/resolv/getnetent.c b/resolv/getnetent.c index fb47c30c99..7ec5607781 100644 --- a/resolv/getnetent.c +++ b/resolv/getnetent.c @@ -143,18 +143,19 @@ again: net.n_net = inet_network(cp); net.n_addrtype = AF_INET; q = net.n_aliases = net_aliases; - if (p != NULL) + if (p != NULL) { cp = p; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &net_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; } - if (q < &net_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; } *q = NULL; return (&net); diff --git a/resolv/getnetnamadr.c b/resolv/getnetnamadr.c index b2c911844e..fad2b8c0cd 100644 --- a/resolv/getnetnamadr.c +++ b/resolv/getnetnamadr.c @@ -139,7 +139,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1]; haveanswer = 0; while (--ancount >= 0 && cp < eom) { n = dn_expand(answer->buf, eom, cp, bp, buflen); - if (n < 0) + if ((n < 0) || !dn_isvalid(bp)) break; cp += n; ans[0] = '\0'; @@ -150,7 +150,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1]; GETSHORT(n, cp); if (class == C_IN && type == T_PTR) { n = dn_expand(answer->buf, eom, cp, bp, buflen); - if (n < 0) { + if ((n < 0) || !res_hnok(bp)) { cp += n; return (NULL); } @@ -202,7 +202,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1]; struct netent * getnetbyaddr(net, net_type) - register long net; + register u_long net; register int net_type; { unsigned int netbr[4]; diff --git a/resolv/netdb.h b/resolv/netdb.h index 822b621363..fd06e17bb4 100644 --- a/resolv/netdb.h +++ b/resolv/netdb.h @@ -135,7 +135,7 @@ struct hostent *gethostbyaddr __P((const char *, int, int)); struct hostent *gethostbyname __P((const char *)); struct hostent *gethostbyname2 __P((const char *, int)); struct hostent *gethostent __P((void)); -struct netent *getnetbyaddr __P((long, int)); /* u_long? */ +struct netent *getnetbyaddr __P((unsigned long, int)); struct netent *getnetbyname __P((const char *)); struct netent *getnetent __P((void)); struct protoent *getprotobyname __P((const char *)); diff --git a/resolv/res_comp.c b/resolv/res_comp.c index 1342205f28..f234772e41 100644 --- a/resolv/res_comp.c +++ b/resolv/res_comp.c @@ -148,9 +148,6 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length) } } *dn = '\0'; - for (dn = exp_dn; (c = *dn) != '\0'; dn++) - if (isascii(c) && isspace(c)) - return (-1); if (len < 0) len = cp - comp_dn; return (len); @@ -339,6 +336,88 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr) return (-1); } +/* + * Verify that a domain name uses an acceptable character set. + */ + +/**** +To: "Lawrence R. Rogers" +cc: cert@cert.org, pvm@home.net +Subject: Re: VU#14542 +In-reply-to: Your message of "Mon, 19 Feb 1996 17:16:27 PST." +Date: Tue, 20 Feb 1996 22:37:21 -0800 +From: Paul A Vixie + +in retrospect, + + hostname = firstlabel ( "." otherlabel )+ + firstchar = [a-zA-Z0-9_] + otherchar = [a-zA-Z0-9_-/] + firstlabel = firstchar otherchar* + otherlabel = otherchar+ + +should have been + + hostname = label ( "." label )+ + firstchar = [a-zA-Z0-9_] + otherchar = [a-zA-Z0-9_-] + label = firstchar otherchar* + +i know of no example of a real host name that needs the looser rule i sent +earlier. since i'm only trying to bend the spec to fit actual known uses, +i should not have widened the rules as far as i did earlier. +****/ + +#define firstchar(c) ((isascii(c) && isalnum(c)) || (c) == '_') +#define otherchar(c) (firstchar(c) || (c) == '-') +#define wildlabel(firstlabel, ch, nch) \ + ((firstlabel) && (ch) == '*' && ((nch) == '.' || (nch) == '\0')) + +int +res_hnok(dn) + const char *dn; +{ + int ppch = '\0', pch = '.', ch = *dn++, firstlabel = 1; + + while (ch != '\0') { + int nch = *dn++; + + if (ch == '.' || (ch == '\\' && nch == '.')) { + NULL; + } else if (pch == '.' && ppch != '\\') { + if (!firstchar(ch) && !wildlabel(firstlabel, ch, nch)) + return (0); + } else { + if (!otherchar(ch)) + return (0); + } + ppch = pch, pch = ch, ch = nch; + firstlabel = 0; + } + return (1); +} + +/* + * This function is quite liberal, since RFC 1034's character sets are only + * recommendations. + * + * Note that some char's are signed, so we have to cast to unsigned. + */ +int +dn_isvalid(dn) + const char *dn; +{ + unsigned char *t = (unsigned char *)dn; + int ch; + + while ((ch = *t++) != '\0') + if (ch <= 0x1f || ch >= 0x7f) { + /* Unprintable in ASCII. */ + return (0); + } + return (1); +} + /* * Routines to insert/extract short/long's. */ diff --git a/resolv/res_debug.c b/resolv/res_debug.c index b3dfcdf8f6..85ec628b89 100644 --- a/resolv/res_debug.c +++ b/resolv/res_debug.c @@ -502,16 +502,28 @@ __p_rr(cp, msg, file) case T_HINFO: case T_ISDN: + (void) fputs("\t\"", file); cp2 = cp + dlen; - if (n = *cp++) { - fprintf(file, "\t%.*s", n, cp); - cp += n; + if ((n = (unsigned char) *cp++) != 0) { + for (c = n; c > 0 && cp < cp2; c--) { + if (strchr("\n\"\\", *cp)) + (void) putc('\\', file); + (void) putc(*cp++, file); + } + putc('"', file); } - if ((cp < cp2) && (n = *cp++)) { - fprintf(file, "\t%.*s", n, cp); - cp += n; - } else if (type == T_HINFO) + if (cp < cp2 && (n = (unsigned char) *cp++) != 0) { + (void) fputs ("\t\"", file); + for (c = n; c > 0 && cp < cp2; c--) { + if (strchr("\n\"\\", *cp)) + (void) putc('\\', file); + (void) putc(*cp++, file); + } + putc('"', file); + } else if (type == T_HINFO) { + (void) fputs("\"?\"", file); fprintf(file, "\n;; *** Warning *** OS-type missing"); + } break; case T_SOA: @@ -563,12 +575,11 @@ __p_rr(cp, msg, file) cp2 = cp1 + dlen; while (cp < cp2) { if (n = (unsigned char) *cp++) { - for (c = n; c > 0 && cp < cp2; c--) - if ((*cp == '\n') || (*cp == '"')) { - (void) putc('\\', file); - (void) putc(*cp++, file); - } else - (void) putc(*cp++, file); + for (c = n; c > 0 && cp < cp2; c--) { + if (strchr("\n\"\\", *cp)) + (void) putc('\\', file); + (void) putc(*cp++, file); + } } } putc('"', file); diff --git a/resolv/res_send.c b/resolv/res_send.c index 5a10faa393..d2c97d0cd4 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -409,6 +409,7 @@ res_send(buf, buflen, ans, anssiz) /* * Receive length & response */ +read_len: cp = ans; len = INT16SZ; while ((n = read(s, (char *)cp, (int)len)) > 0) { @@ -477,6 +478,20 @@ res_send(buf, buflen, ans, anssiz) break; } } + /* + * The calling applicating has bailed out of + * a previous call and failed to arrange to have + * the circuit closed or the server has got + * itself confused. Anyway drop the packet and + * wait for the correct one. + */ + if (hp->id != anhp->id) { + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; old answer (unexpected):\n"), + ans, (resplen>anssiz)?anssiz:resplen); + goto read_len; + } } else { /* * Use datagrams. @@ -593,6 +608,8 @@ res_send(buf, buflen, ans, anssiz) n = select(s+1, &dsmask, (fd_set *)NULL, (fd_set *)NULL, &timeout); if (n < 0) { + if (errno == EINTR) + goto wait; Perror(stderr, "select", errno); _res_close(); goto next_ns; @@ -626,7 +643,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; old answer:\n"), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); goto wait; } #if CHECK_SRVR_ADDR @@ -640,7 +657,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; not our server:\n"), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); goto wait; } #endif @@ -655,7 +672,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; wrong query name:\n"), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); goto wait; } if (anhp->rcode == SERVFAIL || @@ -663,7 +680,7 @@ res_send(buf, buflen, ans, anssiz) anhp->rcode == REFUSED) { DprintQ(_res.options & RES_DEBUG, (stdout, "server rejected query:\n"), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); badns |= (1 << ns); _res_close(); /* don't retry if called from dig */ @@ -689,7 +706,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ""), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); /* * If using virtual circuits, we assume that the first server * is preferred over the rest (i.e. it is on the local diff --git a/resolv/resolv.h b/resolv/resolv.h index fb3de282b2..1a4a0dec89 100644 --- a/resolv/resolv.h +++ b/resolv/resolv.h @@ -78,7 +78,7 @@ * is new enough to contain a certain feature. */ -#define __RES 19951031 +#define __RES 19960229 /* * Resolver configuration file. @@ -184,6 +184,8 @@ typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr_in *ns, extern struct __res_state _res; /* Private routines shared between libc/net, named, nslookup and others. */ +#define res_hnok __res_hnok +#define dn_isvalid __dn_isvalid #define dn_skipname __dn_skipname #define fp_query __fp_query #define fp_nquery __fp_nquery @@ -203,6 +205,8 @@ extern struct __res_state _res; #define res_nameinquery __res_nameinquery #define res_queriesmatch __res_queriesmatch __BEGIN_DECLS +int __res_hnok __P((const char *)); +int __dn_isvalid __P((const char *)); int __dn_skipname __P((const u_char *, const u_char *)); void __fp_resstat __P((struct __res_state *, FILE *)); void __fp_query __P((const u_char *, FILE *)); -- cgit v1.2.3