From 8a6b3f088ba94640cdeba19da116167517cb7c35 Mon Sep 17 00:00:00 2001 From: TCY16 Date: Fri, 8 Oct 2021 15:54:10 +0200 Subject: [PATCH] add DNSKEY EDE code --- services/mesh.c | 4 +- util/config_file.c | 41 +++++++++++++++++- util/config_file.h | 8 ++++ validator/val_sigcrypt.c | 4 +- validator/val_utils.c | 94 +++++++++++++++++++++++++++++++++------- validator/val_utils.h | 23 ++++++++++ validator/validator.c | 13 ++++-- 7 files changed, 165 insertions(+), 22 deletions(-) diff --git a/services/mesh.c b/services/mesh.c index 991dcce7d..4f1cb83d9 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -1280,9 +1280,11 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, char *reason = m->s.env->cfg->val_log_level >= 2 ? errinf_to_str_bogus(&m->s) : NULL; + sldns_ede_code reason_bogus = rep->reason_bogus != LDNS_EDE_DNSSEC_BOGUS + ? rep->reason_bogus : errinf_to_reason_bogus(&m->s); edns_opt_append_ede(&r->edns, m->s.region, - rep->reason_bogus, reason); + reason_bogus, reason); free(reason); } error_encode(r_buffer, rcode, &m->s.qinfo, r->qid, diff --git a/util/config_file.c b/util/config_file.c index 50b0e645a..1a8f5ada8 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -2542,6 +2542,7 @@ void errinf(struct module_qstate* qstate, const char* str) } p->next = NULL; p->str = regional_strdup(qstate->region, str); + p->reason_bogus = LDNS_EDE_DNSSEC_BOGUS; if(!p->str) { log_err("malloc failure in validator-error-info string"); return; @@ -2549,7 +2550,34 @@ void errinf(struct module_qstate* qstate, const char* str) /* add at end */ if(qstate->errinf) { struct config_strlist* q = qstate->errinf; - while(q->next) + while(q->next) + q = q->next; + q->next = p; + } else qstate->errinf = p; +} + +void errinf_ede(struct module_qstate* qstate, + const char* str, sldns_ede_code reason_bogus) +{ + struct config_strlist* p; + if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str) + return; + p = (struct config_strlist*)regional_alloc(qstate->region, sizeof(*p)); + if(!p) { + log_err("malloc failure in validator-error-info string"); + return; + } + p->next = NULL; + p->str = regional_strdup(qstate->region, str); + p->reason_bogus = reason_bogus; + if(!p->str) { + log_err("malloc failure in validator-error-info string"); + return; + } + /* add at end */ + if(qstate->errinf) { + struct config_strlist* q = qstate->errinf; + while(q->next) q = q->next; q->next = p; } else qstate->errinf = p; @@ -2600,6 +2628,17 @@ char* errinf_to_str_bogus(struct module_qstate* qstate) return p; } +sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate) +{ + struct config_strlist* s; + for(s=qstate->errinf; s; s=s->next) { + if (s->reason_bogus != LDNS_EDE_DNSSEC_BOGUS) { + return s->reason_bogus; + } + } + return LDNS_EDE_DNSSEC_BOGUS; +} + char* errinf_to_str_servfail(struct module_qstate* qstate) { char buf[20480]; diff --git a/util/config_file.h b/util/config_file.h index b868d9cc8..a7b759e93 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -41,6 +41,7 @@ #ifndef UTIL_CONFIG_FILE_H #define UTIL_CONFIG_FILE_H +#include "sldns/rrdef.h" struct config_stub; struct config_auth; struct config_view; @@ -784,6 +785,8 @@ struct config_strlist { struct config_strlist* next; /** config option string */ char* str; + /** EDE code companion to the error str */ + sldns_ede_code reason_bogus; }; /** @@ -1233,6 +1236,8 @@ char* cfg_ptr_reverse(char* str); * Failures to allocate are logged. */ void errinf(struct module_qstate* qstate, const char* str); +void errinf_ede(struct module_qstate* qstate, const char* str, + sldns_ede_code reason_bogus); /** * Append text to error info: from 1.2.3.4 @@ -1268,6 +1273,9 @@ void errinf_dname(struct module_qstate* qstate, const char* str, */ char* errinf_to_str_bogus(struct module_qstate* qstate); +// @TODO write this +sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate); + /** * Create error info in string. For other servfails. * @param qstate: query state. diff --git a/validator/val_sigcrypt.c b/validator/val_sigcrypt.c index 67db8cfe4..777376c1f 100644 --- a/validator/val_sigcrypt.c +++ b/validator/val_sigcrypt.c @@ -645,7 +645,8 @@ dnskey_verify_rrset_ede(struct module_env* env, struct val_env* ve, verbose(VERB_QUERY, "rrset failed to verify due to a lack of " "signatures"); *reason = "no signatures"; - // @TODO ADD EDE 10 + if(reason_bogus) + *reason_bogus = LDNS_EDE_RRSIGS_MISSING; return sec_status_bogus; } for(i=0; iscratch, env->scratch_buffer, ve, *env->now, rrset, dnskey, dnskey_idx, i, &sortree, &buf_canon, reason, diff --git a/validator/val_utils.c b/validator/val_utils.c index e94a1bb9f..2fa0b37e1 100644 --- a/validator/val_utils.c +++ b/validator/val_utils.c @@ -421,11 +421,23 @@ val_verify_rrset_entry_ede(struct module_env* env, struct val_env* ve, } /** verify that a DS RR hashes to a key and that key signs the set */ +#if 0 static enum sec_status verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason, struct module_qstate* qstate) +{ + return verify_dnskeys_with_ds_rr_ede( env, ve, dnskey_rrset, ds_rrset, + ds_idx, reason, NULL, qstate); +} +#endif + +static enum sec_status +verify_dnskeys_with_ds_rr_ede(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason, + sldns_ede_code *reason_bogus, struct module_qstate* qstate) { enum sec_status sec = sec_status_bogus; size_t i, num, numchecked = 0, numhashok = 0, numsizesupp = 0; @@ -460,8 +472,8 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve, /* Otherwise, we have a match! Make sure that the DNSKEY * verifies *with this key* */ - sec = dnskey_verify_rrset(env, ve, dnskey_rrset, - dnskey_rrset, i, reason, LDNS_SECTION_ANSWER, qstate); + sec = dnskey_verify_rrset_ede(env, ve, dnskey_rrset, dnskey_rrset, + i, reason, reason_bogus, LDNS_SECTION_ANSWER, qstate); if(sec == sec_status_secure) { return sec; } @@ -498,11 +510,22 @@ int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset) return digest_algo; } -enum sec_status +// @TODO change the use of this function to _ede function in authzone.c:8111 +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, struct module_qstate* qstate) +{ + return val_verify_DNSKEY_with_DS_ede(env, ve, dnskey_rrset, ds_rrset, + sigalg, reason, NULL, qstate); +} + +enum sec_status +val_verify_DNSKEY_with_DS_ede(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, + sldns_ede_code *reason_bogus, struct module_qstate* qstate) { /* as long as this is false, we can consider this DS rrset to be * equivalent to no DS rrset. */ @@ -538,8 +561,8 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve, continue; } - sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset, - ds_rrset, i, reason, qstate); + sec = verify_dnskeys_with_ds_rr_ede(env, ve, dnskey_rrset, + ds_rrset, i, reason, reason_bogus, qstate); if(sec == sec_status_insecure) continue; @@ -582,15 +605,26 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve, return sec_status_bogus; } -struct key_entry_key* +struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region, struct module_env* env, struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason, struct module_qstate* qstate) { + return val_verify_new_DNSKEYs_ede(region, env, ve,dnskey_rrset, ds_rrset, + downprot, reason, NULL, qstate); +} + +struct key_entry_key* +val_verify_new_DNSKEYs_ede(struct regional* region, struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason, + sldns_ede_code *reason_bogus, struct module_qstate* qstate) +{ uint8_t sigalg[ALGO_NEEDS_MAX+1]; - enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve, - dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason, qstate); + enum sec_status sec = val_verify_DNSKEY_with_DS_ede(env, ve, + dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason, + reason_bogus, qstate); if(sec == sec_status_secure) { return key_entry_create_rrset(region, @@ -608,12 +642,23 @@ val_verify_new_DNSKEYs(struct regional* region, struct module_env* env, BOGUS_KEY_TTL, *env->now); } -enum sec_status +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, struct module_qstate* qstate) +{ + return val_verify_DNSKEY_with_TA_ede(env, ve, dnskey_rrset, ta_ds, + ta_dnskey, sigalg, reason, NULL, qstate); +} + +enum sec_status +val_verify_DNSKEY_with_TA_ede(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, + sldns_ede_code *reason_bogus, struct module_qstate* qstate) { /* as long as this is false, we can consider this anchor to be * equivalent to no anchor. */ @@ -628,6 +673,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve, verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset " "by name"); *reason = "DNSKEY RRset did not match DS RRset by name"; + if (reason_bogus) + *reason_bogus = LDNS_EDE_DNSKEY_MISSING; return sec_status_bogus; } if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len @@ -636,6 +683,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve, verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset " "by name"); *reason = "DNSKEY RRset did not match anchor RRset by name"; + if (reason_bogus) + *reason_bogus = LDNS_EDE_DNSKEY_MISSING; return sec_status_bogus; } @@ -658,8 +707,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve, ds_get_digest_algo(ta_ds, i) != digest_algo) continue; - sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset, - ta_ds, i, reason, qstate); + sec = verify_dnskeys_with_ds_rr_ede(env, ve, dnskey_rrset, + ta_ds, i, reason, reason_bogus, qstate); if(sec == sec_status_insecure) continue; @@ -732,26 +781,39 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve, return sec_status_bogus; } +#if 0 struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env, struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, struct ub_packed_rrset_key* ta_ds_rrset, struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot, char** reason, struct module_qstate* qstate) +{ + return val_verify_rrset_entry_ede(region, env, ve, dnskey_rrset, + ta_ds_rrset, ta_dnskey_rrset,downprot, reason, NULL, qstate); +} +#endif + +struct key_entry_key* +val_verify_new_DNSKEYs_with_ta_ede(struct regional* region, struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ta_ds_rrset, + struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot, + char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate) { uint8_t sigalg[ALGO_NEEDS_MAX+1]; - enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, + enum sec_status sec = val_verify_DNSKEY_with_TA_ede(env, ve, dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset, - downprot?sigalg:NULL, reason, qstate); + downprot?sigalg:NULL, reason, reason_bogus, qstate); if(sec == sec_status_secure) { - return key_entry_create_rrset(region, + return key_entry_create_rrset(region, dnskey_rrset->rk.dname, dnskey_rrset->rk.dname_len, ntohs(dnskey_rrset->rk.rrset_class), dnskey_rrset, downprot?sigalg:NULL, *env->now); } else if(sec == sec_status_insecure) { return key_entry_create_null(region, dnskey_rrset->rk.dname, - dnskey_rrset->rk.dname_len, + dnskey_rrset->rk.dname_len, ntohs(dnskey_rrset->rk.rrset_class), rrset_get_ttl(dnskey_rrset), *env->now); } @@ -760,7 +822,7 @@ val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env, BOGUS_KEY_TTL, *env->now); } -int +int val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset) { size_t i; diff --git a/validator/val_utils.h b/validator/val_utils.h index b7b0aea1b..1c22a8894 100644 --- a/validator/val_utils.h +++ b/validator/val_utils.h @@ -177,6 +177,11 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env, struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason, struct module_qstate* qstate); +enum sec_status val_verify_DNSKEY_with_DS_ede(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, + sldns_ede_code *reason_bogus, struct module_qstate* qstate); + /** * Verify DNSKEYs with DS and DNSKEY rrset. Like val_verify_DNSKEY_with_DS * but for a trust anchor. @@ -200,6 +205,12 @@ enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env, struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason, struct module_qstate* qstate); +enum sec_status val_verify_DNSKEY_with_TA_ede(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, + sldns_ede_code *reason_bogus, struct module_qstate* qstate); + /** * Verify new DNSKEYs with DS rrset. The DS contains hash values that should * match the DNSKEY keys. @@ -230,6 +241,11 @@ struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region, struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason, struct module_qstate* qstate); +struct key_entry_key* val_verify_new_DNSKEYs_ede(struct regional* region, + struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason, + sldns_ede_code *reason_bogus, struct module_qstate* qstate); /** * Verify rrset with trust anchor: DS and DNSKEY rrset. @@ -261,6 +277,13 @@ struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region, struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot, char** reason, struct module_qstate* qstate); +struct key_entry_key* val_verify_new_DNSKEYs_with_ta_ede(struct regional* region, + struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ta_ds_rrset, + struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot, + char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate); + /** * Determine if DS rrset is usable for validator or not. * Returns true if the algorithms for key and DShash are supported, diff --git a/validator/validator.c b/validator/validator.c index 309128fcd..c5e351e83 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -1720,6 +1720,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id) vq->chase_reply->reason_bogus = LDNS_EDE_RRSIGS_MISSING; errinf_origin(qstate, qstate->reply_origin); vq->chase_reply->security = sec_status_bogus; + // @TODO add EDE 10 - RRSIGs Missing vq->state = VAL_FINISHED_STATE; return 1; } @@ -2313,6 +2314,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; + sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS; int downprot = qstate->env->cfg->harden_algo_downgrade; if(!dnskey_rrset) { @@ -2334,9 +2336,9 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, return kkey; } /* attempt to verify with trust anchor DS and DNSKEY */ - kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve, + kkey = val_verify_new_DNSKEYs_with_ta_ede(qstate->region, qstate->env, ve, dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, downprot, - &reason, qstate); + &reason, &reason_bogus, qstate); if(!kkey) { log_err("out of memory: verifying prime TA"); return NULL; @@ -2355,7 +2357,8 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, /* NOTE: in this case, we should probably reject the trust * anchor for longer, perhaps forever. */ if(qstate->env->cfg->harden_dnssec_stripped) { - errinf(qstate, reason); + // errinf(qstate, reason); + errinf_ede(qstate, reason, reason_bogus); kkey = key_entry_create_bad(qstate->region, ta->name, ta->namelen, ta->dclass, BOGUS_KEY_TTL, *qstate->env->now); @@ -2706,6 +2709,9 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, /* bad response */ verbose(VERB_DETAIL, "Missing DNSKEY RRset in response to " "DNSKEY query."); + + // @TODO add EDE 9 - DNSKEY Missing + if(vq->restart_count < ve->max_restart) { val_blacklist(&vq->chain_blacklist, qstate->region, origin, 1); @@ -2733,6 +2739,7 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, return; } downprot = qstate->env->cfg->harden_algo_downgrade; + // @TODO add _ede vq->key_entry = val_verify_new_DNSKEYs(qstate->region, qstate->env, ve, dnskey, vq->ds_rrset, downprot, &reason, qstate); -- 2.47.2