}
}
- if (do_doctor(header, n))
- cache_secure = 0;
-
- switch (extract_addresses(header, n, daemon->namebuff, now, ipsets, nftsets, is_sign, check_rebind, no_cache, cache_secure))
+ if (!bogusanswer)
{
- case 1:
- my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
- munged = 1;
- cache_secure = 0;
- ede = EDE_BLOCKED;
- break;
+ if (daemon->doctors && !do_doctor(header, n))
+ {
+ /* do_doctors found malformed answer. */
+ munged = 1;
+ SET_RCODE(header, SERVFAIL);
+ cache_secure = 0;
+ ede = EDE_OTHER;
+ }
- /* extract_addresses() found a malformed answer. */
- case 2:
- munged = 1;
- SET_RCODE(header, SERVFAIL);
- cache_secure = 0;
- ede = EDE_OTHER;
- break;
+ if (RCODE(header) != SERVFAIL)
+ switch (extract_addresses(header, n, daemon->namebuff, now, ipsets, nftsets, is_sign, check_rebind, no_cache, cache_secure))
+ {
+ case 1:
+ my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
+ munged = 1;
+ cache_secure = 0;
+ ede = EDE_BLOCKED;
+ break;
+
+ /* extract_addresses() found a malformed answer. */
+ case 2:
+ munged = 1;
+ SET_RCODE(header, SERVFAIL);
+ cache_secure = 0;
+ ede = EDE_OTHER;
+ break;
+ }
}
-
- if (rcode == NOERROR && rrfilter(header, &n, RRFILTER_CONF) > 0)
+
+ if (RCODE(header) == NOERROR && rrfilter(header, &n, RRFILTER_CONF) > 0)
ede = EDE_FILTERED;
}
{
unsigned char *p;
int i, qtype, qclass, rdlen;
- int doctored = 0;
-
- if (!daemon->doctors)
- return 0;
-
+
if (!(p = skip_questions(header, qlen)))
return 0;
-
+
for (i = 0; i < ntohs(header->ancount) + ntohs(header->arcount); i++)
{
/* Skip over auth section */
addr.addr4.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
/* Since we munged the data, the server it came from is no longer authoritative */
header->hb3 &= ~HB3_AA;
- doctored = 1;
+#ifdef HAVE_DNSSEC
+ /* remove validated flag from this RR, since we changed it! */
+ if (option_bool(OPT_DNSSEC_VALID) && i < ntohs(header->ancount))
+ daemon->rr_status[i] = 0;
+#endif
memcpy(p, &addr.addr4, INADDRSZ);
log_query(F_FORWARD | F_CONFIG | F_IPV4, daemon->workspacename, &addr, NULL, 0);
break;
return 0; /* bad packet */
}
- return doctored;
+ return 1;
}
/* Find SOA RR in auth section to get TTL for negative caching of name.
Cache said SOA and return the difference in length between name and the name of the
SOA RR so we can look it up again.
*/
-static int find_soa(struct dns_header *header, size_t qlen, char *name, int *substring, int no_cache, int secure, time_t now)
+static int find_soa(struct dns_header *header, size_t qlen, char *name, int *substring, int no_cache, time_t now)
{
unsigned char *p, *psave;
int qtype, qclass, rdlen;
size_t name_len, soa_len, len;
union all_addr addr;
- (void)secure; /* warning */
-
/* first move to NS section and find TTL from SOA RR */
if (!(p = skip_questions(header, qlen)) ||
!(p = skip_section(p, ntohs(header->ancount), header, qlen)))
int secflag = 0;
#ifdef HAVE_DNSSEC
- if (option_bool(OPT_DNSSEC_VALID) && secure && daemon->rr_status[i + ntohs(header->ancount)] != 0)
+ if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[i + ntohs(header->ancount)] != 0)
{
secflag = F_DNSSECOK;
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
{
#ifdef HAVE_DNSSEC
- if (option_bool(OPT_DNSSEC_VALID) && secure && daemon->rr_status[j] != 0)
+ if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[j] != 0)
{
/* validated RR anywhere in CNAME chain, don't cache. */
if (cname_short || aqtype == T_CNAME)
if (!found && !option_bool(OPT_NO_NEG))
{
/* don't cache SOAs for negative PTR records */
- ttl = find_soa(header, qlen, name, NULL, 1, 0, now);
+ ttl = find_soa(header, qlen, name, NULL, 1, now);
flags |= F_NEG | (secure ? F_DNSSECOK : 0);
if (name_encoding && ttl)
}
#ifdef HAVE_DNSSEC
- if (option_bool(OPT_DNSSEC_VALID) && secure && daemon->rr_status[j] != 0)
+ if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[j] != 0)
{
secflag = F_DNSSECOK;
/* If there's no SOA to get the TTL from, but there is a CNAME
pointing at this, inherit its TTL */
- if (insert && !option_bool(OPT_NO_NEG) && ((ttl = find_soa(header, qlen, name, &substring, no_cache_dnssec, secure, now)) || cpp))
+ if (insert && !option_bool(OPT_NO_NEG) && ((ttl = find_soa(header, qlen, name, &substring, no_cache_dnssec, now)) || cpp))
{
addr.rrdata.datalen = substring;
addr.rrdata.rrtype = qtype;