Commit 2dbba34b authored by Simon Kelley's avatar Simon Kelley

DNSSEC validation tweak.

A zone which has at least one key with an algorithm we don't
support should be considered as insecure.
parent c2bcd1e1
...@@ -763,10 +763,10 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int ...@@ -763,10 +763,10 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int
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)
STAT_NEED_DS need DS to complete validation (name is returned in keyname) STAT_NEED_DS need DS 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,
otherwise find the key in the cache. otherwise find the key in the cache.
name is unchanged on exit. keyname is used as workspace and trashed. Name is unchanged on exit. keyname is used as workspace and trashed.
Call explore_rrset first to find and count RRs and sigs. Call explore_rrset first to find and count RRs and sigs.
*/ */
...@@ -919,6 +919,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -919,6 +919,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
return STAT_BOGUS; return STAT_BOGUS;
} }
/* 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:
...@@ -1834,12 +1835,12 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns ...@@ -1834,12 +1835,12 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
STAT_SECURE zone is signed. STAT_SECURE zone is signed.
STAT_INSECURE zone proved unsigned. STAT_INSECURE zone proved unsigned.
STAT_NEED_DS require DS record of name returned in keyname. STAT_NEED_DS require DS record of name returned in keyname.
STAT_NEED_DNSKEY require DNSKEY record of name returned in keyname.
name returned unaltered. name returned unaltered.
*/ */
static int zone_status(char *name, int class, char *keyname, time_t now) static int zone_status(char *name, int class, char *keyname, time_t now)
{ {
int name_start = strlen(name); int secure_ds, name_start = strlen(name);
struct crec *crecp; struct crec *crecp;
char *p; char *p;
...@@ -1850,6 +1851,9 @@ static int zone_status(char *name, int class, char *keyname, time_t now) ...@@ -1850,6 +1851,9 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DS))) if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DS)))
return STAT_NEED_DS; return STAT_NEED_DS;
else else
{
secure_ds = 0;
do do
{ {
if (crecp->uid == (unsigned int)class) if (crecp->uid == (unsigned int)class)
...@@ -1867,9 +1871,31 @@ static int zone_status(char *name, int class, char *keyname, time_t now) ...@@ -1867,9 +1871,31 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
} }
else if (!ds_digest_name(crecp->addr.ds.digest) || !algo_digest_name(crecp->addr.ds.algo)) else if (!ds_digest_name(crecp->addr.ds.digest) || !algo_digest_name(crecp->addr.ds.algo))
return STAT_INSECURE; /* algo we can't use - insecure */ return STAT_INSECURE; /* algo we can't use - insecure */
else
secure_ds = 1;
} }
} }
while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS))); while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS)));
}
if (secure_ds)
{
/* We've found only DS records that attest to the DNSKEY RRset in the zone, so we believe
that RRset is good. Furthermore the DNSKEY whose hash is proved by the DS record is
one we can use. However the DNSKEY RRset may contain more than one key and
one of the other keys may use an algorithm we don't support. If that's
the case the zone is insecure for us. */
if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY)))
return STAT_NEED_KEY;
do
{
if (crecp->uid == (unsigned int)class && !algo_digest_name(crecp->addr.key.algo))
return STAT_INSECURE;
}
while ((crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY)));
}
if (name_start == 0) if (name_start == 0)
break; break;
......
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