Commit 87070192 authored by Simon Kelley's avatar Simon Kelley

Mass edit of INSECURE->BOGUS returns for server failure/bad input.

parent d1fbb77e
...@@ -592,8 +592,8 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int ...@@ -592,8 +592,8 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
STAT_SECURE if it validates. STAT_SECURE if it validates.
STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion. STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion.
STAT_NO_SIG no RRsigs found. STAT_NO_SIG no RRsigs found.
STAT_INSECURE can't validate (no RRSIG, bad packet). STAT_INSECURE RRset empty.
STAT_BOGUS signature is wrong. STAT_BOGUS signature is wrong, bad packet.
STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname) STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
if key is non-NULL, use that key, which has the algo and tag given in the params of those names, if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
...@@ -614,7 +614,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -614,7 +614,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
u16 *rr_desc = get_desc(type); u16 *rr_desc = get_desc(type);
if (!(p = skip_questions(header, plen))) if (!(p = skip_questions(header, plen)))
return STAT_INSECURE; return STAT_BOGUS;
name_labels = count_labels(name); /* For 4035 5.3.2 check */ name_labels = count_labels(name); /* For 4035 5.3.2 check */
...@@ -628,7 +628,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -628,7 +628,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
pstart = p; pstart = p;
if (!(res = extract_name(header, plen, &p, name, 0, 10))) if (!(res = extract_name(header, plen, &p, name, 0, 10)))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(stype, p); GETSHORT(stype, p);
GETSHORT(sclass, p); GETSHORT(sclass, p);
...@@ -639,14 +639,14 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -639,14 +639,14 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
GETSHORT(rdlen, p); GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen)) if (!CHECK_LEN(header, p, plen, rdlen))
return STAT_INSECURE; return STAT_BOGUS;
if (res == 1 && sclass == class) if (res == 1 && sclass == class)
{ {
if (stype == type) if (stype == type)
{ {
if (!expand_workspace(&rrset, &rrset_sz, rrsetidx)) if (!expand_workspace(&rrset, &rrset_sz, rrsetidx))
return STAT_INSECURE; return STAT_BOGUS;
rrset[rrsetidx++] = pstart; rrset[rrsetidx++] = pstart;
} }
...@@ -654,14 +654,14 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -654,14 +654,14 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
if (stype == T_RRSIG) if (stype == T_RRSIG)
{ {
if (rdlen < 18) if (rdlen < 18)
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(type_covered, p); GETSHORT(type_covered, p);
if (type_covered == type) if (type_covered == type)
{ {
if (!expand_workspace(&sigs, &sig_sz, sigidx)) if (!expand_workspace(&sigs, &sig_sz, sigidx))
return STAT_INSECURE; return STAT_BOGUS;
sigs[sigidx++] = pdata; sigs[sigidx++] = pdata;
} }
...@@ -671,7 +671,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -671,7 +671,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
} }
if (!ADD_RDLEN(header, p, plen, rdlen)) if (!ADD_RDLEN(header, p, plen, rdlen))
return STAT_INSECURE; return STAT_BOGUS;
} }
/* RRset empty */ /* RRset empty */
...@@ -710,7 +710,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -710,7 +710,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
GETSHORT(key_tag, p); GETSHORT(key_tag, p);
if (!extract_name(header, plen, &p, keyname, 1, 0)) if (!extract_name(header, plen, &p, keyname, 1, 0))
return STAT_INSECURE; return STAT_BOGUS;
/* RFC 4035 5.3.1 says that the Signer's Name field MUST equal /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
the name of the zone containing the RRset. We can't tell that the name of the zone containing the RRset. We can't tell that
...@@ -765,7 +765,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -765,7 +765,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
p = rrset[i]; p = rrset[i];
if (!extract_name(header, plen, &p, name, 1, 10)) if (!extract_name(header, plen, &p, name, 1, 10))
return STAT_INSECURE; return STAT_BOGUS;
name_start = name; name_start = name;
...@@ -788,7 +788,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -788,7 +788,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
p += 8; /* skip class, type, ttl */ p += 8; /* skip class, type, ttl */
GETSHORT(rdlen, p); GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen)) if (!CHECK_LEN(header, p, plen, rdlen))
return STAT_INSECURE; return STAT_BOGUS;
end = p + rdlen; end = p + rdlen;
...@@ -839,10 +839,10 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -839,10 +839,10 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* The DNS packet is expected to contain the answer to a DNSKEY query. /* The DNS packet is expected to contain the answer to a DNSKEY query.
Put all DNSKEYs in the answer which are valid into the cache. Put all DNSKEYs in the answer which are valid into the cache.
return codes: return codes:
STAT_INSECURE bad packet, no DNSKEYs in reply. STAT_INSECURE No DNSKEYs in reply.
STAT_SECURE At least one valid DNSKEY found and in cache. STAT_SECURE At least one valid DNSKEY found and in cache.
STAT_BOGUS No DNSKEYs found, which can be validated with DS, STAT_BOGUS No DNSKEYs found, which can be validated with DS,
or self-sign for DNSKEY RRset is not valid. or self-sign for DNSKEY RRset is not valid, bad packet.
STAT_NEED_DS DS records to validate a key not found, name in keyname STAT_NEED_DS DS records to validate a key not found, name in keyname
*/ */
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class) int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
...@@ -855,13 +855,16 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch ...@@ -855,13 +855,16 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
if (ntohs(header->qdcount) != 1 || if (ntohs(header->qdcount) != 1 ||
!extract_name(header, plen, &p, name, 1, 4)) !extract_name(header, plen, &p, name, 1, 4))
return STAT_INSECURE; return STAT_BOGUS;
GETSHORT(qtype, p); GETSHORT(qtype, p);
GETSHORT(qclass, p); GETSHORT(qclass, p);
if (qtype != T_DNSKEY || qclass != class || ntohs(header->ancount) == 0) if (qtype != T_DNSKEY || qclass != class)
return STAT_BOGUS; return STAT_BOGUS;
if (ntohs(header->ancount) == 0)
return STAT_INSECURE;
/* See if we have cached a DS record which validates this key */ /* See if we have cached a DS record which validates this key */
if (!(crecp = cache_find_by_name(NULL, name, now, F_DS))) if (!(crecp = cache_find_by_name(NULL, name, now, F_DS)))
...@@ -879,7 +882,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch ...@@ -879,7 +882,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
{ {
/* Ensure we have type, class TTL and length */ /* Ensure we have type, class TTL and length */
if (!(rc = extract_name(header, plen, &p, name, 0, 10))) if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(qtype, p); GETSHORT(qtype, p);
GETSHORT(qclass, p); GETSHORT(qclass, p);
...@@ -887,7 +890,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch ...@@ -887,7 +890,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
GETSHORT(rdlen, p); GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4) if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
if (qclass != class || qtype != T_DNSKEY || rc == 2) if (qclass != class || qtype != T_DNSKEY || rc == 2)
{ {
...@@ -914,7 +917,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch ...@@ -914,7 +917,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
{ {
if (key) if (key)
blockdata_free(key); blockdata_free(key);
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
} }
/* No zone key flag or malloc failure */ /* No zone key flag or malloc failure */
...@@ -976,7 +979,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch ...@@ -976,7 +979,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
GETSHORT(rdlen, p); GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen)) if (!CHECK_LEN(header, p, plen, rdlen))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
if (qclass == class && rc == 1) if (qclass == class && rc == 1)
{ {
...@@ -985,7 +988,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch ...@@ -985,7 +988,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
if (qtype == T_DNSKEY) if (qtype == T_DNSKEY)
{ {
if (rdlen < 4) if (rdlen < 4)
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(flags, p); GETSHORT(flags, p);
if (*p++ != 3) if (*p++ != 3)
...@@ -1017,7 +1020,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1017,7 +1020,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
{ {
/* RRSIG, cache if covers DNSKEY RRset */ /* RRSIG, cache if covers DNSKEY RRset */
if (rdlen < 18) if (rdlen < 18)
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(type_covered, p); GETSHORT(type_covered, p);
...@@ -1049,7 +1052,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1049,7 +1052,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
} }
if (!ADD_RDLEN(header, p, plen, rdlen)) if (!ADD_RDLEN(header, p, plen, rdlen))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
} }
/* commit cache insert. */ /* commit cache insert. */
...@@ -1064,10 +1067,10 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1064,10 +1067,10 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
/* The DNS packet is expected to contain the answer to a DS query /* The DNS packet is expected to contain the answer to a DS query
Put all DSs in the answer which are valid into the cache. Put all DSs in the answer which are valid into the cache.
return codes: return codes:
STAT_INSECURE bad packet, no DS in reply, proven no DS in reply. STAT_INSECURE no DS in reply or not signed.
STAT_SECURE At least one valid DS found and in cache. STAT_SECURE At least one valid DS found and in cache.
STAT_NO_DS It's proved there's no DS here. STAT_NO_DS It's proved there's no DS here.
STAT_BOGUS At least one DS found, which fails validation. STAT_BOGUS At least one DS found, which fails validation, bad packet.
STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname
*/ */
...@@ -1078,7 +1081,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char ...@@ -1078,7 +1081,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
if (ntohs(header->qdcount) != 1 || if (ntohs(header->qdcount) != 1 ||
!(p = skip_name(p, header, plen, 4))) !(p = skip_name(p, header, plen, 4)))
return STAT_INSECURE; return STAT_BOGUS;
GETSHORT(qtype, p); GETSHORT(qtype, p);
GETSHORT(qclass, p); GETSHORT(qclass, p);
...@@ -1096,7 +1099,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char ...@@ -1096,7 +1099,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
p += 4; /* qtype, qclass */ p += 4; /* qtype, qclass */
if (!(p = skip_section(p, ntohs(header->ancount), header, plen))) if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
return STAT_INSECURE; return STAT_BOGUS;
if (val == STAT_BOGUS) if (val == STAT_BOGUS)
log_query(F_UPSTREAM, name, NULL, "BOGUS DS"); log_query(F_UPSTREAM, name, NULL, "BOGUS DS");
...@@ -1116,7 +1119,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char ...@@ -1116,7 +1119,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
for (i = ntohs(header->nscount); i != 0; i--) for (i = ntohs(header->nscount); i != 0; i--)
{ {
if (!(p = skip_name(p, header, plen, 0))) if (!(p = skip_name(p, header, plen, 0)))
return STAT_INSECURE; return STAT_BOGUS;
GETSHORT(qtype, p); GETSHORT(qtype, p);
GETSHORT(qclass, p); GETSHORT(qclass, p);
...@@ -1124,7 +1127,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char ...@@ -1124,7 +1127,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
GETSHORT(rdlen, p); GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen)) if (!CHECK_LEN(header, p, plen, rdlen))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
if (qclass != class || qtype != T_SOA) if (qclass != class || qtype != T_SOA)
{ {
...@@ -1137,10 +1140,10 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char ...@@ -1137,10 +1140,10 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
/* MNAME */ /* MNAME */
if (!(p = skip_name(p, header, plen, 0))) if (!(p = skip_name(p, header, plen, 0)))
return STAT_INSECURE; return STAT_BOGUS;
/* RNAME */ /* RNAME */
if (!(p = skip_name(p, header, plen, 20))) if (!(p = skip_name(p, header, plen, 20)))
return STAT_INSECURE; return STAT_BOGUS;
p += 16; /* SERIAL REFRESH RETRY EXPIRE */ p += 16; /* SERIAL REFRESH RETRY EXPIRE */
GETLONG(ttl, p); /* minTTL */ GETLONG(ttl, p); /* minTTL */
...@@ -1237,7 +1240,7 @@ static int find_nsec_records(struct dns_header *header, size_t plen, unsigned ch ...@@ -1237,7 +1240,7 @@ static int find_nsec_records(struct dns_header *header, size_t plen, unsigned ch
static unsigned char **nsecset = NULL; static unsigned char **nsecset = NULL;
static int nsecset_sz = 0; static int nsecset_sz = 0;
int type_found = -1; int type_found = 0;
unsigned char *p = skip_questions(header, plen); unsigned char *p = skip_questions(header, plen);
int type, class, rdlen, i, nsecs_found; int type, class, rdlen, i, nsecs_found;
...@@ -1296,12 +1299,12 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi ...@@ -1296,12 +1299,12 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
{ {
p = nsecs[i]; p = nsecs[i];
if (!extract_name(header, plen, &p, workspace1, 1, 10)) if (!extract_name(header, plen, &p, workspace1, 1, 10))
return STAT_INSECURE; return STAT_BOGUS;
p += 8; /* class, type, TTL */ p += 8; /* class, type, TTL */
GETSHORT(rdlen, p); GETSHORT(rdlen, p);
psave = p; psave = p;
if (!extract_name(header, plen, &p, workspace2, 1, 10)) if (!extract_name(header, plen, &p, workspace2, 1, 10))
return STAT_INSECURE; return STAT_BOGUS;
rc = hostname_cmp(workspace1, name); rc = hostname_cmp(workspace1, name);
...@@ -1319,7 +1322,7 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi ...@@ -1319,7 +1322,7 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
while (rdlen >= 2) while (rdlen >= 2)
{ {
if (!CHECK_LEN(header, p, plen, rdlen)) if (!CHECK_LEN(header, p, plen, rdlen))
return STAT_INSECURE; return STAT_BOGUS;
if (p[0] == type >> 8) if (p[0] == type >> 8)
{ {
...@@ -1434,7 +1437,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1434,7 +1437,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
for (i = 0; i < nsec_count; i++) for (i = 0; i < nsec_count; i++)
{ {
if (!(p = skip_name(nsecs[i], header, plen, 15))) if (!(p = skip_name(nsecs[i], header, plen, 15)))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
p += 10; /* type, class, TTL, rdlen */ p += 10; /* type, class, TTL, rdlen */
algo = *p++; algo = *p++;
...@@ -1452,7 +1455,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1452,7 +1455,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
salt_len = *p++; salt_len = *p++;
salt = p; salt = p;
if (!CHECK_LEN(header, salt, plen, salt_len)) if (!CHECK_LEN(header, salt, plen, salt_len))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
/* Now prune so we only have NSEC3 records with same iterations, salt and algo */ /* Now prune so we only have NSEC3 records with same iterations, salt and algo */
for (i = 0; i < nsec_count; i++) for (i = 0; i < nsec_count; i++)
...@@ -1463,7 +1466,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1463,7 +1466,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
nsecs[i] = NULL; /* Speculative, will be restored if OK. */ nsecs[i] = NULL; /* Speculative, will be restored if OK. */
if (!(p = skip_name(nsec3p, header, plen, 15))) if (!(p = skip_name(nsec3p, header, plen, 15)))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
p += 10; /* type, class, TTL, rdlen */ p += 10; /* type, class, TTL, rdlen */
...@@ -1480,7 +1483,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1480,7 +1483,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
continue; continue;
if (!CHECK_LEN(header, p, plen, salt_len)) if (!CHECK_LEN(header, p, plen, salt_len))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
if (memcmp(p, salt, salt_len) != 0) if (memcmp(p, salt, salt_len) != 0)
continue; continue;
...@@ -1491,7 +1494,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1491,7 +1494,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
/* Algo is checked as 1 above */ /* Algo is checked as 1 above */
if (!(hash = hash_find("sha1"))) if (!(hash = hash_find("sha1")))
return STAT_INSECURE; return STAT_BOGUS;
/* Now, we need the "closest encloser NSEC3" */ /* Now, we need the "closest encloser NSEC3" */
closest_encloser = name; closest_encloser = name;
...@@ -1503,14 +1506,14 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1503,14 +1506,14 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
closest_encloser++; closest_encloser++;
if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0) if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0)
return STAT_INSECURE; return STAT_BOGUS;
for (i = 0; i < nsec_count; i++) for (i = 0; i < nsec_count; i++)
if ((p = nsecs[i])) if ((p = nsecs[i]))
{ {
if (!extract_name(header, plen, &p, workspace1, 1, 0) || if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2))) !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
return STAT_INSECURE; return STAT_BOGUS;
if (digest_len == base32_len && if (digest_len == base32_len &&
memcmp(digest, workspace2, digest_len) == 0) memcmp(digest, workspace2, digest_len) == 0)
...@@ -1543,14 +1546,14 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1543,14 +1546,14 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
p += 5 + salt_len; /* algo, flags, iterations, salt_len, salt */ p += 5 + salt_len; /* algo, flags, iterations, salt_len, salt */
hash_len = *p++; hash_len = *p++;
if (!CHECK_LEN(header, p, plen, hash_len)) if (!CHECK_LEN(header, p, plen, hash_len))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
p += hash_len; p += hash_len;
rdlen -= p - psave; rdlen -= p - psave;
while (rdlen >= 2) while (rdlen >= 2)
{ {
if (!CHECK_LEN(header, p, plen, rdlen)) if (!CHECK_LEN(header, p, plen, rdlen))
return STAT_INSECURE; return STAT_BOGUS;
if (p[0] == type >> 8) if (p[0] == type >> 8)
{ {
...@@ -1570,20 +1573,20 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1570,20 +1573,20 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
/* Look for NSEC3 that proves the non-existence of the next-closest encloser */ /* Look for NSEC3 that proves the non-existence of the next-closest encloser */
if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0) if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0)
return STAT_INSECURE; return STAT_BOGUS;
for (i = 0; i < nsec_count; i++) for (i = 0; i < nsec_count; i++)
if ((p = nsecs[i])) if ((p = nsecs[i]))
{ {
if (!extract_name(header, plen, &p, workspace1, 1, 0) || if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2))) !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
return STAT_INSECURE; return STAT_BOGUS;
p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */ p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
hash_len = *p++; /* p now points to next hashed name */ hash_len = *p++; /* p now points to next hashed name */
if (!CHECK_LEN(header, p, plen, hash_len)) if (!CHECK_LEN(header, p, plen, hash_len))
return STAT_INSECURE; return STAT_BOGUS;
if (digest_len == base32_len && hash_len == base32_len) if (digest_len == base32_len && hash_len == base32_len)
{ {
...@@ -1611,20 +1614,20 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1611,20 +1614,20 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
*wildcard = '*'; *wildcard = '*';
if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0) if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
return STAT_INSECURE; return STAT_BOGUS;
for (i = 0; i < nsec_count; i++) for (i = 0; i < nsec_count; i++)
if ((p = nsecs[i])) if ((p = nsecs[i]))
{ {
if (!extract_name(header, plen, &p, workspace1, 1, 0) || if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2))) !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
return STAT_INSECURE; return STAT_BOGUS;
p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */ p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
hash_len = *p++; /* p now points to next hashed name */ hash_len = *p++; /* p now points to next hashed name */
if (!CHECK_LEN(header, p, plen, hash_len)) if (!CHECK_LEN(header, p, plen, hash_len))
return STAT_INSECURE; return STAT_BOGUS;
if (digest_len == base32_len && hash_len == base32_len) if (digest_len == base32_len && hash_len == base32_len)
{ {
...@@ -1659,16 +1662,16 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1659,16 +1662,16 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if (neganswer) if (neganswer)
*neganswer = 0; *neganswer = 0;
if (RCODE(header) == SERVFAIL) if (RCODE(header) == SERVFAIL || ntohs(header->qdcount) != 1)
return STAT_BOGUS; return STAT_BOGUS;
if ((RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR) || ntohs(header->qdcount) != 1) if (RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR)
return STAT_INSECURE; return STAT_INSECURE;
qname = p1 = (unsigned char *)(header+1); qname = p1 = (unsigned char *)(header+1);
if (!extract_name(header, plen, &p1, name, 1, 4)) if (!extract_name(header, plen, &p1, name, 1, 4))
return STAT_INSECURE; return STAT_BOGUS;
GETSHORT(qtype, p1); GETSHORT(qtype, p1);
GETSHORT(qclass, p1); GETSHORT(qclass, p1);
...@@ -1684,7 +1687,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1684,7 +1687,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
/* leave pointer to missing name in qname */ /* leave pointer to missing name in qname */
if (!(rc = extract_name(header, plen, &p1, name, 0, 10))) if (!(rc = extract_name(header, plen, &p1, name, 0, 10)))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(type2, p1); GETSHORT(type2, p1);
GETSHORT(class2, p1); GETSHORT(class2, p1);
...@@ -1705,7 +1708,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1705,7 +1708,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
/* looped CNAMES */ /* looped CNAMES */
if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0)) if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
return STAT_INSECURE; return STAT_BOGUS;
p1 = ans_start; p1 = ans_start;
goto cname_loop; goto cname_loop;
...@@ -1713,7 +1716,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1713,7 +1716,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
} }
if (!ADD_RDLEN(header, p1, plen, rdlen2)) if (!ADD_RDLEN(header, p1, plen, rdlen2))
return STAT_INSECURE; return STAT_BOGUS;
} }
if (neganswer && !have_answer) if (neganswer && !have_answer)
...@@ -1726,7 +1729,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1726,7 +1729,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++) for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
{ {
if (!extract_name(header, plen, &p1, name, 1, 10)) if (!extract_name(header, plen, &p1, name, 1, 10))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(type1, p1); GETSHORT(type1, p1);
GETSHORT(class1, p1); GETSHORT(class1, p1);
...@@ -1740,7 +1743,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1740,7 +1743,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
for (p2 = ans_start, j = 0; j < i; j++) for (p2 = ans_start, j = 0; j < i; j++)
{ {
if (!(rc = extract_name(header, plen, &p2, name, 0, 10))) if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(type2, p2); GETSHORT(type2, p2);
GETSHORT(class2, p2); GETSHORT(class2, p2);
...@@ -1751,7 +1754,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1751,7 +1754,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
break; /* Done it before: name, type, class all match. */ break; /* Done it before: name, type, class all match. */
if (!ADD_RDLEN(header, p2, plen, rdlen2)) if (!ADD_RDLEN(header, p2, plen, rdlen2))
return STAT_INSECURE; return STAT_BOGUS;
} }
/* Not done, validate now */ /* Not done, validate now */
...@@ -1771,15 +1774,8 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1771,15 +1774,8 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
answer and overlay a genuine RR. To prove this answer and overlay a genuine RR. To prove this
hasn't happened, the answer must prove that hasn't happened, the answer must prove that
the gennuine record doesn't exist. Check that here. */ the gennuine record doesn't exist. Check that here. */
if (!nsec_type) if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class1)))
{ return STAT_BOGUS; /* No NSECs or bad packet */
nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class1);
if (nsec_type == 0)
return STAT_INSECURE; /* Bad packet */
if (nsec_type == -1)
return STAT_BOGUS; /* No NSECs */
}
if (nsec_type == T_NSEC) if (nsec_type == T_NSEC)
rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1); rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1);
...@@ -1802,7 +1798,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1802,7 +1798,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++) for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
{ {
if (!(rc = extract_name(header, plen, &p2, name, 0, 10))) if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(type2, p2); GETSHORT(type2, p2);
GETSHORT(class2, p2); GETSHORT(class2, p2);
...@@ -1810,7 +1806,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1810,7 +1806,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
GETSHORT(rdlen2, p2); GETSHORT(rdlen2, p2);
if (!CHECK_LEN(header, p2, plen, rdlen2)) if (!CHECK_LEN(header, p2, plen, rdlen2))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
if (class2 == class1 && rc == 1) if (class2 == class1 && rc == 1)
{ {
...@@ -1819,7 +1815,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1819,7 +1815,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if (type1 == T_DS && type2 == T_DS) if (type1 == T_DS && type2 == T_DS)
{ {
if (rdlen2 < 4) if (rdlen2 < 4)
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(keytag, p2); GETSHORT(keytag, p2);
algo = *p2++; algo = *p2++;
...@@ -1847,7 +1843,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1847,7 +1843,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
else if (type2 == T_RRSIG) else if (type2 == T_RRSIG)
{ {
if (rdlen2 < 18) if (rdlen2 < 18)
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
GETSHORT(type_covered, p2); GETSHORT(type_covered, p2);
...@@ -1883,7 +1879,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1883,7 +1879,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
} }
if (!ADD_RDLEN(header, p2, plen, rdlen2)) if (!ADD_RDLEN(header, p2, plen, rdlen2))
return STAT_INSECURE; /* bad packet */ return STAT_BOGUS; /* bad packet */
} }
cache_end_insert(); cache_end_insert();
...@@ -1891,7 +1887,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1891,7 +1887,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
} }
if (!ADD_RDLEN(header, p1, plen, rdlen1)) if (!ADD_RDLEN(header, p1, plen, rdlen1))
return STAT_INSECURE; return STAT_BOGUS;
} }
/* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */ /* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */
...@@ -1900,19 +1896,12 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch ...@@ -1900,19 +1896,12 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
/* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */ /* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
/* First marshall the NSEC records, if we've not done it previously */ /* First marshall the NSEC records, if we've not done it previously */
if (!nsec_type) if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
{ return STAT_BOGUS; /* No NSECs */
nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass);
if (nsec_type == 0)
return STAT_INSECURE; /* Bad packet */
if (nsec_type == -1)
return STAT_BOGUS; /* No NSECs */
}
/* Get name of missing answer */ /* Get name of missing answer */
if (!extract_name(header, plen, &qname, name, 1, 0)) if (!extract_name(header, plen, &qname, name, 1, 0))
return STAT_INSECURE; return STAT_BOGUS;
if (nsec_type == T_NSEC) if (nsec_type == T_NSEC)
return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype); return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment