]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
validator work.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 2 Aug 2007 14:36:20 +0000 (14:36 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 2 Aug 2007 14:36:20 +0000 (14:36 +0000)
git-svn-id: file:///svn/unbound/trunk@481 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
validator/validator.c
validator/validator.h

index f0574e59eab8e7df4299d0d3c7acdcc3d99689b2..b9554f4b75b34da6ed6b753dce7af623aef94a31 100644 (file)
@@ -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
index d6092f2b38bfda5d2f42dd3154e7133cdaa1c13e..90aa0e3f87c3c719065065b716128cac17ed6519 100644 (file)
  */
 #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";
 }
index b25dfc124183e3bbeed011c40cd6864b7d604efa..03d2d2c176faa179cc03f5dfe804e45c121a8e8c 100644 (file)
@@ -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;
 };
 
 /**