aboutsummaryrefslogtreecommitdiff
path: root/validator
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 11:56:52 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 11:56:52 +0000
commit4289761a7b61df4b64c11ada446a187df61e6a1e (patch)
treeed7ceb7a1652fb9f865fafd21fbe18d1a3b5f79d /validator
parent197f1a0fe3e81cde0cd25a3a1f37ebedf9a99488 (diff)
downloadsrc-vendor/unbound/1.7.1.tar.gz
src-vendor/unbound/1.7.1.zip
Vendor import of Unbound 1.7.1.vendor/unbound/1.7.1
Diffstat (limited to 'validator')
-rw-r--r--validator/val_anchor.c41
-rw-r--r--validator/val_anchor.h15
-rw-r--r--validator/val_neg.c14
-rw-r--r--validator/val_neg.h6
-rw-r--r--validator/val_secalgo.c16
-rw-r--r--validator/validator.c54
-rw-r--r--validator/validator.h7
7 files changed, 151 insertions, 2 deletions
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; i<numtag; i++) {
+ if(*tl == keytag) {
+ free(taglist);
+ return 1;
+ }
+ tl++;
+ }
+ free(taglist);
+ return 0;
+}
diff --git a/validator/val_anchor.h b/validator/val_anchor.h
index 318a2b227cc7..a2a795d093d2 100644
--- a/validator/val_anchor.h
+++ b/validator/val_anchor.h
@@ -227,4 +227,19 @@ void anchors_delete_insecure(struct val_anchors* anchors, uint16_t c,
*/
size_t anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num);
+/**
+ * Check if there is a trust anchor for given zone with this keytag.
+ *
+ * @param anchors: anchor storage
+ * @param name: name of trust anchor (wireformat)
+ * @param namelabs: labels in name
+ * @param namelen: length of name
+ * @param dclass: class of trust anchor
+ * @param keytag: keytag
+ * @return 1 if there is a trust anchor in the trustachor store for this zone
+ * and keytag, else 0.
+ */
+int anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs,
+ size_t namelen, uint16_t dclass, uint16_t keytag);
+
#endif /* VALIDATOR_VAL_ANCHOR_H */
diff --git a/validator/val_neg.c b/validator/val_neg.c
index 541238148307..c494a6be637f 100644
--- a/validator/val_neg.c
+++ b/validator/val_neg.c
@@ -1515,6 +1515,10 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
return NULL;
if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL))
return NULL;
+
+ lock_basic_lock(&neg->lock);
+ 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 <ctype.h>
#include "validator/validator.h"
#include "validator/val_anchor.h"
#include "validator/val_kcache.h"
@@ -478,6 +479,31 @@ generate_keytag_query(struct module_qstate* qstate, int id,
}
/**
+ * 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.
* The trust anchor can be DNSKEY or DS and does not have to be signed.
@@ -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.
*/