From 4289761a7b61df4b64c11ada446a187df61e6a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Sat, 12 May 2018 11:56:52 +0000 Subject: Vendor import of Unbound 1.7.1. --- validator/val_anchor.c | 41 +++++++++++++++++++++++++++++++++++++ validator/val_anchor.h | 15 ++++++++++++++ validator/val_neg.c | 14 ++++++++++++- validator/val_neg.h | 6 ++++++ validator/val_secalgo.c | 16 ++++++++++++++- validator/validator.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ validator/validator.h | 7 +++++++ 7 files changed, 151 insertions(+), 2 deletions(-) (limited to 'validator') diff --git a/validator/val_anchor.c b/validator/val_anchor.c index 6c6322447d6d..8ae9e7f3bce0 100644 --- a/validator/val_anchor.c +++ b/validator/val_anchor.c @@ -1309,3 +1309,44 @@ anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num) qsort(list, ret, sizeof(*list), keytag_compare); return ret; } + +int +anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs, + size_t namelen, uint16_t dclass, uint16_t keytag) +{ + uint16_t* taglist; + uint16_t* tl; + size_t numtag, i; + struct trust_anchor* anchor = anchor_find(anchors, + name, namelabs, namelen, dclass); + if(!anchor) + return 0; + if(!anchor->numDS && !anchor->numDNSKEY) { + lock_basic_unlock(&anchor->lock); + return 0; + } + + taglist = calloc(anchor->numDS + anchor->numDNSKEY, sizeof(*taglist)); + if(!taglist) { + lock_basic_unlock(&anchor->lock); + return 0; + } + + numtag = anchor_list_keytags(anchor, taglist, + anchor->numDS+anchor->numDNSKEY); + lock_basic_unlock(&anchor->lock); + if(!numtag) { + free(taglist); + return 0; + } + tl = taglist; + for(i=0; ilock); + neg->num_neg_cache_noerror++; + lock_basic_unlock(&neg->lock); return msg; } else if(nsec && val_nsec_proves_name_error(nsec, qinfo->qname)) { if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len, @@ -1578,7 +1582,7 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo, rcode = LDNS_RCODE_NXDOMAIN; else if(!nsec_proves_nodata(wcrr, &wc_qinfo, &nodata_wc) || nodata_wc) - /* &nodata_wc shoudn't be set, wc_qinfo + /* &nodata_wc shouldn't be set, wc_qinfo * already contains wildcard domain. */ /* NSEC doesn't prove anything for * wildcard. */ @@ -1595,6 +1599,14 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo, if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL)) return NULL; + /* Increment statistic counters */ + lock_basic_lock(&neg->lock); + if(rcode == LDNS_RCODE_NOERROR) + neg->num_neg_cache_noerror++; + else if(rcode == LDNS_RCODE_NXDOMAIN) + neg->num_neg_cache_nxdomain++; + lock_basic_unlock(&neg->lock); + FLAGS_SET_RCODE(msg->rep->flags, rcode); return msg; } diff --git a/validator/val_neg.h b/validator/val_neg.h index 00dad6df1f5c..877f5c944747 100644 --- a/validator/val_neg.h +++ b/validator/val_neg.h @@ -80,6 +80,12 @@ struct val_neg_cache { size_t max; /** max nsec3 iterations allowed */ size_t nsec3_max_iter; + /** number of times neg cache records were used to generate NOERROR + * responses. */ + size_t num_neg_cache_noerror; + /** number of times neg cache records were used to generate NXDOMAIN + * responses. */ + size_t num_neg_cache_nxdomain; }; /** diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c index 7f5c5181fd2d..95200a48b61b 100644 --- a/validator/val_secalgo.c +++ b/validator/val_secalgo.c @@ -231,7 +231,10 @@ dnskey_algo_id_is_supported(int id) #ifdef USE_ED25519 case LDNS_ED25519: #endif -#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA) +#ifdef USE_ED448 + case LDNS_ED448: +#endif +#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA) || defined(USE_ED25519) || defined(USE_ED448) return 1; #endif @@ -569,6 +572,17 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, *digest_type = NULL; break; #endif /* USE_ED25519 */ +#ifdef USE_ED448 + case LDNS_ED448: + *evp_key = sldns_ed4482pkey_raw(key, keylen); + if(!*evp_key) { + verbose(VERB_QUERY, "verify: " + "sldns_ed4482pkey_raw failed"); + return 0; + } + *digest_type = NULL; + break; +#endif /* USE_ED448 */ default: verbose(VERB_QUERY, "verify: unknown algorithm %d", algo); diff --git a/validator/validator.c b/validator/validator.c index 5ed45e9bdefd..5777b2932cb4 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -40,6 +40,7 @@ * According to RFC 4034. */ #include "config.h" +#include #include "validator/validator.h" #include "validator/val_anchor.h" #include "validator/val_kcache.h" @@ -477,6 +478,31 @@ generate_keytag_query(struct module_qstate* qstate, int id, return 1; } +/** + * Get keytag as uint16_t from string + * + * @param start: start of string containing keytag + * @param keytag: pointer where to store the extracted keytag + * @return: 1 if keytag was extracted, else 0. + */ +static int +sentinel_get_keytag(char* start, uint16_t* keytag) { + char* keytag_str; + char* e = NULL; + keytag_str = calloc(1, SENTINEL_KEYTAG_LEN + 1 /* null byte */); + if(!keytag_str) + return 0; + memmove(keytag_str, start, SENTINEL_KEYTAG_LEN); + keytag_str[SENTINEL_KEYTAG_LEN] = '\0'; + *keytag = (uint16_t)strtol(keytag_str, &e, 10); + if(!e || *e != '\0') { + free(keytag_str); + return 0; + } + free(keytag_str); + return 1; +} + /** * Prime trust anchor for use. * Generate and dispatch a priming query for the given trust anchor. @@ -2223,6 +2249,34 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, vq->orig_msg->rep->security = sec_status_indeterminate; } + if(vq->orig_msg->rep->security == sec_status_secure && + qstate->env->cfg->root_key_sentinel && + (qstate->qinfo.qtype == LDNS_RR_TYPE_A || + qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)) { + char* keytag_start; + uint16_t keytag; + if(*qstate->qinfo.qname == strlen(SENTINEL_IS) + + SENTINEL_KEYTAG_LEN && + dname_lab_startswith(qstate->qinfo.qname, SENTINEL_IS, + &keytag_start)) { + if(sentinel_get_keytag(keytag_start, &keytag) && + !anchor_has_keytag(qstate->env->anchors, + (uint8_t*)"", 1, 0, vq->qchase.qclass, keytag)) { + vq->orig_msg->rep->security = + sec_status_secure_sentinel_fail; + } + } else if(*qstate->qinfo.qname == strlen(SENTINEL_NOT) + + SENTINEL_KEYTAG_LEN && + dname_lab_startswith(qstate->qinfo.qname, SENTINEL_NOT, + &keytag_start)) { + if(sentinel_get_keytag(keytag_start, &keytag) && + anchor_has_keytag(qstate->env->anchors, + (uint8_t*)"", 1, 0, vq->qchase.qclass, keytag)) { + vq->orig_msg->rep->security = + sec_status_secure_sentinel_fail; + } + } + } /* store results in cache */ if(qstate->query_flags&BIT_RD) { /* if secure, this will override cache anyway, no need diff --git a/validator/validator.h b/validator/validator.h index 9a591078f71c..9e4c8a9414a1 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -67,6 +67,13 @@ struct config_strlist; /** max number of query restarts, number of IPs to probe */ #define VAL_MAX_RESTART_COUNT 5 +/** Root key sentinel is ta preamble */ +#define SENTINEL_IS "root-key-sentinel-is-ta-" +/** Root key sentinel is not ta preamble */ +#define SENTINEL_NOT "root-key-sentinel-not-ta-" +/** Root key sentinal keytag length */ +#define SENTINEL_KEYTAG_LEN 5 + /** * Global state for the validator. */ -- cgit v1.2.3