mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
- algorithm compromise protection using the algorithms signalled in
the DS record. Also, trust anchors, DLV, and RFC5011 receive this,
and thus, if you have multiple algorithms in your trust-anchor-file
then it will now behave different than before. Also, 5011 rollover
for algorithms needs to be double-signature until the old algorithm
is revoked.
git-svn-id: file:///svn/unbound/trunk@2358 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
f378068b32
commit
daab92e954
5 changed files with 52 additions and 31 deletions
|
|
@ -1,3 +1,12 @@
|
|||
21 December 2010: Wouter
|
||||
- algorithm compromise protection using the algorithms signalled in
|
||||
the DS record. Also, trust anchors, DLV, and RFC5011 receive this,
|
||||
and thus, if you have multiple algorithms in your trust-anchor-file
|
||||
then it will now behave different than before. Also, 5011 rollover
|
||||
for algorithms needs to be double-signature until the old algorithm
|
||||
is revoked.
|
||||
It is not an option, because I see no use to turn the security off.
|
||||
|
||||
17 December 2010: Wouter
|
||||
- squelch 'tcp connect: bla' in logfile, (set verbosity 2 to see them).
|
||||
- fix validation in this case: CNAME to nodata for co-hosted opt-in
|
||||
|
|
|
|||
|
|
@ -972,27 +972,17 @@ verify_dnskey(struct module_env* env, struct val_env* ve,
|
|||
struct trust_anchor* tp, struct ub_packed_rrset_key* rrset)
|
||||
{
|
||||
char* reason = NULL;
|
||||
if(tp->ds_rrset) {
|
||||
/* verify with ds, any will do to prime autotrust */
|
||||
enum sec_status sec = val_verify_DNSKEY_with_DS(
|
||||
env, ve, rrset, tp->ds_rrset, 0, &reason);
|
||||
verbose(VERB_ALGO, "autotrust: validate DNSKEY with DS: %s",
|
||||
uint8_t sigalg[ALGO_NEEDS_MAX+1];
|
||||
int downprot = 1;
|
||||
enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset,
|
||||
tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason);
|
||||
/* sigalg is ignored, it returns algorithms signalled to exist, but
|
||||
* in 5011 there are no other rrsets to check. if downprot is
|
||||
* enabled, then it checks that the DNSKEY is signed with all
|
||||
* algorithms available in the trust store. */
|
||||
verbose(VERB_ALGO, "autotrust: validate DNSKEY with anchor: %s",
|
||||
sec_status_to_string(sec));
|
||||
if(sec == sec_status_secure) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(tp->dnskey_rrset) {
|
||||
/* verify with keys */
|
||||
enum sec_status sec = val_verify_rrset(env, ve, rrset,
|
||||
tp->dnskey_rrset, 0, &reason);
|
||||
verbose(VERB_ALGO, "autotrust: validate DNSKEY with keys: %s",
|
||||
sec_status_to_string(sec));
|
||||
if(sec == sec_status_secure) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return sec == sec_status_secure;
|
||||
}
|
||||
|
||||
/** Find minimum expiration interval from signatures */
|
||||
|
|
@ -1024,6 +1014,8 @@ rr_is_selfsigned_revoked(struct module_env* env, struct val_env* ve,
|
|||
char* reason = NULL;
|
||||
verbose(VERB_ALGO, "seen REVOKE flag, check self-signed, rr %d",
|
||||
(int)i);
|
||||
/* no algorithm downgrade protection necessary, if it is selfsigned
|
||||
* revoked it can be removed. */
|
||||
sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset, i,
|
||||
&reason);
|
||||
return (sec == sec_status_secure);
|
||||
|
|
|
|||
|
|
@ -551,8 +551,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
|
|||
struct ub_packed_rrset_key* ta_ds,
|
||||
struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason)
|
||||
{
|
||||
/* as long as this is false, we can consider this DS rrset to be
|
||||
* equivalent to no DS rrset. */
|
||||
/* as long as this is false, we can consider this anchor to be
|
||||
* equivalent to no anchor. */
|
||||
int has_useful_ta = 0, digest_algo = 0, alg;
|
||||
struct algo_needs needs;
|
||||
size_t i, num;
|
||||
|
|
@ -591,9 +591,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
|
|||
* And check it is the strongest digest */
|
||||
if(!ds_digest_algo_is_supported(ta_ds, i) ||
|
||||
!ds_key_algo_is_supported(ta_ds, i) ||
|
||||
ds_get_digest_algo(ta_ds, i) != digest_algo) {
|
||||
ds_get_digest_algo(ta_ds, i) != digest_algo)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Once we see a single DS with a known digestID and
|
||||
* algorithm, we cannot return INSECURE (with a
|
||||
|
|
@ -620,9 +619,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
|
|||
num = rrset_get_count(ta_dnskey);
|
||||
for(i=0; i<num; i++) {
|
||||
/* Check to see if we can understand this DNSKEY */
|
||||
if(!dnskey_algo_is_supported(ta_dnskey, i)) {
|
||||
if(!dnskey_algo_is_supported(ta_dnskey, i))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we saw a useful TA */
|
||||
has_useful_ta = true;
|
||||
|
|
@ -632,7 +630,7 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
|
|||
if(sec == sec_status_secure) {
|
||||
if(!sigalg || algo_needs_set_secure(&needs,
|
||||
(uint8_t)dnskey_get_algo(ta_dnskey, i))) {
|
||||
verbose(VERB_ALGO, "DS matched DNSKEY.");
|
||||
verbose(VERB_ALGO, "anchor matched DNSKEY.");
|
||||
return sec_status_secure;
|
||||
}
|
||||
} else if(sigalg && sec == sec_status_bogus) {
|
||||
|
|
@ -642,7 +640,6 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* If no DSs were understandable, then this is OK. */
|
||||
if(!has_useful_ta) {
|
||||
verbose(VERB_ALGO, "No usable trust anchors were found -- "
|
||||
|
|
|
|||
|
|
@ -158,6 +158,27 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
|
|||
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
|
||||
struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason);
|
||||
|
||||
/**
|
||||
* Verify DNSKEYs with DS and DNSKEY rrset. Like val_verify_DNSKEY_with_DS
|
||||
* but for a trust anchor.
|
||||
* @param env: module environment (scratch buffer)
|
||||
* @param ve: validator environment (verification settings)
|
||||
* @param dnskey_rrset: DNSKEY rrset to verify
|
||||
* @param ta_ds: DS rrset to verify with.
|
||||
* @param ta_dnskey: DNSKEY rrset to verify with.
|
||||
* @param sigalg: if nonNULL provide downgrade protection otherwise one
|
||||
* algorithm is enough. The list of signalled algorithms is returned,
|
||||
* must have enough space for ALGO_NEEDS_MAX+1.
|
||||
* @param reason: reason of failure. Fixed string or alloced in scratch.
|
||||
* @return: sec_status_secure if a DS matches.
|
||||
* sec_status_insecure if end of trust (i.e., unknown algorithms).
|
||||
* sec_status_bogus if it fails.
|
||||
*/
|
||||
enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env,
|
||||
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
|
||||
struct ub_packed_rrset_key* ta_ds,
|
||||
struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason);
|
||||
|
||||
/**
|
||||
* Verify new DNSKEYs with DS rrset. The DS contains hash values that should
|
||||
* match the DNSKEY keys.
|
||||
|
|
|
|||
|
|
@ -2241,6 +2241,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
|
|||
struct key_entry_key* kkey = NULL;
|
||||
enum sec_status sec = sec_status_unchecked;
|
||||
char* reason = NULL;
|
||||
int downprot = 1;
|
||||
|
||||
if(!dnskey_rrset) {
|
||||
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
|
||||
|
|
@ -2262,7 +2263,8 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
|
|||
}
|
||||
/* attempt to verify with trust anchor DS and DNSKEY */
|
||||
kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve,
|
||||
dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, 0, &reason);
|
||||
dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, downprot,
|
||||
&reason);
|
||||
if(!kkey) {
|
||||
log_err("out of memory: verifying prime TA");
|
||||
return NULL;
|
||||
|
|
|
|||
Loading…
Reference in a new issue