From: Wouter Wijngaards Date: Thu, 2 Aug 2007 14:36:20 +0000 (+0000) Subject: validator work. X-Git-Tag: release-0.5~160 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce12d59957a7353fd8f2dc8485695d3020e351be;p=thirdparty%2Funbound.git validator work. git-svn-id: file:///svn/unbound/trunk@481 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index f0574e59e..b9554f4b7 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -6,6 +6,7 @@ so that the classification is lame. - validator module exists, and does nothing but pass through, with calling of next module and return. + - validator work. 1 August 2007: Wouter - set version to 0.5 diff --git a/validator/validator.c b/validator/validator.c index d6092f2b3..90aa0e3f8 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -41,8 +41,11 @@ */ #include "config.h" #include "validator/validator.h" +#include "services/cache/dns.h" #include "util/module.h" #include "util/log.h" +#include "util/net_help.h" +#include "util/region-allocator.h" /** validator init */ static int @@ -73,6 +76,88 @@ val_deinit(struct module_env* env, int id) free(val_env); } +/** allocate new validator query state */ +static struct val_qstate* +val_new(struct module_qstate* qstate, int id) +{ + struct val_qstate* vq = (struct val_qstate*)region_alloc( + qstate->region, sizeof(*vq)); + log_assert(!qstate->minfo[id]); + if(!vq) + return NULL; + memset(vq, 0, sizeof(*vq)); + qstate->minfo[id] = vq; + vq->state = VAL_INIT_STATE; + if(!qstate->return_msg || qstate->return_rcode != LDNS_RCODE_NOERROR) { + /* create a message to verify */ + verbose(VERB_ALGO, "constructing reply for validation"); + vq->orig_msg = (struct dns_msg*)region_alloc(qstate->region, + sizeof(struct dns_msg)); + if(!vq->orig_msg) + return NULL; + vq->orig_msg->qinfo = qstate->qinfo; + vq->orig_msg->rep = (struct reply_info*)region_alloc( + qstate->region, sizeof(struct reply_info)); + if(!vq->orig_msg->rep) + return NULL; + memset(vq->orig_msg->rep, 0, sizeof(struct reply_info)); + vq->orig_msg->rep->flags = (uint16_t)(qstate->return_rcode&0xf) + |BIT_QR|BIT_RA|(qstate->query_flags|(BIT_CD|BIT_RD)); + vq->orig_msg->rep->qdcount = 1; + } else { + vq->orig_msg = qstate->return_msg; + } + vq->qchase = qstate->qinfo; + vq->chase_reply = vq->orig_msg->rep; + return vq; +} + +/** + * Process init state for validator. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + * @return true to continue processing + */ +static int +processInit(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + return 0; +} + +/** + * Handle validator state. + * If a method returns true, the next state is started. If false, then + * processing will stop. + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + */ +static void +val_handle(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + int cont = 1; + while(cont) { + verbose(VERB_ALGO, "val handle processing q with state %s", + val_state_to_string(vq->state)); + switch(vq->state) { + case VAL_INIT_STATE: + cont = processInit(qstate, vq, ve, id); + break; + default: + log_warn("validator: invalid state %d", + vq->state); + cont = 0; + break; + } + } +} + /** validator operate on a query */ static void val_operate(struct module_qstate* qstate, enum module_ev event, int id, @@ -83,9 +168,8 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id, verbose(VERB_DETAIL, "validator[module %d] operate: extstate:%s " "event:%s", id, strextstate(qstate->ext_state[id]), strmodulevent(event)); - if(vq) log_query_info(VERB_DETAIL, "validator operate: query", + log_query_info(VERB_DETAIL, "validator operate: query", &qstate->qinfo); - (void)ve; (void)outbound; if(event == module_event_new || event == module_event_pass) { /* pass request to next module, to get it */ @@ -94,11 +178,35 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id, return; } if(event == module_event_moddone) { - /* we're done */ + /* check if validation is needed */ verbose(VERB_ALGO, "validator: nextmodule returned"); - qstate->ext_state[id] = module_finished; + if(qstate->return_rcode != LDNS_RCODE_NOERROR && + qstate->return_rcode != LDNS_RCODE_NXDOMAIN && + qstate->return_rcode != LDNS_RCODE_YXDOMAIN) { + verbose(VERB_ALGO, "rcode for error not validated"); + qstate->ext_state[id] = module_finished; + return; + } + if(qstate->query_flags & BIT_CD) { + /* no need to validate this */ + verbose(VERB_ALGO, "CD bit set: query not validated"); + qstate->ext_state[id] = module_finished; + return; + } + /* create state to start validation */ + qstate->ext_state[id] = module_error; /* override this */ + if(!vq) { + vq = val_new(qstate, id); + if(!vq) { + log_err("validator: malloc failure"); + qstate->ext_state[id] = module_error; + return; + } + } + val_handle(qstate, vq, ve, id); return; } + log_err("validator: bad event %s", strmodulevent(event)); qstate->ext_state[id] = module_error; return; } @@ -148,7 +256,15 @@ const char* val_state_to_string(enum val_state state) { switch(state) { - case VAL_STATE_INIT: return "VAL_STATE_INIT"; + case VAL_INIT_STATE: return "VAL_INIT_STATE"; + case VAL_PRIME_RESP_STATE: return "VAL_PRIME_RESP_STATE"; + case VAL_FINDKEY_STATE: return "VAL_FINDKEY_STATE"; + case VAL_FINDKEY_DS_RESP_STATE: + return "VAL_FINDKEY_DS_RESP_STATE"; + case VAL_FINDKEY_DNSKEY_RESP_STATE: + return "VAL_FINDKEY_DNSKEY_RESP_STATE"; + case VAL_VALIDATE_STATE: return "VAL_VALIDATE_STATE"; + case VAL_FINISHED_STATE: return "VAL_FINISHED_STATE"; } return "UNKNOWN VALIDATOR STATE"; } diff --git a/validator/validator.h b/validator/validator.h index b25dfc124..03d2d2c17 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -43,6 +43,7 @@ #ifndef VALIDATOR_VALIDATOR_H #define VALIDATOR_VALIDATOR_H struct module_func_block; +#include "util/data/msgreply.h" /** * Global state for the validator. @@ -50,6 +51,10 @@ struct module_func_block; struct val_env { /** global state placeholder */ int option; + + /** trusted key storage */ + + /** key cache */ }; /** @@ -57,7 +62,19 @@ struct val_env { */ enum val_state { /** initial state for validation */ - VAL_STATE_INIT = 0 + VAL_INIT_STATE = 0, + /** handle response to trust anchor priming query */ + VAL_PRIME_RESP_STATE, + /** find the proper keys for validation, follow trust chain */ + VAL_FINDKEY_STATE, + /** handle response to DS query to make trust chain */ + VAL_FINDKEY_DS_RESP_STATE, + /** handle response to DNSKEY query to make trust chain */ + VAL_FINDKEY_DNSKEY_RESP_STATE, + /** validate the answer, using found key entry */ + VAL_VALIDATE_STATE, + /** finish up */ + VAL_FINISHED_STATE }; /** @@ -68,6 +85,24 @@ struct val_qstate { * State of the validator module. */ enum val_state state; + + /** + * The original message we have been given to validate. + */ + struct dns_msg* orig_msg; + + /** + * The query name we have chased to; qname after following CNAMEs + */ + struct query_info qchase; + + /** + * The chased reply, extract from original message. Can be: + * o CNAME + * o DNAME + CNAME + * o answer plus authority, additional (nsecs). + */ + struct reply_info* chase_reply; }; /**