diff options
Diffstat (limited to 'contrib/bind/bin/named/ns_req.c')
-rw-r--r-- | contrib/bind/bin/named/ns_req.c | 131 |
1 files changed, 78 insertions, 53 deletions
diff --git a/contrib/bind/bin/named/ns_req.c b/contrib/bind/bin/named/ns_req.c index 75d688f..f103ad6 100644 --- a/contrib/bind/bin/named/ns_req.c +++ b/contrib/bind/bin/named/ns_req.c @@ -1,6 +1,6 @@ #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.119 2000/08/21 05:57:09 vixie Exp $"; +static const char rcsid[] = "$Id: ns_req.c,v 8.129 2001/01/08 23:46:41 marka Exp $"; #endif /* not lint */ /* @@ -174,11 +174,14 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp, HEADER *hp = (HEADER *) msg; u_char *cp, *eom; enum req_action action; - int n, ra, has_tsig, msglen_orig, tsig_size, siglen, sig2len; + int n, ra, has_tsig, tsig_size, sig2len; u_char *tsigstart; u_char sig[TSIG_SIG_SIZE], sig2[TSIG_SIG_SIZE]; struct tsig_record *in_tsig = NULL; int error = NOERROR; + int msglen_orig = msglen; + int buflen_orig = buflen; + int siglen = sizeof sig; DST_KEY *key; time_t tsig_time; @@ -188,8 +191,6 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp, fp_nquery(msg, msglen, log_get_stream(packet_channel)); } #endif - msglen_orig = msglen; - siglen = sizeof(sig); tsigstart = ns_find_tsig(msg, msg + msglen); if (tsigstart == NULL) @@ -198,7 +199,7 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp, char buf[MAXDNAME]; has_tsig = 1; - n = dn_expand(msg, msg + msglen, tsigstart, buf, sizeof(buf)); + n = dn_expand(msg, msg + msglen, tsigstart, buf, sizeof buf); if (n < 0) { ns_debug(ns_log_default, 1, "ns_req: bad TSIG key name", @@ -374,24 +375,31 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp, * a TSIG error, build a new message with no data and a TSIG. */ if ((hp->tc || error != NOERROR) && has_tsig > 0) { + sign_again: hp->ancount = htons(0); hp->nscount = htons(0); hp->arcount = htons(0); cp = msg + HFIXEDSZ; cp += ns_skiprr(cp, msg + msglen, ns_s_qd, ntohs(hp->qdcount)); - sig2len = sizeof(sig2); - buflen += (msglen - (cp - msg)); + sig2len = sizeof sig2; msglen = cp - msg; + buflen = buflen_orig - msglen; n = ns_sign(msg, &msglen, msglen + buflen, error, key, sig, siglen, sig2, &sig2len, tsig_time); - if (n != 0) { - INSIST(0); + if (n == NS_TSIG_ERROR_NO_SPACE && ntohs(hp->qdcount) != 0) { + hp->qdcount = htons(0); + goto sign_again; } + if (n != 0) + ns_info(ns_log_default, + "ns_req: unable to sign response"); cp = msg + msglen; - } /* Either the message is not truncated or there was no TSIG */ else { + /* + * Reserve space for tsig if required. + */ if (has_tsig > 0) buflen -= tsig_size; n = doaddinfo(hp, cp, buflen); @@ -399,7 +407,7 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp, buflen -= n; if (has_tsig > 0) { buflen += tsig_size; - sig2len = sizeof(sig2); + sig2len = sizeof sig2; msglen = cp - msg; n = ns_sign(msg, &msglen, msglen + buflen, error, key, sig, siglen, sig2, &sig2len, tsig_time); @@ -417,12 +425,12 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp, ntohs(hp->id), cp - msg, hp->rcode); if (debug >= 10) res_pquery(&res, msg, cp - msg, - log_get_stream(packet_channel)); + log_get_stream(packet_channel)); #endif /*DEBUG*/ if (qsp == NULL) { if (sendto(dfd, (char*)msg, cp - msg, 0, (struct sockaddr *)&from, - sizeof(from)) < 0) { + sizeof from) < 0) { if (!haveComplained(ina_ulong(from.sin_addr), (u_long)sendtoStr)) ns_info(ns_log_default, @@ -460,7 +468,7 @@ static enum req_action req_notify(HEADER *hp, u_char **cpp, u_char *eom, u_char *msg, struct sockaddr_in from) { - int n, type, class, zn; + int n, type, class; char dnbuf[MAXDNAME]; struct zoneinfo *zp; @@ -769,11 +777,6 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp, np == NULL ? "missed" : "found", dname, fname, cname); - - ns_debug(ns_log_default, 1, "req: %s '%s' as '%s' (cname=%d)", - np == NULL ? "missed" : "found", - dname, fname, cname); - #ifdef YPKLUDGE /* Some braindamaged resolver software will not recognize internet addresses in dot notation and @@ -950,6 +953,10 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp, p_type(type), sin_ntoa(from), *dname ? dname : "."); nameserIncr(from.sin_addr, nssRcvdUXFR); + if (type == ns_t_ixfr) { + hp->rcode = ns_r_refused; + return (Finish); + } return (Refuse); } @@ -961,6 +968,10 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp, p_type(type), sin_ntoa(from), *dname ? dname : "."); nameserIncr(from.sin_addr, nssRcvdUXFR); + if (type == ns_t_ixfr) { + hp->rcode = ns_r_refused; + return (Finish); + } return (Refuse); } @@ -972,6 +983,10 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp, p_type(type), sin_ntoa(from), *dname ? dname : "."); nameserIncr(from.sin_addr, nssRcvdUXFR); + if (type == ns_t_ixfr) { + hp->rcode = ns_r_refused; + return (Finish); + } return (Refuse); } @@ -983,6 +998,10 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp, p_type(type), sin_ntoa(from), *dname ? dname : "."); nameserIncr(from.sin_addr, nssRcvdUXFR); + if (type == ns_t_ixfr) { + hp->rcode = ns_r_refused; + return (Finish); + } return (Refuse); } @@ -1389,15 +1408,20 @@ static enum req_action req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp, u_char *msg, struct sockaddr_in from) { - int dlen, alen, n, type, class, count; - char dnbuf[MAXDNAME], anbuf[PACKETSZ], *data, *fname; + u_int rdata_offset; + size_t alen; + int dlen, n; + ns_type type; + ns_class class; + u_char anbuf[PACKETSZ], *anptr; + char dnbuf[MAXDNAME]; nameserIncr(from.sin_addr, nssRcvdIQ); - if (ntohs(hp->ancount) != 1 - || ntohs(hp->qdcount) != 0 - || ntohs(hp->nscount) != 0 - || ntohs(hp->arcount) != 0) { + if (ntohs(hp->ancount) != 1 || + ntohs(hp->qdcount) != 0 || + ntohs(hp->nscount) != 0 || + ntohs(hp->arcount) != 0) { ns_debug(ns_log_default, 1, "FORMERR IQuery header counts wrong"); hp->rcode = ns_r_formerr; @@ -1407,7 +1431,9 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp, /* * Skip domain name, get class, and type. */ - if ((n = dn_skipname(*cpp, eom)) < 0) { + anptr = *cpp; + n = dn_skipname(*cpp, eom); + if (n < 0) { ns_debug(ns_log_default, 1, "FORMERR IQuery packet name problem"); hp->rcode = ns_r_formerr; @@ -1430,43 +1456,41 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp, hp->rcode = ns_r_formerr; return (Finish); } + rdata_offset = *cpp - anptr; *cpp += dlen; + INSIST(*cpp == eom); /* - * not all inverse queries are handled. + * Not all inverse queries are handled. */ - switch (type) { - case T_A: - if (!NS_OPTION_P(OPTION_FAKE_IQUERY) || dlen != INT32SZ) { - if (dlen != INT32SZ) - ns_warning(ns_log_security, - "bad iquery from %s", - inet_ntoa(from.sin_addr)); - return (Refuse); - } - break; - default: + if (type != ns_t_a) { ns_warning(ns_log_security, "unsupported iquery type from %s", inet_ntoa(from.sin_addr)); return (Refuse); } + if (dlen != INT32SZ) { + ns_warning(ns_log_security, + "bad iquery from %s", + inet_ntoa(from.sin_addr)); + return (Refuse); + } + if (!NS_OPTION_P(OPTION_FAKE_IQUERY)) + return (Refuse); + ns_debug(ns_log_default, 1, "req: IQuery class %d type %d", class, type); - fname = (char *)msg + HFIXEDSZ; - alen = (char *)*cpp - fname; - if ((size_t)alen > sizeof anbuf) { + alen = eom - anptr; + if (alen > sizeof anbuf) { ns_warning(ns_log_security, "bad iquery from %s", inet_ntoa(from.sin_addr)); return (Refuse); } - memcpy(anbuf, fname, alen); - data = anbuf + alen - dlen; - *cpp = (u_char *)fname; + memcpy(anbuf, anptr, alen); + *cpp = anptr; *buflenp -= HFIXEDSZ; - count = 0; #ifdef QRYLOG if (qrylog) { @@ -1474,7 +1498,7 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp, strcpy(tmp, inet_ntoa(from.sin_addr)); ns_info(ns_log_queries, "XX /%s/%s/-%s", - tmp, inet_ntoa(ina_get((u_char *)data)), + tmp, inet_ntoa(ina_get(&anbuf[rdata_offset])), p_type(type)); } #endif /*QRYLOG*/ @@ -1487,7 +1511,7 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp, * A better strategy would be to turn this into a PTR query, but that * would legitimize inverse queries in a way they do not deserve. */ - sprintf(dnbuf, "[%s]", inet_ntoa(ina_get((u_char *)data))); + sprintf(dnbuf, "[%s]", inet_ntoa(ina_get(&anbuf[rdata_offset]))); *buflenp -= QFIXEDSZ; n = dn_comp(dnbuf, *cpp, *buflenp, NULL, NULL); if (n < 0) { @@ -1495,19 +1519,20 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp, return (Finish); } *cpp += n; + *buflenp -= n; PUTSHORT((u_int16_t)type, *cpp); + *buflenp -= INT16SZ; PUTSHORT((u_int16_t)class, *cpp); - *buflenp -= n; - count++; + *buflenp -= INT16SZ; - ns_debug(ns_log_default, 1, "req: IQuery %d records", count); - hp->qdcount = htons((u_int16_t)count); + hp->qdcount = htons(1); if (alen > *buflenp) { hp->tc = 1; return (Finish); } memcpy(*cpp, anbuf, alen); *cpp += alen; + *buflenp -= alen; return (Finish); } @@ -1540,7 +1565,7 @@ stale(struct databuf *dp) { if ((int32_t)(tt.tv_sec - zp->z_lastupdate) > (int32_t)zp->z_expire) { ns_debug(ns_log_default, 1, - "stale: secondary zone %s expired", + "stale: slave zone %s expired", zp->z_origin); if (!haveComplained((u_long)zp, (u_long)stale)) { ns_notice(ns_log_default, @@ -1775,7 +1800,7 @@ make_rr(const char *name, struct databuf *dp, u_char *buf, /* Replacement */ ns_debug(ns_log_default, 1, "Replacement = %s", cp1); - n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + n = dn_comp((char *)cp1, cp, buflen, NULL, NULL); ns_debug(ns_log_default, 1, "dn_comp's n = %u", n); if (n < 0) goto cleanup; |