From: Wouter Wijngaards Date: Thu, 2 Aug 2007 15:45:32 +0000 (+0000) Subject: validator, trust anchors. X-Git-Tag: release-0.5~159 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd3e3ed05ba582bc18f68b92dfea5aa9a6bf5427;p=thirdparty%2Funbound.git validator, trust anchors. git-svn-id: file:///svn/unbound/trunk@482 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/example.conf b/doc/example.conf index 49c636cc0..4d1b04afe 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -151,6 +151,10 @@ server: # module configuration of the server. A string with identifiers # separated by spaces. "iterator" or "validator iterator" # module-config: "validator iterator" + + # File with trusted keys for validation. + # Zone file format, with DS and DNSKEY entries. + # trust-anchor-file: "" # Stub zones. # Create entries like below, to make all queries for 'example.com' and diff --git a/doc/unbound.conf.5 b/doc/unbound.conf.5 index 3811b3687..b2166ecce 100644 --- a/doc/unbound.conf.5 +++ b/doc/unbound.conf.5 @@ -188,6 +188,10 @@ Module configuration, a list of module names separated by spaces, surround the string with quotes (""). The modules can be validator, iterator. Setting this to "iterator" will result in a non-validating server. Setting this to "validator iterator" will turn on validation. +.It \fBtrust-anchor-file:\fR +File with trusted keys for validation. Both DS and DNSKEY entries can appear +in the file. The format of the file is the standard DNS Zone file format. +Default is "", or no trust anchor file. .El .Ss Stub Zone Options diff --git a/util/config_file.c b/util/config_file.c index c803cebf2..94175f074 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -111,6 +111,7 @@ config_create() cfg->hide_version = 0; cfg->identity = NULL; cfg->version = NULL; + cfg->trust_anchor_file = NULL; if(!(cfg->module_conf = strdup("iterator"))) goto error_exit; return cfg; error_exit: @@ -205,6 +206,7 @@ config_delete(struct config_file* cfg) free(cfg->identity); free(cfg->version); free(cfg->module_conf); + free(cfg->trust_anchor_file); free(cfg); } diff --git a/util/config_file.h b/util/config_file.h index 0a66e25e4..71d5ead0e 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -139,6 +139,9 @@ struct config_file { /** the module configuration string */ char* module_conf; + /** file with trusted DS and DNSKEYs in zonefile format */ + char* trust_anchor_file; + /** daemonize, i.e. fork into the background. */ int do_daemonize; }; diff --git a/util/configlexer.lex b/util/configlexer.lex index 365b887b5..d902f988a 100644 --- a/util/configlexer.lex +++ b/util/configlexer.lex @@ -142,6 +142,7 @@ hide-version{COLON} { YDOUT; return VAR_HIDE_VERSION;} identity{COLON} { YDOUT; return VAR_IDENTITY;} version{COLON} { YDOUT; return VAR_VERSION;} module-conf{COLON} { YDOUT; return VAR_MODULE_CONF;} +trust-anchor-file{COLON} { YDOUT; return VAR_TRUST_ANCHOR_FILE;} {NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;} /* Quoted strings. Strip leading and ending quotes */ diff --git a/util/configparser.y b/util/configparser.y index 6e2e68875..b086f8cbe 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -80,6 +80,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_FORWARD_ZONE VAR_FORWARD_HOST VAR_FORWARD_ADDR %token VAR_DO_NOT_QUERY_ADDRESS VAR_HIDE_IDENTITY VAR_HIDE_VERSION %token VAR_IDENTITY VAR_VERSION VAR_HARDEN_GLUE VAR_MODULE_CONF +%token VAR_TRUST_ANCHOR_FILE %% toplevelvars: /* empty */ | toplevelvars toplevelvar ; @@ -112,7 +113,7 @@ content_server: server_num_threads | server_verbosity | server_port | server_harden_short_bufsize | server_harden_large_queries | server_do_not_query_address | server_hide_identity | server_hide_version | server_identity | server_version | - server_harden_glue | server_module_conf + server_harden_glue | server_module_conf | server_trust_anchor_file ; stubstart: VAR_STUB_ZONE { @@ -284,6 +285,13 @@ server_pidfile: VAR_PIDFILE STRING cfg_parser->cfg->pidfile = $2; } ; +server_trust_anchor_file: VAR_TRUST_ANCHOR_FILE STRING + { + OUTYY(("P(server_trust_anchor_file:%s)\n", $2)); + free(cfg_parser->cfg->trust_anchor_file); + cfg_parser->cfg->trust_anchor_file = $2; + } + ; server_hide_identity: VAR_HIDE_IDENTITY STRING { OUTYY(("P(server_hide_identity:%s)\n", $2)); diff --git a/validator/val_anchor.c b/validator/val_anchor.c new file mode 100644 index 000000000..af0fef763 --- /dev/null +++ b/validator/val_anchor.c @@ -0,0 +1,139 @@ +/* + * validator/val_anchor.c - validator trust anchor storage. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains storage for the trust anchors for the validator. + */ +#include "config.h" +#include "validator/val_anchor.h" +#include "util/data/packed_rrset.h" +#include "util/data/dname.h" +#include "util/log.h" +#include "util/region-allocator.h" +#include "util/config_file.h" + +/** compare two trust anchors */ +static int +anchor_cmp(const void* k1, const void* k2) +{ + int m; + struct trust_anchor* n1 = (struct trust_anchor*)k1; + struct trust_anchor* n2 = (struct trust_anchor*)k2; + /* no need to ntohs(class) because sort order is irrelevant */ + if(n1->dclass != n2->dclass) { + if(n1->dclass < n2->dclass) + return -1; + return 1; + } + return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, + &m); +} + +struct val_anchors* +anchors_create() +{ + struct val_anchors* a = (struct val_anchors*)calloc(1, sizeof(*a)); + if(!a) + return NULL; + a->region = region_create(malloc, free); + if(!a->region) { + free(a); + return NULL; + } + a->tree = rbtree_create(anchor_cmp); + if(!a->tree) { + anchors_delete(a); + return NULL; + } + return a; +} + +void +anchors_delete(struct val_anchors* anchors) +{ + if(!anchors) + return; + free(anchors->tree); + region_destroy(anchors->region); + free(anchors); +} + +/** initialise parent pointers in the tree */ +static void +init_parents(struct val_anchors* anchors) +{ + struct trust_anchor* node, *prev = NULL, *p; + int m; + RBTREE_FOR(node, struct trust_anchor*, anchors->tree) { + node->parent = NULL; + if(!prev || prev->dclass != node->dclass) { + prev = node; + continue; + } + (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, + node->namelabs, &m); /* we know prev is smaller */ + /* sort order like: . com. bla.com. zwb.com. net. */ + /* find the previous, or parent-parent-parent */ + for(p = prev; p; p = p->parent) + /* looking for name with few labels, a parent */ + if(p->namelabs <= m) { + /* ==: since prev matched m, this is closest*/ + /* <: prev matches more, but is not a parent, + * this one is a (grand)parent */ + node->parent = p; + break; + } + prev = node; + } +} + +int +anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg) +{ + if(cfg->trust_anchor_file && cfg->trust_anchor_file[0]) { + /* read trust anchor file */ + } + init_parents(anchors); + return 1; +} + +struct trust_anchor* +anchors_lookup(struct val_anchors* anchors, + uint8_t* qname, size_t qname_len, uint16_t qclass) +{ + return NULL; +} diff --git a/validator/val_anchor.h b/validator/val_anchor.h new file mode 100644 index 000000000..f0de67eaa --- /dev/null +++ b/validator/val_anchor.h @@ -0,0 +1,137 @@ +/* + * validator/val_anchor.h - validator trust anchor storage. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains storage for the trust anchors for the validator. + */ + +#ifndef VALIDATOR_VAL_ANCHOR_H +#define VALIDATOR_VAL_ANCHOR_H +#include "util/rbtree.h" +struct region; +struct trust_anchor; +struct config_file; + +/** + * Trust anchor store. + */ +struct val_anchors { + /** region where trust anchors are allocated */ + struct region* region; + /** + * Anchors are store in this tree. Sort order is chosen, so that + * dnames are in nsec-like order. A lookup on class, name will return + * an exact match of the closest match, with the ancestor needed. + * contents of type trust_anchor. + */ + rbtree_t* tree; +}; + +/** + * Trust anchor key + */ +struct ta_key { + /** next in list */ + struct ta_key* next; + /** rdata, in wireformat of the key RR. */ + uint8_t* data; + /** length of the rdata */ + size_t len; + /** DNS type (host format) of the key, DS or DNSKEY */ + uint16_t type; +}; + +/** + * A trust anchor in the trust anchor store. + * Unique by name, class. + */ +struct trust_anchor { + /** rbtree node, key is this structure */ + rbnode_t node; + /** name of this trust anchor */ + uint8_t* name; + /** number of labels in name of rrset */ + int namelabs; + /** the ancestor in the trustanchor tree */ + struct trust_anchor* parent; + /** + * List of DS or DNSKEY rrs that form the trust anchor. + * It is allocated in the region. + */ + struct ta_key* keylist; + /** number of DSs in the keylist */ + size_t numDS; + /** number of DNSKEYs in the keylist */ + size_t numDNSKEY; + /** class of the trust anchor */ + uint16_t dclass; +}; + +/** + * Create trust anchor storage + * @return new storage or NULL on error. + */ +struct val_anchors* anchors_create(); + +/** + * Delete trust anchor storage. + * @param anchors: to delete. + */ +void anchors_delete(struct val_anchors* anchors); + +/** + * Process trust anchor config. + * @param anchors: struct anchor storage + * @param cfg: config options. + * @return 0 on error. + */ +int anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg); + +/** + * Given a qname/qclass combination, find the trust anchor closest above it. + * Or return NULL if none exists. + * + * @param anchors: struct anchor storage + * @param qname: query name, uncompressed wireformat. + * @param qname_len: length of qname. + * @param qclass: class to query for. + * @return the trust anchor or NULL if none is found. + */ +struct trust_anchor* anchors_lookup(struct val_anchors* anchors, + uint8_t* qname, size_t qname_len, uint16_t qclass); + +#endif /* VALIDATOR_VAL_ANCHOR_H */ diff --git a/validator/validator.c b/validator/validator.c index 90aa0e3f8..d03808b1b 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -41,12 +41,30 @@ */ #include "config.h" #include "validator/validator.h" +#include "validator/val_anchor.h" #include "services/cache/dns.h" #include "util/module.h" #include "util/log.h" #include "util/net_help.h" #include "util/region-allocator.h" +/** apply config settings to validator */ +static int +val_apply_cfg(struct val_env* val_env, struct config_file* cfg) +{ + if(!val_env->anchors) + val_env->anchors = anchors_create(); + if(!val_env->anchors) { + log_err("out of memory"); + return 0; + } + if(!anchors_apply_cfg(val_env->anchors, cfg)) { + log_err("validator: error in trustanchors config"); + return 0; + } + return 1; +} + /** validator init */ static int val_init(struct module_env* env, int id) @@ -58,10 +76,10 @@ val_init(struct module_env* env, int id) return 0; } env->modinfo[id] = (void*)val_env; - /*if(!val_apply_cfg(val_env, env->cfg)) { + if(!val_apply_cfg(val_env, env->cfg)) { log_err("validator: could not apply configuration settings."); return 0; - }*/ + } return 1; } @@ -73,6 +91,7 @@ val_deinit(struct module_env* env, int id) if(!env || !env->modinfo || !env->modinfo[id]) return; val_env = (struct val_env*)env->modinfo[id]; + anchors_delete(val_env->anchors); free(val_env); } diff --git a/validator/validator.h b/validator/validator.h index 03d2d2c17..a664c6526 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -44,15 +44,14 @@ #define VALIDATOR_VALIDATOR_H struct module_func_block; #include "util/data/msgreply.h" +struct val_anchors; /** * Global state for the validator. */ struct val_env { - /** global state placeholder */ - int option; - /** trusted key storage */ + struct val_anchors* anchors; /** key cache */ };