]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1609. [func] dig now has support to chase DNSSEC signature chains.
authorMark Andrews <marka@isc.org>
Tue, 13 Apr 2004 02:39:35 +0000 (02:39 +0000)
committerMark Andrews <marka@isc.org>
Tue, 13 Apr 2004 02:39:35 +0000 (02:39 +0000)
                        Requires -DDIG_SIGCHASE=1 to be set in STD_CDEFINES.

CHANGES
README
bin/dig/Makefile.in
bin/dig/dig.c
bin/dig/dig.docbook
bin/dig/dighost.c
bin/dig/host.c
bin/dig/include/dig/dig.h
bin/dig/nslookup.c

diff --git a/CHANGES b/CHANGES
index e6068f4bd34345cd2a6f85cb8eea619935f42893..0b4e537943fc674fead5a8a2d3d3cd11e8251b36 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+1609.  [func]          dig now has support to chase DNSSEC signature chains.
+                       Requires -DDIG_SIGCHASE=1 to be set in STD_CDEFINES.
+
 1608.  [func]          dig and host now accept -4/-6 to select IP transport
                        to use when making queries.
 
diff --git a/README b/README
index 717d8fd47deaf278d2e21dcac40134b192793507..aa7ce9503b7a03fdce5d2a7df08a468c9d8c3244 100644 (file)
--- a/README
+++ b/README
@@ -237,7 +237,10 @@ Building
 
                Possible settings:
                Change the default syslog facility of named/lwresd.
-               e.g. -DISC_FACILITY=LOG_LOCAL0  
+                 -DISC_FACILITY=LOG_LOCAL0     
+               Enable DNSSEC signature chasing support in dig.
+                 -DDIG_SIGCHASE=1 (sets -DDIG_SIGCHASE_TD=1 and
+                                   -DDIG_SIGCHASE_BU=1)
 
        To build shared libraries, specify "--with-libtool" on the
        configure command line.
index c7b43377af478088ad113f2fd0284c94088d001a..e74e55c9773640fc1ed71607687439fc81431767 100644 (file)
@@ -13,7 +13,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: Makefile.in,v 1.33 2004/03/05 04:57:29 marka Exp $
+# $Id: Makefile.in,v 1.34 2004/04/13 02:39:33 marka Exp $
 
 srcdir =       @srcdir@
 VPATH =                @srcdir@
@@ -27,6 +27,7 @@ CINCLUDES =   -I${srcdir}/include ${DNS_INCLUDES} ${BIND9_INCLUDES} \
                ${ISC_INCLUDES} ${LWRES_INCLUDES}
 
 CDEFINES =     -DVERSION=\"${VERSION}\"
+               
 CWARNINGS =
 
 ISCCFGLIBS =   ../../lib/isccfg/libisccfg.@A@
@@ -96,4 +97,6 @@ install:: dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@ installdirs
                host@EXEEXT@ ${DESTDIR}${bindir}
        ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
                nslookup@EXEEXT@ ${DESTDIR}${bindir}
-       for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man1; done
+       for m in ${MANPAGES}; do \
+               ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man1; \
+               done
index 98c50168decd086f68b15a563d09917e110934f8..5d72a0f80d1cafbf30bde93af0f57848bcda2607 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dig.c,v 1.187 2004/04/13 01:09:36 marka Exp $ */
+/* $Id: dig.c,v 1.188 2004/04/13 02:39:34 marka Exp $ */
 
 #include <config.h>
 #include <stdlib.h>
 
 #include <dig/dig.h>
 
+#ifdef DIG_SIGCHASE
+#ifndef DIG_SIGCHASE_BU
+#define DIG_SIGCHASE_BU 1
+#endif
+#ifndef DIG_SIGCHASE_TD
+#define DIG_SIGCHASE_TD 1
+#endif
+#endif
+
 extern ISC_LIST(dig_lookup_t) lookup_list;
 extern dig_serverlist_t server_list;
 extern ISC_LIST(dig_searchlist_t) search_list;
@@ -69,6 +78,9 @@ extern isc_sockaddr_t bind_address;
 extern char keynametext[MXNAME];
 extern char keyfile[MXNAME];
 extern char keysecret[MXNAME];
+#ifdef DIG_SIGCHASE
+extern char trustedkey[MXNAME];
+#endif
 extern dns_tsigkey_t *key;
 extern isc_boolean_t validated;
 extern isc_taskmgr_t *taskmgr;
@@ -205,6 +217,13 @@ help(void) {
 "                 +[no]identify       (ID responders in short answers)\n"
 "                 +[no]trace          (Trace delegation down from root)\n"
 "                 +[no]dnssec         (Request DNSSEC records)\n"
+#ifdef DIG_SIGCHASE
+"                 +[no]sigchase       (Chase DNSSEC signatures)\n"
+"                 +trusted-key=####   (Trusted Key when chasing DNSSEC sigs)\n"
+#if DIG_SIGCHASE_TD
+"                 +[no]topdown        (Do DNSSEC validation top down mode)\n"
+#endif
+#endif
 "                 +[no]multiline      (Print records in an expanded format)\n"
 "        global d-opts and servers (before host name) affect all queries.\n"
 "        local d-opts and servers (after host name) affect only that lookup.\n"
@@ -350,6 +369,51 @@ short_answer(dns_message_t *msg, dns_messagetextflag_t flags,
 
        return (ISC_R_SUCCESS);
 }
+#ifdef DIG_SIGCHASE
+isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+             isc_buffer_t *target)
+{
+       isc_result_t result;
+       dns_master_style_t *style = NULL;
+       unsigned int styleflags = 0;
+
+       if (rdataset == NULL || owner_name == NULL || target == NULL)
+               return(ISC_FALSE);
+
+       styleflags |= DNS_STYLEFLAG_REL_OWNER;
+       if (nottl)
+               styleflags |= DNS_STYLEFLAG_NO_TTL;
+       if (noclass)
+               styleflags |= DNS_STYLEFLAG_NO_CLASS;
+       if (multiline) {
+               styleflags |= DNS_STYLEFLAG_OMIT_OWNER;
+               styleflags |= DNS_STYLEFLAG_OMIT_CLASS;
+               styleflags |= DNS_STYLEFLAG_REL_DATA;
+               styleflags |= DNS_STYLEFLAG_OMIT_TTL;
+               styleflags |= DNS_STYLEFLAG_TTL;
+               styleflags |= DNS_STYLEFLAG_MULTILINE;
+               styleflags |= DNS_STYLEFLAG_COMMENT;
+       }
+       if (multiline || (nottl && noclass))
+               result = dns_master_stylecreate(&style, styleflags,
+                                               24, 24, 24, 32, 80, 8, mctx);
+       else if (nottl || noclass)
+               result = dns_master_stylecreate(&style, styleflags,
+                                               24, 24, 32, 40, 80, 8, mctx);
+       else 
+               result = dns_master_stylecreate(&style, styleflags,
+                                               24, 32, 40, 48, 80, 8, mctx);
+       check_result(result, "dns_master_stylecreate");
+
+       result = dns_master_rdatasettotext(owner_name, rdataset, style, target);
+
+       if (style != NULL)
+               dns_master_styledestroy(&style, mctx);
+  
+       return(result);
+}
+#endif
 
 /*
  * Callback from dighost.c to print the reply from a server
@@ -450,8 +514,7 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
 
 repopulate_buffer:
 
-       if (query->lookup->comments && headers && !short_form)
-       {
+       if (query->lookup->comments && headers && !short_form) {
                result = dns_message_pseudosectiontotext(msg,
                         DNS_PSEUDOSECTION_OPT,
                         style, flags, buf);
@@ -649,17 +712,20 @@ plus_option(char *option, isc_boolean_t is_batchfile,
        char option_store[256];
        char *cmd, *value, *ptr;
        isc_boolean_t state = ISC_TRUE;
+#ifdef DIG_SIGCHASE
+       size_t n;
+#endif
 
        strncpy(option_store, option, sizeof(option_store));
        option_store[sizeof(option_store)-1]=0;
        ptr = option_store;
        cmd = next_token(&ptr,"=");
        if (cmd == NULL) {
-               printf(";; Invalid option %s\n",option_store);
+               printf(";; Invalid option %s\n", option_store);
                return;
        }
        value = ptr;
-       if (strncasecmp(cmd,"no",2)==0) {
+       if (strncasecmp(cmd, "no", 2)==0) {
                cmd += 2;
                state = ISC_FALSE;
        }
@@ -899,6 +965,14 @@ plus_option(char *option, isc_boolean_t is_batchfile,
                                lookup->stats = ISC_FALSE;
                        }
                        break;
+#ifdef DIG_SIGCHASE
+               case 'i': /* sigchase */
+                       FULLCHECK("sigchase");
+                       lookup->sigchase = state;
+                       if (lookup->sigchase)
+                               lookup->dnssec = ISC_TRUE;
+                       break;  
+#endif
                case 't': /* stats */
                        FULLCHECK("stats");
                        lookup->stats = state;
@@ -924,6 +998,12 @@ plus_option(char *option, isc_boolean_t is_batchfile,
                        if (timeout == 0)
                                timeout = 1;
                        break;
+#if DIG_SIGCHASE_TD
+               case 'o': /* topdown */ 
+                       FULLCHECK("topdown");
+                       lookup->do_topdown = state;
+                       break;
+#endif
                case 'r':
                        switch (cmd[2]) {
                        case 'a': /* trace */
@@ -937,7 +1017,7 @@ plus_option(char *option, isc_boolean_t is_batchfile,
                                        lookup->stats = ISC_FALSE;
                                        lookup->section_additional = ISC_FALSE;
                                        lookup->section_authority = ISC_TRUE;
-                                       lookup->section_question = ISC_FALSE;
+                               lookup->section_question = ISC_FALSE;
                                }
                                break;
                        case 'i': /* tries */
@@ -947,10 +1027,22 @@ plus_option(char *option, isc_boolean_t is_batchfile,
                                if (!state)
                                        goto invalid_option;
                                lookup->retries = parse_uint(value, "tries",
-                                                      MAXTRIES);
+                                                            MAXTRIES);
                                if (lookup->retries == 0)
                                        lookup->retries = 1;
                                break;
+#ifdef DIG_SIGCHASE
+                       case 'u': /* trusted-key */
+                               if (value == NULL) 
+                                       goto need_value;
+                               if (!state)
+                                       goto invalid_option;
+                               n = strlcpy(trustedkey, ptr,
+                                           sizeof(trustedkey));
+                               if (n >= sizeof(trustedkey))
+                                       fatal("trusted key too large");
+                               break;
+#endif
                        default:
                                goto invalid_option;
                        }
@@ -1049,8 +1141,9 @@ dash_option(char *option, char *next, dig_lookup_t **lookup,
        case 'b':
                hash = strchr(value, '#');
                if (hash != NULL) {
-                       srcport = (in_port_t) parse_uint(hash + 1,
-                                                        "port number", MAXPORT);
+                       srcport = (in_port_t)
+                               parse_uint(hash + 1,
+                                          "port number", MAXPORT);
                        *hash = '\0';
                } else
                        srcport = 0;
@@ -1105,8 +1198,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup,
                        result = dns_rdatatype_fromtext(&rdtype,
                                                (isc_textregion_t *)&tr);
                        if (result == ISC_R_SUCCESS &&
-                           rdtype == dns_rdatatype_ixfr)
-                       {
+                           rdtype == dns_rdatatype_ixfr) {
                                result = DNS_R_UNKNOWN;
                        }
                }
@@ -1153,8 +1245,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup,
        case 'x':
                *lookup = clone_lookup(default_lookup, ISC_TRUE);
                if (get_reverse(textname, sizeof(textname), value,
-                               ip6_int, ISC_FALSE) == ISC_R_SUCCESS)
-               {
+                               ip6_int, ISC_FALSE) == ISC_R_SUCCESS) {
                        strncpy((*lookup)->textname, textname,
                                sizeof((*lookup)->textname));
                        debug("looking up %s", (*lookup)->textname);
@@ -1166,8 +1257,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup,
                        if (!(*lookup)->rdclassset)
                                (*lookup)->rdclass = dns_rdataclass_in;
                        (*lookup)->new_search = ISC_TRUE;
-                       if (*lookup && *firstarg)
-                       {
+                       if (*lookup && *firstarg) {
                                printgreeting(argc, argv, *lookup);
                                *firstarg = ISC_FALSE;
                        }
@@ -1333,8 +1423,7 @@ parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only,
                                        result = dns_rdatatype_fromtext(&rdtype,
                                                (isc_textregion_t *)&tr);
                                        if (result == ISC_R_SUCCESS &&
-                                           rdtype == dns_rdatatype_ixfr)
-                                       {
+                                           rdtype == dns_rdatatype_ixfr) {
                                                result = DNS_R_UNKNOWN;
                                                fprintf(stderr, ";; Warning, "
                                                        "ixfr requires a "
@@ -1548,6 +1637,9 @@ main(int argc, char **argv) {
                        fclose(batchfp);
                batchname = NULL;
        }
+#ifdef DIG_SIGCHASE
+       clean_trustedkey();
+#endif
        cancel_all();
        destroy_libs();
        isc_app_finish();
index fbe3031a0c2bfb3129928e7b43bf70d4ccc11c74..7724593785e5acd76b147e8263638f403a0e0916 100644 (file)
@@ -16,7 +16,7 @@
  - PERFORMANCE OF THIS SOFTWARE.
 -->
 
-<!-- $Id: dig.docbook,v 1.18 2004/04/13 01:09:36 marka Exp $ -->
+<!-- $Id: dig.docbook,v 1.19 2004/04/13 02:39:34 marka Exp $ -->
 
 <refentry>
 
@@ -483,29 +483,46 @@ Print records like the SOA records in a verbose multi-line
 format with human-readable comments.  The default is to print
 each record on a single line, to facilitate machine parsing 
 of the <command>dig</command> output.
-</para>
-</listitem></varlistentry>
+</para></listitem></varlistentry>
 
 <varlistentry><term><option>+[no]fail</option></term>
 <listitem><para>
 Do not try the next server if you receive a SERVFAIL.  The default is
 to not try the next server which is the reverse of normal stub resolver
 behaviour.
-</para>
+</para></listitem></varlistentry>
 
-</listitem></varlistentry>
 <varlistentry><term><option>+[no]besteffort</option></term>
 <listitem><para>
 Attempt to display the contents of messages which are malformed.
 The default is to not display malformed answers.
-</para>
+</para></listitem></varlistentry>
 
-</listitem></varlistentry>
 <varlistentry><term><option>+[no]dnssec</option></term>
 <listitem><para>
 Requests DNSSEC records be sent by setting the DNSSEC OK bit (DO)
 in the OPT record in the additional section of the query.
-</para>
+</para></listitem></varlistentry>
+
+<varlistentry><term><option>+[no]sigchase</option></term>
+<listitem><para>
+Chase DNSSEC signature chains.  Requires dig be compiled with
+-DDIG_SIGCHASE.
+</para></listitem></varlistentry>
+
+<varlistentry><term><option>+trusted-key=####</option></term>
+<listitem><para>
+Specify a trusted key to be used with <option>+sigchase</option>.
+Requires dig be compiled with -DDIG_SIGCHASE.
+</para></listitem></varlistentry>
+
+<varlistentry><term><option>+[no]topdown</option></term>
+<listitem><para>
+When chasing DNSSEC signature chains perform a top down validation.
+Requires dig be compiled with -DDIG_SIGCHASE.
+</para></listitem></varlistentry>
+
+
 
 </variablelist>
 
index be3d2d7062ada9b8eea608f04f9a86f553c32355..cecde0c26e27b9d32c046ff75ffe4f5d3f021efc 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dighost.c,v 1.260 2004/04/08 01:21:16 marka Exp $ */
+/* $Id: dighost.c,v 1.261 2004/04/13 02:39:35 marka Exp $ */
 
 /*
  * Notice to programmers:  Do not use this code as an example of how to
 #include <string.h>
 #include <limits.h>
 
+#ifdef DIG_SIGCHASE
+#ifndef DIG_SIGCHASE_BU
+#define DIG_SIGCHASE_BU 1
+#endif
+#ifndef DIG_SIGCHASE_TD
+#define DIG_SIGCHASE_TD 1
+#endif
+#endif 
+
 #include <dns/byaddr.h>
+#ifdef DIG_SIGCHASE
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/nsec.h>
+#include <isc/file.h>
+#include <isc/random.h>
+#include <ctype.h>
+#endif
 #include <dns/fixedname.h>
 #include <dns/message.h>
 #include <dns/name.h>
@@ -52,6 +69,9 @@
 #include <isc/entropy.h>
 #include <isc/lang.h>
 #include <isc/netaddr.h>
+#ifdef DIG_SIGCHASE
+#include <isc/netdb.h>
+#endif
 #include <isc/print.h>
 #include <isc/random.h>
 #include <isc/result.h>
@@ -133,6 +153,152 @@ char *progname = NULL;
 isc_mutex_t lookup_lock;
 dig_lookup_t *current_lookup = NULL;
 
+#ifdef DIG_SIGCHASE
+
+isc_result_t      get_trusted_key(isc_mem_t *mctx);
+dns_rdataset_t *  sigchase_scanname(dns_rdatatype_t type,
+                                   dns_rdatatype_t covers,
+                                   isc_boolean_t *lookedup,
+                                   dns_name_t *rdata_name);
+dns_rdataset_t *  chase_scanname_section(dns_message_t *msg,
+                                        dns_name_t *name,
+                                        dns_rdatatype_t type,
+                                        dns_rdatatype_t covers,
+                                        int section);
+isc_result_t      advanced_rrsearch(dns_rdataset_t **rdataset,
+                                   dns_name_t *name,
+                                   dns_rdatatype_t type,
+                                   dns_rdatatype_t covers,
+                                   isc_boolean_t *lookedup);
+isc_result_t      sigchase_verify_sig_key(dns_name_t *name,
+                                         dns_rdataset_t *rdataset,
+                                         dst_key_t* dnsseckey,
+                                         dns_rdataset_t *sigrdataset,
+                                         isc_mem_t *mctx);
+isc_result_t      sigchase_verify_sig(dns_name_t *name,
+                                     dns_rdataset_t *rdataset,
+                                     dns_rdataset_t *keyrdataset,
+                                     dns_rdataset_t *sigrdataset,
+                                     isc_mem_t *mctx);
+isc_result_t      sigchase_verify_ds(dns_name_t *name,
+                                    dns_rdataset_t *keyrdataset,
+                                    dns_rdataset_t *dsrdataset,
+                                    isc_mem_t *mctx);
+void              sigchase(dns_message_t *msg);
+void              print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
+void              print_rdataset(dns_name_t *name,
+                                dns_rdataset_t *rdataset, isc_mem_t *mctx);
+void              dup_name(dns_name_t *source, dns_name_t* target,
+                          isc_mem_t *mctx);
+void              dump_database(void);
+void              dump_database_section(dns_message_t *msg, int section);
+dns_rdataset_t *  search_type(dns_name_t *name, dns_rdatatype_t type,
+                             dns_rdatatype_t covers);
+isc_result_t      contains_trusted_key(dns_name_t *name,
+                                      dns_rdataset_t *rdataset,
+                                      dns_rdataset_t *sigrdataset,
+                                      isc_mem_t *mctx);
+void              print_type(dns_rdatatype_t type);
+isc_result_t      prove_nx_domain(dns_message_t * msg,
+                                 dns_name_t * name,
+                                 dns_name_t * rdata_name,
+                                 dns_rdataset_t ** rdataset,
+                                 dns_rdataset_t ** sigrdataset);
+isc_result_t      prove_nx_type(dns_message_t * msg, dns_name_t *name,
+                               dns_rdataset_t *nsec,
+                               dns_rdataclass_t class,
+                               dns_rdatatype_t type,
+                               dns_name_t * rdata_name,
+                               dns_rdataset_t ** rdataset,
+                               dns_rdataset_t ** sigrdataset);
+isc_result_t      prove_nx(dns_message_t * msg, dns_name_t * name,
+                          dns_rdataclass_t class,
+                          dns_rdatatype_t type,
+                          dns_name_t * rdata_name,
+                          dns_rdataset_t ** rdataset,
+                          dns_rdataset_t ** sigrdataset);
+isc_result_t      nameFromString( const char *str, dns_name_t *p_ret );
+int               inf_name(dns_name_t * name1, dns_name_t * name2);
+isc_result_t      opentmpkey(isc_mem_t *mctx, const char *file,
+                            char **tempp, FILE **fp);
+isc_result_t      removetmpkey(isc_mem_t *mctx, const char *file);
+void              clean_trustedkey(void );
+void              insert_trustedkey(dst_key_t  * key);
+#if DIG_SIGCHASE_BU
+isc_result_t      getneededrr(dns_message_t *msg);
+void              sigchase_bottom_up(dns_message_t *msg);
+void              sigchase_bu(dns_message_t *msg);
+#endif
+#if DIG_SIGCHASE_TD
+isc_result_t      initialization(dns_name_t *name);
+isc_result_t      prepare_lookup(dns_name_t *name);
+isc_result_t      grandfather_pb_test(dns_name_t * zone_name,
+                                     dns_rdataset_t *sigrdataset);
+isc_result_t      child_of_zone(dns_name_t *name,
+                               dns_name_t *zone_name,
+                               dns_name_t *child_name);
+void              sigchase_td(dns_message_t *msg);
+#endif
+char trustedkey[MXNAME] = "";
+
+dns_rdataset_t * chase_rdataset = NULL;
+dns_rdataset_t * chase_sigrdataset = NULL;
+dns_rdataset_t * chase_dsrdataset = NULL;
+dns_rdataset_t * chase_sigdsrdataset = NULL;
+dns_rdataset_t * chase_keyrdataset = NULL;
+dns_rdataset_t * chase_sigkeyrdataset = NULL;
+dns_rdataset_t * chase_nsrdataset = NULL;
+
+dns_name_t  chase_name; /* the query name */
+#if DIG_SIGCHASE_TD
+/*
+ * the current name is the parent name when we follow delegation
+ */
+dns_name_t  chase_current_name; 
+/*
+ * the child name is used for delegation (NS DS responses in AUTHORITY section)
+ */
+dns_name_t  chase_authority_name;
+#endif
+#if DIG_SIGCHASE_BU
+dns_name_t  chase_signame;
+#endif
+
+
+isc_boolean_t chase_siglookedup = ISC_FALSE;
+isc_boolean_t chase_keylookedup = ISC_FALSE;
+isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
+isc_boolean_t chase_dslookedup = ISC_FALSE;
+isc_boolean_t chase_sigdslookedup = ISC_FALSE;
+#if DIG_SIGCHASE_TD
+isc_boolean_t chase_nslookedup = ISC_FALSE;
+isc_boolean_t chase_lookedup = ISC_FALSE;
+
+
+isc_boolean_t delegation_follow = ISC_FALSE;
+isc_boolean_t grandfather_pb = ISC_FALSE;
+isc_boolean_t have_response = ISC_FALSE;
+isc_boolean_t have_delegation_ns = ISC_FALSE;
+dns_message_t * error_message = NULL;
+#endif
+
+isc_boolean_t dsvalidating = ISC_FALSE;
+isc_boolean_t chase_name_dup  = ISC_FALSE;
+
+ISC_LIST(dig_message_t) chase_message_list;
+ISC_LIST(dig_message_t) chase_message_list2;
+
+
+#define MAX_TRUSTED_KEY 5
+typedef struct struct_trusted_key_list {
+  dst_key_t * key[MAX_TRUSTED_KEY];
+  int nb_tk;
+} struct_tk_list;
+
+struct_tk_list  tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
+
+#endif
+
 /*
  * Apply and clear locks at the event level in global task.
  * Can I get rid of these using shutdown events?  XXX
@@ -506,6 +672,18 @@ make_empty_lookup(void) {
        looknew->servfail_stops = ISC_TRUE;
        looknew->besteffort = ISC_TRUE;
        looknew->dnssec = ISC_FALSE;
+#ifdef DIG_SIGCHASE
+       looknew->sigchase = ISC_FALSE;
+#if DIG_SIGCHASE_TD
+       looknew->do_topdown =  ISC_FALSE;
+       looknew->trace_root_sigchase = ISC_FALSE;
+       looknew->rdtype_sigchaseset = ISC_FALSE;
+       looknew->rdtype_sigchase = dns_rdatatype_any;
+       looknew->qrdtype_sigchase = dns_rdatatype_any;
+       looknew->rdclass_sigchase = dns_rdataclass_in;
+       looknew->rdclass_sigchaseset  = ISC_FALSE;
+#endif
+#endif
        looknew->udpsize = 0;
        looknew->recurse = ISC_TRUE;
        looknew->aaonly = ISC_FALSE;
@@ -550,6 +728,9 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
        looknew = make_empty_lookup();
        INSIST(looknew != NULL);
        strncpy(looknew->textname, lookold->textname, MXNAME);
+#if DIG_SIGCHASE_TD
+       strncpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
+#endif
        strncpy(looknew->cmdline, lookold->cmdline, MXNAME);
        looknew->textname[MXNAME-1] = 0;
        looknew->rdtype = lookold->rdtype;
@@ -567,6 +748,18 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
        looknew->servfail_stops = lookold->servfail_stops;
        looknew->besteffort = lookold->besteffort;
        looknew->dnssec = lookold->dnssec;
+#ifdef DIG_SIGCHASE
+       looknew->sigchase = lookold->sigchase;
+#if DIG_SIGCHASE_TD
+       looknew->do_topdown =  lookold->do_topdown;
+       looknew->trace_root_sigchase = lookold->trace_root_sigchase;
+       looknew->rdtype_sigchaseset =  lookold->rdtype_sigchaseset;
+       looknew->rdtype_sigchase = lookold->rdtype_sigchase;
+       looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
+       looknew->rdclass_sigchase = lookold->rdclass_sigchase;
+       looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
+#endif
+#endif
        looknew->udpsize = lookold->udpsize;
        looknew->recurse = lookold->recurse;
        looknew->aaonly = lookold->aaonly;
@@ -758,12 +951,12 @@ setup_system(void) {
        if (lwconf->nsnext == 0) {
                if (have_ipv4) {
                        lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
-                       if(lwresult != ISC_R_SUCCESS)
+                       if (lwresult != ISC_R_SUCCESS)
                                fatal("add_nameserver failed");
                }
                if (have_ipv6) {
                        lwresult = add_nameserver(lwconf, "::1", AF_INET6);
-                       if(lwresult != ISC_R_SUCCESS)
+                       if (lwresult != ISC_R_SUCCESS)
                                fatal("add_nameserver failed");
                }
        }
@@ -775,6 +968,11 @@ setup_system(void) {
                setup_file_key();
        else if (keysecret[0] != 0)
                setup_text_key();
+#ifdef DIG_SIGCHASE
+       /* Setup the list of messages for +sigchase */
+        ISC_LIST_INIT(chase_message_list);
+#endif
+
 }
 
 static void
@@ -1052,6 +1250,94 @@ start_lookup(void) {
         */
        if (current_lookup != NULL) {
                ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
+#if DIG_SIGCHASE_TD
+               if (current_lookup->do_topdown &&
+                   !current_lookup->rdtype_sigchaseset) {
+                       dst_key_t * trustedkey = NULL;
+                       isc_buffer_t *b = NULL;
+                       isc_region_t r;
+                       isc_result_t result;
+                       dns_name_t query_name;
+                       dns_name_t * key_name;
+                       int i;
+
+                       result = get_trusted_key(mctx);
+                       if (result != ISC_R_SUCCESS) {
+                               printf("\n;; No trusted key, "
+                                      "+sigchase option is disabled\n");
+                               current_lookup->sigchase = ISC_FALSE;
+                               goto novalidation;
+                       }
+                       result = nameFromString(current_lookup->textname,
+                                               &query_name);
+                       check_result(result, "nameFromString");
+
+                       for (i = 0; i< tk_list.nb_tk; i++) {
+                               key_name = dst_key_name(tk_list.key[i]);
+                     
+                               if (dns_name_issubdomain(&query_name,
+                                                        key_name) == ISC_TRUE)
+                                       trustedkey = tk_list.key[i];
+                               /*
+                                * Verifier que la temp est bien la plus basse
+                                * WARNING
+                                */
+                       }
+                       if (trustedkey == NULL) {
+                               printf("\n;; The queried zone: ");
+                               dns_name_print(&query_name, stdout);
+                               printf(" isn't a subdomain of any Trusted Keys"
+                                      ": +sigchase option is disable\n");
+                               current_lookup->sigchase = ISC_FALSE;
+                               dns_name_free(&query_name, mctx);
+                               goto novalidation;
+                       }
+                       dns_name_free(&query_name, mctx);
+
+                   
+                       current_lookup->rdtype_sigchase
+                               = current_lookup->rdtype;
+                       current_lookup->rdtype_sigchaseset
+                               = current_lookup->rdtypeset;
+                       current_lookup->rdtype = dns_rdatatype_ns;
+                     
+                
+                       current_lookup->qrdtype_sigchase
+                               = current_lookup->qrdtype;
+                       current_lookup->qrdtype = dns_rdatatype_ns;
+                  
+                       current_lookup->rdclass_sigchase
+                               = current_lookup->rdclass;
+                       current_lookup->rdclass_sigchaseset
+                               = current_lookup->rdclassset;
+                       current_lookup->rdclass = dns_rdataclass_in;
+               
+
+                       strncpy(current_lookup->textnamesigchase,
+                               current_lookup->textname, MXNAME);
+
+                       current_lookup->trace_root_sigchase = ISC_TRUE;
+                   
+                       result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+                       check_result(result, "isc_buffer_allocate");
+                       result = dns_name_totext(dst_key_name(trustedkey),
+                                                ISC_FALSE, b);
+                       check_result(result, "dns_name_totext");
+                       isc_buffer_usedregion(b, &r);
+                       r.base[r.length] = '\0';
+                       strncpy(current_lookup->textname, (char*)r.base,
+                               MXNAME);
+                       isc_buffer_free(&b);
+
+                       result = nameFromString(current_lookup
+                                               ->textnamesigchase,
+                                               &chase_name);
+                       check_result(result, "nameFromString");
+
+                       dns_name_init(&chase_authority_name, NULL);
+               }
+       novalidation:
+#endif
                setup_lookup(current_lookup);
                do_lookup(current_lookup);
        } else {
@@ -1104,8 +1390,7 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
        
        for (result = dns_message_firstname(msg, section);
             result == ISC_R_SUCCESS;
-            result = dns_message_nextname(msg, section))
-       {
+            result = dns_message_nextname(msg, section)) {
                name = NULL;
                dns_message_currentname(msg, section, &name);
 
@@ -1119,8 +1404,7 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
 
                for (result = dns_rdataset_first(rdataset);
                     result == ISC_R_SUCCESS;
-                    result = dns_rdataset_next(rdataset))
-               {
+                    result = dns_rdataset_next(rdataset)) {
                        char namestr[DNS_NAME_FORMATSIZE];
                        dns_rdata_ns_t ns;
 
@@ -1946,7 +2230,8 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
 
        isc_buffer_clear(&query->slbuf);
        isc_buffer_clear(&query->lengthbuf);
-       isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->lookup->sendbuf.used);
+       isc_buffer_putuint16(&query->slbuf,
+                            (isc_uint16_t) query->lookup->sendbuf.used);
        ISC_LIST_INIT(query->sendlist);
        ISC_LINK_INIT(&query->slbuf, link);
        ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
@@ -1962,7 +2247,7 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
                                  global_task, tcp_length_done, query);
        check_result(result, "isc_socket_recvv");
        recvcount++;
-       debug("recvcount=%d",recvcount);
+       debug("recvcount=%d", recvcount);
        if (!query->first_soa_rcvd) {
                debug("sending a request in launch_next_query");
                TIME_NOW(&query->time_sent);
@@ -2214,6 +2499,10 @@ recv_done(isc_task_t *task, isc_event_t *event) {
        dig_query_t *query = NULL;
        isc_buffer_t *b = NULL;
        dns_message_t *msg = NULL;
+#ifdef DIG_SIGCHASE
+       dig_message_t *chase_msg = NULL;
+       dig_message_t *chase_msg2 = NULL;
+#endif
        isc_result_t result;
        dig_lookup_t *n, *l;
        isc_boolean_t docancel = ISC_FALSE;
@@ -2221,6 +2510,13 @@ recv_done(isc_task_t *task, isc_event_t *event) {
        unsigned int parseflags;
        dns_messageid_t id;
        unsigned int msgflags;
+#ifdef DIG_SIGCHASE
+       isc_result_t do_sigchase = ISC_FALSE;
+
+       dns_message_t *msg_temp = NULL;
+       isc_region_t r;
+       isc_buffer_t *buf = NULL;
+#endif
 
        UNUSED(task);
        INSIST(!free_now);
@@ -2323,7 +2619,8 @@ recv_done(isc_task_t *task, isc_event_t *event) {
                                        fail = ISC_FALSE;
                                query->warn_id = ISC_FALSE;
                        } else
-                               printf(";; ERROR: short (< header size) message\n");
+                               printf(";; ERROR: short "
+                                      "(< header size) message\n");
                        if (fail) {
                                isc_event_free(&event);
                                clear_query(query);
@@ -2336,7 +2633,8 @@ recv_done(isc_task_t *task, isc_event_t *event) {
                        printf(";; Warning: ID mismatch: "
                               "expected ID %u, got %u\n", l->sendmsg->id, id);
                else
-                       printf(";; Warning: short (< header size) message received\n");
+                       printf(";; Warning: short "
+                              "(< header size) message received\n");
        }
 
        if (!match) {
@@ -2375,6 +2673,14 @@ recv_done(isc_task_t *task, isc_event_t *event) {
 
        debug("before parse starts");
        parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
+#ifdef DIG_SIGCHASE
+       if (!l->sigchase) {
+               do_sigchase = ISC_FALSE;
+       } else {
+               parseflags = 0;
+               do_sigchase = ISC_TRUE;
+       }
+#endif
        if (l->besteffort) {
                parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
                parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
@@ -2398,8 +2704,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
                return;
        }
        if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0
-           && !l->ignore && !l->tcp_mode)
-       {
+           && !l->ignore && !l->tcp_mode) {
                printf(";; Truncated, retrying in TCP mode.\n");
                n = requeue_lookup(l, ISC_TRUE);
                n->tcp_mode = ISC_TRUE;
@@ -2493,24 +2798,33 @@ recv_done(isc_task_t *task, isc_event_t *event) {
        }
 
        if (!l->doing_xfr || l->xfr_q == query) {
+#ifdef DIG_SIGCHASE
+               int count = 0;
+#endif
                if (msg->rcode != dns_rcode_noerror && l->origin != NULL) {
                        if (!next_origin(msg, query)) {
                                printmessage(query, msg, ISC_TRUE);
                                received(b->used, &sevent->address, query);
                        }
                } else if (!l->trace && !l->ns_search_only) {
-                       printmessage(query, msg, ISC_TRUE);
+#ifdef DIG_SIGCHASE
+                       if (!do_sigchase)
+#endif
+                               printmessage(query, msg, ISC_TRUE);
                } else if (l->trace) {
                        int n = 0;
+#ifdef DIG_SIGCHASE
+                       count = msg->counts[DNS_SECTION_ANSWER];
+#else
                        int count = msg->counts[DNS_SECTION_ANSWER];
+#endif
 
                        debug("in TRACE code");
                        if (!l->ns_search_only)
                                printmessage(query, msg, ISC_TRUE);
 
                        l->rdtype = l->qrdtype;
-                       if (l->trace_root || (l->ns_search_only && count > 0))
-                       {
+                       if (l->trace_root || (l->ns_search_only && count > 0)) {
                                if (!l->trace_root)
                                        l->rdtype = dns_rdatatype_soa;
                                n = followup_lookup(msg, query,
@@ -2537,9 +2851,56 @@ recv_done(isc_task_t *task, isc_event_t *event) {
                                        docancel = ISC_TRUE;
                                l->trace_root = ISC_FALSE;
                        } else
+#ifdef DIG_SIGCHASE
+                               if (!do_sigchase)
+#endif
                                printmessage(query, msg, ISC_TRUE);
                } 
+#ifdef DIG_SIGCHASE
+               if ( do_sigchase) {          
+                       chase_msg = isc_mem_allocate(mctx,
+                                                    sizeof(dig_message_t));
+                       if (chase_msg == NULL) {
+                               fatal("Memory allocation failure in %s:%d",
+                                     __FILE__, __LINE__);
+                       }
+                       ISC_LIST_APPEND(chase_message_list, chase_msg, link);
+                       if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
+                                              &msg_temp) != ISC_R_SUCCESS) {
+                               fatal("dns_message_create in %s:%d",
+                                     __FILE__, __LINE__);
+                       }
+        
+                       isc_buffer_usedregion(b, &r);
+                       result = isc_buffer_allocate(mctx, &buf, r.length);
+          
+                       check_result(result, "isc_buffer_allocate");
+                       result =  isc_buffer_copyregion(buf, &r);
+                       check_result(result, "isc_buffer_copyregion");
+          
+                       result =  dns_message_parse(msg_temp, buf, 0);
+                       isc_buffer_free(&buf);
+                       chase_msg->msg = msg_temp;
+
+                       chase_msg2 = isc_mem_allocate(mctx,
+                                                     sizeof(dig_message_t));
+                       if (chase_msg2 == NULL) {
+                               fatal("Memory allocation failure in %s:%d",
+                                     __FILE__, __LINE__);
+                       }
+                       ISC_LIST_APPEND(chase_message_list2, chase_msg2, link);
+                       chase_msg2->msg = msg;
+               }
+#endif
+       
        }
+       
+#ifdef DIG_SIGCHASE
+       if (l->sigchase && ISC_LIST_EMPTY(lookup_list) ) {   
+               sigchase(msg_temp);
+       }
+#endif
 
        if (l->pending)
                debug("still pending.");
@@ -2560,21 +2921,37 @@ recv_done(isc_task_t *task, isc_event_t *event) {
                        check_next_lookup(l);
                }
        } else {
-               if (msg->rcode == dns_rcode_noerror || l->origin == NULL)
-                       received(b->used, &sevent->address, query);
+
+               if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
+
+#ifdef DIG_SIGCHASE
+                       if (!l->sigchase)
+#endif
+                               received(b->used, &sevent->address, query);
+               }
+
                if (!query->lookup->ns_search_only)
                        query->lookup->pending = ISC_FALSE;
                if (!query->lookup->ns_search_only ||
-                   query->lookup->trace_root || docancel)
-               {
-                       dns_message_destroy(&msg);
+                   query->lookup->trace_root || docancel) {
+#ifdef DIG_SIGCHASE
+                       if (!do_sigchase)
+#endif
+                               dns_message_destroy(&msg);
+
                        cancel_lookup(l);
                }
                clear_query(query);
                check_next_lookup(l);
        }
-       if (msg != NULL)
-               dns_message_destroy(&msg);
+       if (msg != NULL) {
+#ifdef DIG_SIGCHASE
+               if (do_sigchase)
+                       msg = NULL;
+               else
+#endif
+                       dns_message_destroy(&msg);
+       }
        isc_event_free(&event);
        UNLOCK_LOOKUP;
 }
@@ -2677,6 +3054,10 @@ cancel_all(void) {
  */
 void
 destroy_libs(void) {
+#ifdef DIG_SIGCHASE 
+       void * ptr;
+       dig_message_t *chase_msg;
+#endif
 
        debug("destroy_libs()");
        if (global_task != NULL) {
@@ -2739,8 +3120,1945 @@ destroy_libs(void) {
 
        UNLOCK_LOOKUP;
        DESTROYLOCK(&lookup_lock);
+#ifdef DIG_SIGCHASE
+
+       debug("Destroy the messages kept for sigchase");
+       /* Destroy the messages kept for sigchase */
+               chase_msg = ISC_LIST_HEAD(chase_message_list);
+
+       while (chase_msg != NULL) {
+               INSIST(chase_msg->msg != NULL);
+               dns_message_destroy(&(chase_msg->msg));
+               ptr = chase_msg;
+               chase_msg = ISC_LIST_NEXT(chase_msg, link);
+               isc_mem_free(mctx, ptr);
+       }
+
+       chase_msg = ISC_LIST_HEAD(chase_message_list2);
+
+       while (chase_msg != NULL) {
+               INSIST(chase_msg->msg != NULL);
+               dns_message_destroy(&(chase_msg->msg));
+               ptr = chase_msg;
+               chase_msg = ISC_LIST_NEXT(chase_msg, link);
+               isc_mem_free(mctx, ptr);
+       }
+
+       debug("Destroy memory");
+       
+#endif
        if (memdebugging != 0)
                isc_mem_stats(mctx, stderr);
        if (mctx != NULL)
                isc_mem_destroy(&mctx);
 }
+
+
+
+#ifdef DIG_SIGCHASE
+void
+print_type(dns_rdatatype_t type)
+{
+       isc_buffer_t * b = NULL;
+       isc_result_t result;
+       isc_region_t r;
+  
+       result = isc_buffer_allocate(mctx, &b, 4000);
+       check_result(result, "isc_buffer_allocate");
+
+       result = dns_rdatatype_totext(type, b);
+       check_result(result, "print_type");
+  
+       isc_buffer_usedregion(b, &r);
+       r.base[r.length] = '\0';
+  
+       printf("%s", r.base);
+
+       isc_buffer_free(&b);
+}
+
+
+void
+dump_database_section( dns_message_t *msg, int section)
+{
+       dns_name_t *msg_name=NULL;
+       dns_rdataset_t *rdataset;
+
+       do {
+               dns_message_currentname(msg, section, &msg_name);
+    
+               for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
+                    rdataset = ISC_LIST_NEXT(rdataset, link)) {        
+                       dns_name_print(msg_name, stdout);
+                       printf("\n");
+                       print_rdataset(msg_name, rdataset, mctx);
+                       printf("end\n");
+               }
+               msg_name = NULL;
+       } while ( dns_message_nextname(msg, section) == ISC_R_SUCCESS);
+}
+
+
+void dump_database(void)
+{
+       dig_message_t * msg;
+
+       for (msg = ISC_LIST_HEAD(chase_message_list);  msg != NULL;
+            msg = ISC_LIST_NEXT(msg, link)) {
+               if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
+                   == ISC_R_SUCCESS) 
+                       dump_database_section(msg->msg, DNS_SECTION_ANSWER);
+       
+               if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
+                   == ISC_R_SUCCESS) 
+                       dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
+       
+               if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
+                   == ISC_R_SUCCESS) 
+                       dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
+       }
+}
+
+
+dns_rdataset_t *  search_type(dns_name_t *name,
+                             dns_rdatatype_t type,
+                             dns_rdatatype_t covers)
+{
+       dns_rdataset_t *rdataset;
+       dns_rdata_sig_t siginfo;
+       dns_rdata_t sigrdata;
+       isc_result_t result;
+
+       for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+            rdataset = ISC_LIST_NEXT(rdataset, link)) {
+               if (type == dns_rdatatype_any) {
+                       if (rdataset->type != dns_rdatatype_rrsig)
+                               return rdataset;
+               } 
+               else if ((type == dns_rdatatype_rrsig) &&
+                        (rdataset->type == dns_rdatatype_rrsig)) {
+                       dns_rdata_init(&sigrdata);
+                       result = dns_rdataset_first(rdataset);
+                       check_result(result, "empty rdataset");
+                       dns_rdataset_current(rdataset, &sigrdata);
+                       result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+                       check_result(result, "sigrdata tostruct siginfo");
+
+                       if ((siginfo.covered == covers) ||
+                           (covers == dns_rdatatype_any)) {
+                               dns_rdata_reset(&sigrdata);
+                               dns_rdata_freestruct(&siginfo); 
+                               return rdataset;
+                       }
+                       dns_rdata_reset(&sigrdata);
+                       dns_rdata_freestruct(&siginfo);
+               } 
+               else if (rdataset->type == type)
+                       return rdataset;
+       }
+       return NULL;
+}
+
+dns_rdataset_t *
+chase_scanname_section(dns_message_t *msg,
+                      dns_name_t *name,
+                      dns_rdatatype_t type,
+                      dns_rdatatype_t covers,
+                      int section)
+{
+       dns_rdataset_t *rdataset;
+       dns_name_t *msg_name = NULL;
+  
+       do {
+               dns_message_currentname(msg, section, &msg_name);
+               if (dns_name_compare(msg_name, name) == 0) {
+                       rdataset = search_type(msg_name, type, covers);
+                       if ( rdataset != NULL)
+                               return rdataset;
+               }
+               msg_name = NULL;
+       } while ( dns_message_nextname(msg, section) == ISC_R_SUCCESS);
+  
+       return(NULL);
+}
+
+
+dns_rdataset_t *
+chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
+{
+       dns_rdataset_t *rdataset = NULL;
+       dig_message_t * msg;
+       for (msg = ISC_LIST_HEAD(chase_message_list2);  msg != NULL;
+            msg = ISC_LIST_NEXT(msg, link)) {
+               if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
+                   == ISC_R_SUCCESS)
+                       rdataset = chase_scanname_section(msg->msg, name,
+                                                         type, covers,
+                                                         DNS_SECTION_ANSWER);
+                       if (rdataset != NULL)
+                               return rdataset;
+               if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
+                   == ISC_R_SUCCESS)
+                       rdataset =
+                               chase_scanname_section(msg->msg, name,
+                                                      type, covers,
+                                                      DNS_SECTION_AUTHORITY);
+                       if (rdataset != NULL)
+                               return rdataset;
+               if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
+                   == ISC_R_SUCCESS)
+                       rdataset =
+                               chase_scanname_section(msg->msg, name, type,
+                                                      covers,
+                                                      DNS_SECTION_ADDITIONAL);
+                       if (rdataset != NULL)
+                               return rdataset;
+       }
+
+       return NULL;
+}
+
+dns_rdataset_t *
+sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
+                 isc_boolean_t * lookedup,
+                 dns_name_t *rdata_name )
+{
+       dig_lookup_t *lookup;
+       isc_buffer_t *b = NULL;
+       isc_region_t r;
+       isc_result_t result;
+       dns_rdataset_t * temp;
+       dns_rdatatype_t querytype;
+
+       if ((temp=chase_scanname(rdata_name, type, covers))!=NULL) {
+               return(temp);
+       }
+
+       if (*lookedup == ISC_TRUE) {
+               return(NULL);
+       }
+
+       lookup = clone_lookup(current_lookup, ISC_TRUE);
+       lookup->trace_root = ISC_FALSE;
+       lookup->new_search = ISC_TRUE;
+  
+       result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+       check_result(result, "isc_buffer_allocate");
+       result = dns_name_totext(rdata_name, ISC_FALSE, b);
+       check_result(result, "dns_name_totext");
+       isc_buffer_usedregion(b, &r);
+       r.base[r.length] = '\0';
+       strcpy(lookup->textname, (char*)r.base);
+       isc_buffer_free(&b);
+
+       if (type ==  dns_rdatatype_rrsig)
+               querytype = covers;
+       else
+               querytype = type;
+       if (querytype == 0 || querytype == 255) {
+               printf("Error in the queried type: %d\n", querytype);
+               return(NULL);
+       }
+
+       lookup->rdtype = querytype;
+       lookup->rdtypeset = ISC_TRUE;
+       lookup->qrdtype = querytype;
+       *lookedup = ISC_TRUE;
+
+       ISC_LIST_APPEND(lookup_list, lookup, link);
+       printf("\n\nLaunch a query to find a RRset of type ");
+       print_type(type);
+       printf(" for zone: %s\n", lookup->textname);
+       return(NULL);
+}
+
+void
+insert_trustedkey(dst_key_t  * key)
+{
+       if (key == NULL)
+               return;
+       if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
+               return;
+
+       tk_list.key[tk_list.nb_tk++] = key;
+       return;   
+}
+
+void
+clean_trustedkey()
+{
+       int i = 0;
+
+       for (i= 0; i < MAX_TRUSTED_KEY; i++) {
+               if (tk_list.key[i] != NULL) {
+                       dst_key_free(&tk_list.key[i]);
+                       tk_list.key[i] = NULL;
+               }
+               else
+                       break;
+       }
+       tk_list.nb_tk = 0;
+       return;
+}
+
+char alphnum[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+isc_result_t
+removetmpkey(isc_mem_t *mctx, const char *file) 
+{
+       char *tempnamekey = NULL;
+       int tempnamekeylen;
+       isc_result_t result;
+  
+       tempnamekeylen = strlen(file)+10;
+  
+       tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
+       if (tempnamekey == NULL)
+               return (ISC_R_NOMEMORY);
+
+       memset(tempnamekey, 0, tempnamekeylen);
+       strcat(tempnamekey, file);
+       strcat(tempnamekey,".key");
+       isc_file_remove(tempnamekey);
+
+       result = isc_file_remove(tempnamekey);
+       isc_mem_free(mctx, tempnamekey);
+       return(result);
+}
+
+isc_result_t
+opentmpkey(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) {
+        FILE *f = NULL;
+        isc_result_t result;
+        char *tempname = NULL;
+       char *tempnamekey = NULL;
+        int tempnamelen;
+       int tempnamekeylen;
+       char *x;
+       char *cp;
+       isc_uint32_t which;
+
+       while (1) {
+               tempnamelen = strlen(file) + 20;
+               tempname = isc_mem_allocate(mctx, tempnamelen);
+               if (tempname == NULL)
+                       return (ISC_R_NOMEMORY);
+               memset(tempname, 0, tempnamelen);
+
+               result = isc_file_mktemplate(file, tempname, tempnamelen);
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup;
+
+               cp = tempname;
+               while (*cp != '\0')
+                       cp++;
+               if (cp == tempname) {
+                       isc_mem_free(mctx, tempname);
+                       return (ISC_R_FAILURE);
+               }
+           
+               x = cp--;
+               while (cp >= tempname && *cp == 'X') {
+                       isc_random_get(&which);
+                       *cp = alphnum[which % (sizeof(alphnum) - 1)];
+                       x = cp--;
+               }
+               tempnamekeylen = tempnamelen+5;
+               tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
+               if (tempnamekey == NULL)
+                       return (ISC_R_NOMEMORY);
+       
+               memset(tempnamekey, 0, tempnamekeylen);
+               strncpy(tempnamekey, tempname, tempnamelen);
+               strcat(tempnamekey ,".key");
+
+          
+               if (isc_file_exists(tempnamekey)) {
+                       isc_mem_free(mctx, tempnamekey);
+                       isc_mem_free(mctx, tempname);
+                       continue;
+               }
+
+               if ((f = fopen(tempnamekey, "w")) == NULL) {
+                       printf("get_trusted_key(): trusted key not found %s\n",
+                              tempnamekey);
+                       return ISC_R_FAILURE;
+               }
+               break;
+       }
+       isc_mem_free(mctx, tempnamekey);
+        *tempp = tempname;
+        *fp = f;
+        return (ISC_R_SUCCESS);
+
+ cleanup:
+        isc_mem_free(mctx, tempname);
+       
+        return (result);
+}
+
+
+isc_result_t
+get_trusted_key(isc_mem_t *mctx)
+{
+       isc_result_t result;
+       const char * filename = NULL;
+       char * filetemp =NULL;
+       char buf[1500];
+       FILE *fp , *fptemp;
+       dst_key_t  * key = NULL;
+       result  = isc_file_exists(trustedkey);
+       if (result !=  ISC_TRUE) {
+               result  = isc_file_exists("/etc/trusted-key.key");
+               if (result !=  ISC_TRUE) {
+                       result  = isc_file_exists("./trusted-key.key");
+                       if (result !=  ISC_TRUE)
+                               return ISC_R_FAILURE;
+                       else
+                               filename = "./trusted-key.key";
+               }
+               else
+                       filename = "/etc/trusted-key.key";
+       }
+       else
+               filename = trustedkey;
+
+       if (filename == NULL) {
+               printf("No trusted key\n");
+               return ISC_R_FAILURE;
+       }
+
+       if ((fp = fopen(filename, "r")) == NULL) {
+               printf("get_trusted_key(): trusted key not found %s\n",
+                      filename);
+               return ISC_R_FAILURE;
+       }
+       while (fgets(buf, 1500, fp) != NULL) {
+               result = opentmpkey(mctx,"tmp_file", &filetemp, &fptemp);
+               if (result != ISC_R_SUCCESS) {
+                       fclose(fp);
+                       return ISC_R_FAILURE;
+               }
+               if (fputs(buf, fptemp)<0) {
+                       fclose(fp);
+                       fclose(fptemp);
+                       return ISC_R_FAILURE;
+               }
+               fclose(fptemp);
+               result = dst_key_fromnamedfile(filetemp, DST_TYPE_PUBLIC,
+                                              mctx, &key);
+               removetmpkey(mctx, filetemp);
+               isc_mem_free(mctx, filetemp);
+               if (result !=  ISC_R_SUCCESS ) {
+                       fclose(fp);
+                       return ISC_R_FAILURE;
+               }
+               insert_trustedkey(key);
+#if 0
+               dst_key_tofile(key, DST_TYPE_PUBLIC,"/tmp");
+#endif
+               key = NULL;
+       }
+       return ISC_R_SUCCESS;
+}
+
+
+isc_result_t
+nameFromString( const char *str, dns_name_t *p_ret )
+{
+       int len = strlen(str);
+       int ret;
+       isc_buffer_t buffer;
+       dns_fixedname_t fixedname;
+       REQUIRE( p_ret);
+       REQUIRE( str != NULL );
+
+       isc_buffer_init( &buffer, str, len );
+       isc_buffer_add( &buffer, len );
+
+       dns_fixedname_init(&fixedname);
+       ret = dns_name_fromtext( dns_fixedname_name(&fixedname), &buffer,
+                                dns_rootname, ISC_TRUE, NULL);
+       if ( ret != ISC_R_SUCCESS ) return ret;
+
+       dns_name_init(p_ret, NULL );
+  
+       ret = dns_name_dup( dns_fixedname_name(&fixedname), mctx, p_ret );
+       return ret;
+} 
+
+
+#if DIG_SIGCHASE_TD
+isc_result_t 
+prepare_lookup(dns_name_t *name)
+{
+       isc_result_t    result;
+       dig_lookup_t  * lookup = NULL;
+       dig_server_t *s;
+       void *ptr;
+
+       lookup = clone_lookup(current_lookup, ISC_TRUE);
+       lookup->trace_root = ISC_FALSE;
+       lookup->new_search = ISC_TRUE;
+       lookup->trace_root_sigchase = ISC_FALSE;
+
+       strncpy(lookup->textname, lookup->textnamesigchase, MXNAME);
+
+       lookup->rdtype = lookup->rdtype_sigchase;
+       lookup->rdtypeset = ISC_TRUE;
+       lookup->qrdtype = lookup->qrdtype_sigchase;
+
+  
+   
+       s = ISC_LIST_HEAD(lookup->my_server_list);
+       while (s != NULL) {
+               debug("freeing server %p belonging to %p",
+                     s, lookup);
+               ptr = s;
+               s = ISC_LIST_NEXT(s, link);
+               ISC_LIST_DEQUEUE(lookup->my_server_list,
+                                (dig_server_t *)ptr, link);
+               isc_mem_free(mctx, ptr);
+       }
+  
+
+       for (result = dns_rdataset_first(chase_nsrdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(chase_nsrdataset)) {
+               char namestr[DNS_NAME_FORMATSIZE];
+               dns_rdata_ns_t ns;
+               dns_rdata_t rdata = DNS_RDATA_INIT;
+               dig_server_t * srv = NULL;
+#define  __FOLLOW_GLUE__
+#ifdef __FOLLOW_GLUE__
+               isc_buffer_t * b = NULL;
+               isc_result_t result;
+               isc_region_t r;
+               dns_rdataset_t * rdataset =NULL;
+               isc_boolean_t   true = ISC_TRUE;
+#endif
+
+               memset(namestr, 0, DNS_NAME_FORMATSIZE);
+
+               dns_rdataset_current(chase_nsrdataset, &rdata);
+
+               (void)dns_rdata_tostruct(&rdata, &ns, NULL);
+      
+     
+      
+#ifdef __FOLLOW_GLUE__
+      
+               result = advanced_rrsearch(&rdataset, &ns.name,
+                                          dns_rdatatype_aaaa,
+                                          dns_rdatatype_any, &true);
+               if (result == ISC_R_SUCCESS) {
+                       for (result = dns_rdataset_first(rdataset);
+                            result == ISC_R_SUCCESS;
+                            result = dns_rdataset_next(rdataset)) {
+                               dns_rdata_t aaaa = DNS_RDATA_INIT;
+                               dns_rdataset_current(rdataset, &aaaa);
+
+                               result = isc_buffer_allocate(mctx, &b, 80);
+                               check_result(result, "isc_buffer_allocate");
+
+                               dns_rdata_totext(&aaaa, &ns.name, b);
+                               isc_buffer_usedregion(b, &r);
+                               r.base[r.length] = '\0';
+                               strncpy(namestr, (char*)r.base,
+                                       DNS_NAME_FORMATSIZE);
+                               isc_buffer_free(&b);
+                               dns_rdata_reset(&aaaa);
+
+
+                               srv = make_server(namestr);
+            
+                               ISC_LIST_APPEND(lookup->my_server_list,
+                                               srv, link);
+                       }
+               }
+      
+               rdataset = NULL;
+               result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
+                                          dns_rdatatype_any, &true);
+               if (result == ISC_R_SUCCESS) {
+                       for (result = dns_rdataset_first(rdataset);
+                            result == ISC_R_SUCCESS;
+                            result = dns_rdataset_next(rdataset)) {
+                               dns_rdata_t a = DNS_RDATA_INIT;
+                               dns_rdataset_current(rdataset, &a);
+
+                               result = isc_buffer_allocate(mctx, &b, 80);
+                               check_result(result, "isc_buffer_allocate");
+
+                               dns_rdata_totext(&a, &ns.name, b);
+                               isc_buffer_usedregion(b, &r);
+                               r.base[r.length] = '\0';
+                               strncpy(namestr, (char*)r.base,
+                                       DNS_NAME_FORMATSIZE);
+                               isc_buffer_free(&b);
+                               dns_rdata_reset(&a);
+                               printf("ns name: %s\n", namestr);
+      
+
+                               srv = make_server(namestr);
+            
+                               ISC_LIST_APPEND(lookup->my_server_list,
+                                               srv, link);
+                       }
+               }
+#else
+       
+               dns_name_format(&ns.name, namestr, sizeof(namestr));
+               printf("ns name: ");
+               dns_name_print(&ns.name, stdout);
+               printf("\n");
+               srv = make_server(namestr);
+            
+               ISC_LIST_APPEND(lookup->my_server_list, srv, link);
+
+#endif 
+               dns_rdata_freestruct(&ns);
+               dns_rdata_reset(&rdata);
+      
+       }
+
+       ISC_LIST_APPEND(lookup_list, lookup, link);
+       printf("\nLaunch a query to find a RRset of type ");
+       print_type(lookup->rdtype);
+       printf(" for zone: %s", lookup->textname);
+       printf(" with nameservers:");
+       printf("\n");
+       print_rdataset(name, chase_nsrdataset, mctx);
+       return ISC_R_SUCCESS;
+}
+
+
+isc_result_t
+child_of_zone(dns_name_t * name, dns_name_t * zone_name,
+             dns_name_t * child_name)
+{
+       dns_namereln_t name_reln;
+       int orderp;
+       unsigned int nlabelsp;
+
+       name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
+       if ( (name_reln != dns_namereln_subdomain) ||
+            (dns_name_countlabels(name) <=
+             dns_name_countlabels(zone_name) +1)) {
+               printf("\n;; ERROR : ");
+               dns_name_print(name, stdout);
+               printf(" is not a subdomain of: ");
+               dns_name_print(zone_name, stdout);
+               printf(" FAILED\n\n");
+               return ISC_R_FAILURE;
+       }
+
+       dns_name_getlabelsequence(name,
+                                 dns_name_countlabels(name) -
+                                 dns_name_countlabels(zone_name) -1,
+                                 dns_name_countlabels(zone_name) +1,
+                                 child_name);
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t
+grandfather_pb_test(dns_name_t * zone_name, dns_rdataset_t  * sigrdataset)
+{
+       isc_result_t result;
+       dns_rdata_t sigrdata;
+       dns_rdata_sig_t siginfo;
+
+       result = dns_rdataset_first(sigrdataset);
+       check_result(result, "empty RRSIG dataset");
+       dns_rdata_init(&sigrdata);
+  
+       do {
+               dns_rdataset_current(sigrdataset, &sigrdata);
+    
+               result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+               check_result(result, "sigrdata tostruct siginfo");
+               if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
+                       dns_rdata_freestruct(&siginfo);
+                       dns_rdata_reset(&sigrdata);
+                       return ISC_R_SUCCESS;
+               }
+
+               dns_rdata_freestruct(&siginfo);
+       } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
+
+       dns_rdata_reset(&sigrdata);
+
+       return ISC_R_FAILURE;
+}
+
+
+isc_result_t
+initialization(dns_name_t * name)
+{
+       isc_result_t   result;
+       isc_boolean_t  true = ISC_TRUE;
+
+       chase_nsrdataset = NULL;
+       result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
+                                  dns_rdatatype_any, &true);
+       if (result != ISC_R_SUCCESS) {
+               printf("\n;; NS RRset is missing to continue validation:"
+                      " FAILED\n\n");
+               return ISC_R_FAILURE;
+       }
+       INSIST(chase_nsrdataset != NULL);
+       prepare_lookup(name);
+
+       dup_name(name, &chase_current_name, mctx);
+
+       return ISC_R_SUCCESS;
+}
+#endif 
+
+void
+print_rdataset(dns_name_t * name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
+{
+       isc_buffer_t * b = NULL;
+       isc_result_t result;
+       isc_region_t r;
+
+       result = isc_buffer_allocate(mctx, &b, 9000);
+       check_result(result, "isc_buffer_allocate");
+
+       printrdataset(name, rdataset, b);
+
+       isc_buffer_usedregion(b, &r);
+       r.base[r.length] = '\0';
+
+
+       printf("%s\n", r.base);
+
+       isc_buffer_free(&b);
+}
+
+
+void 
+dup_name(dns_name_t *source, dns_name_t* target, isc_mem_t *mctx)
+{
+       isc_result_t result; 
+       dns_name_init(target, NULL);
+       result = dns_name_dup(source, mctx, target);
+       check_result(result, "dns_name_dup");
+}
+
+/*
+ *
+ * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
+ * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
+ *                     and the RRset is valid
+ * return ISC_R_NOTFOUND if not contains trusted key
+                       or if the RRset isn't valid
+ * return ISC_R_FAILURE if problem
+ *
+ */
+isc_result_t
+contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
+                    dns_rdataset_t *sigrdataset,
+                    isc_mem_t *mctx)
+{
+       isc_result_t result;
+       dns_rdata_t rdata;
+       dst_key_t * trustedKey = NULL;
+       dst_key_t * dnsseckey = NULL;
+       int i;
+  
+       if (name == NULL || rdataset == NULL) {
+               return ISC_R_FAILURE;
+       }
+
+       result = dns_rdataset_first(rdataset);
+       check_result(result, "empty rdataset");
+       dns_rdata_init(&rdata);
+
+       do {
+               dns_rdataset_current(rdataset, &rdata);
+               INSIST(rdata.type == dns_rdatatype_dnskey);
+         
+               result = dns_dnssec_keyfromrdata(name, &rdata,
+                                                mctx, &dnsseckey);
+               check_result(result, "dns_dnssec_keyfromrdata");
+
+    
+               for (i = 0; i< tk_list.nb_tk; i++) {
+                       if (dst_key_compare(tk_list.key[i], dnsseckey)
+                           == ISC_TRUE) {
+                               dns_rdata_reset(&rdata);
+       
+                               printf(";; Ok, find a Trusted Key in the "
+                                      "DNSKEY RRset: %d\n",
+                                      dst_key_id(dnsseckey));
+                               if (sigchase_verify_sig_key(name, rdataset,
+                                                           dnsseckey,
+                                                           sigrdataset,
+                                                           mctx)
+                                   == ISC_R_SUCCESS) {
+                                       dst_key_free(&dnsseckey);
+                                       dnsseckey = NULL;
+                                       return  ISC_R_SUCCESS;
+                               }
+                       }
+               }
+               dns_rdata_reset(&rdata);
+               if (dnsseckey != NULL)
+                       dst_key_free(&dnsseckey);
+       } while (dns_rdataset_next(rdataset) == ISC_R_SUCCESS);
+
+       if (trustedKey != NULL)
+               dst_key_free(&trustedKey);
+       trustedKey = NULL;
+  
+       return ISC_R_NOTFOUND;
+}
+
+isc_result_t
+sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
+                   dns_rdataset_t *keyrdataset,
+                   dns_rdataset_t *sigrdataset,
+                   isc_mem_t *mctx)
+{
+       isc_result_t result;
+       dns_rdata_t keyrdata;
+       dst_key_t * dnsseckey = NULL;
+
+       result = dns_rdataset_first(keyrdataset);
+       check_result(result, "empty DNSKEY dataset");
+       dns_rdata_init(&keyrdata);
+
+       do {
+               dns_rdataset_current(keyrdataset, &keyrdata);
+               INSIST(keyrdata.type == dns_rdatatype_dnskey);
+         
+               result = dns_dnssec_keyfromrdata(name, &keyrdata,
+                                                mctx, &dnsseckey);
+               check_result(result, "dns_dnssec_keyfromrdata");
+
+               result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
+                                                sigrdataset, mctx);
+               if (result == ISC_R_SUCCESS) {
+                       dns_rdata_reset(&keyrdata);
+                       dst_key_free(&dnsseckey);
+                       return(ISC_R_SUCCESS);
+               }
+               dst_key_free(&dnsseckey);
+       } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
+  
+       dns_rdata_reset(&keyrdata);
+  
+       return ISC_R_NOTFOUND;
+}
+
+isc_result_t
+sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
+                       dst_key_t* dnsseckey,
+                       dns_rdataset_t *sigrdataset, isc_mem_t *mctx)
+{
+       isc_result_t result;
+       dns_rdata_t sigrdata;
+       dns_rdata_sig_t siginfo;
+
+       result = dns_rdataset_first(sigrdataset);
+       check_result(result, "empty RRSIG dataset");
+       dns_rdata_init(&sigrdata);
+    
+       do {
+               dns_rdataset_current(sigrdataset, &sigrdata);
+
+               result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+               check_result(result, "sigrdata tostruct siginfo");
+               /*
+                * Test if the id of the DNSKEY is
+                * the id of the DNSKEY signer's
+                */
+               if (siginfo.keyid == dst_key_id(dnsseckey)) {
+    
+                       result = dns_rdataset_first(rdataset);
+                       check_result(result, "empty DS dataset");
+    
+                       result = dns_dnssec_verify(name, rdataset, dnsseckey,
+                                                  ISC_FALSE, mctx, &sigrdata);
+
+                       printf(";; VERIFYING ");
+                       print_type(rdataset->type);
+                       printf(" RRset for ");
+                       dns_name_print(name, stdout);
+                       printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
+                              isc_result_totext(result));
+        
+                       if (result == ISC_R_SUCCESS) {
+                               dns_rdata_reset(&sigrdata);
+                               return result;
+                       }
+               }
+               dns_rdata_freestruct(&siginfo);
+       } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
+
+       dns_rdata_reset(&sigrdata);
+
+       return ISC_R_NOTFOUND;
+}
+
+
+isc_result_t
+sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
+                  dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
+{
+       isc_result_t result;
+       dns_rdata_t keyrdata;
+       dns_rdata_t newdsrdata;
+       dns_rdata_t dsrdata;
+       dns_rdata_ds_t dsinfo;
+       dst_key_t* dnsseckey = NULL;
+       unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+
+       result = dns_rdataset_first(dsrdataset);
+       check_result(result, "empty DSset dataset");
+       dns_rdata_init(&dsrdata);
+       do {
+               dns_rdataset_current(dsrdataset, &dsrdata);
+    
+               result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
+               check_result(result, "dns_rdata_tostruct  for DS");
+    
+               result = dns_rdataset_first(keyrdataset);
+               check_result(result, "empty KEY dataset");
+               dns_rdata_init(&keyrdata);        
+
+               do {
+                       dns_rdataset_current(keyrdataset, &keyrdata);
+                       INSIST(keyrdata.type == dns_rdatatype_dnskey);
+         
+                       result = dns_dnssec_keyfromrdata(name, &keyrdata,
+                                                        mctx, &dnsseckey);
+                       check_result(result, "dns_dnssec_keyfromrdata");
+
+                       /*
+                        * Test if the id of the DNSKEY is the
+                        * id of DNSKEY referenced by the DS
+                        */
+                       if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
+                               dns_rdata_init(&newdsrdata);
+
+                               result = dns_ds_buildrdata(name, &keyrdata,
+                                                          dsinfo.digest_type,
+                                                          dsbuf, &newdsrdata);
+                               dns_rdata_freestruct(&dsinfo);  
+
+                               if (result != ISC_R_SUCCESS) {
+                                       dns_rdata_reset(&keyrdata);
+                                       dns_rdata_reset(&newdsrdata);
+                                       dns_rdata_reset(&dsrdata);
+                                       dst_key_free(&dnsseckey);
+                                       dns_rdata_freestruct(&dsinfo);  
+                                       printf("Oops: impossible to build"
+                                              " new DS rdata\n");
+                                       return result;
+                               }
+       
+       
+                               if (dns_rdata_compare(&dsrdata,
+                                                     &newdsrdata) == 0) {
+                                       printf(";; OK a DS valids a DNSKEY"
+                                              " in the RRset\n");
+                                       printf(";; Now verify that this"
+                                              " DNSKEY validates the "
+                                              "DNSKEY RRset\n");
+              
+                                       result = sigchase_verify_sig_key(name,
+                                                        keyrdataset,
+                                                        dnsseckey,
+                                                        chase_sigkeyrdataset,
+                                                        mctx);
+                                       if (result ==  ISC_R_SUCCESS) {
+                                               dns_rdata_reset(&keyrdata);
+                                               dns_rdata_reset(&newdsrdata);
+                                               dns_rdata_reset(&dsrdata);
+                                               dst_key_free(&dnsseckey);
+                
+                                               return result;
+                                       }
+                               } 
+                               else {
+                                       printf(";; This DS is NOT the DS for"
+                                              " the chasing KEY: FAILED\n");
+                               }
+
+                               dns_rdata_reset(&newdsrdata);
+                       }
+                       dst_key_free(&dnsseckey);
+                       dnsseckey = NULL;
+               } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
+               dns_rdata_reset(&keyrdata);
+       } while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS);
+#if 0
+       dns_rdata_reset(&dsrdata); WARNING
+#endif
+       return ISC_R_NOTFOUND;
+}
+
+/*
+ *
+ * take a pointer on a rdataset in parameter and try to resolv it.
+ * the searched rrset is a rrset on 'name' with type 'type'
+ * (and if the type is a rrsig the signature cover 'covers').
+ * the lookedup is to known if you have already done the query on the net.
+ * ISC_R_SUCCESS: if we found the rrset
+ * ISC_R_NOTFOUND: we do not found the rrset in cache
+ * and we do a query on the net
+ * ISC_R_FAILURE: rrset not found 
+ */
+isc_result_t
+advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t * name,
+                 dns_rdatatype_t type,
+                 dns_rdatatype_t covers,
+                 isc_boolean_t *lookedup)
+{ 
+       isc_boolean_t  tmplookedup;
+
+       INSIST(rdataset != NULL);
+
+       if (*rdataset != NULL)
+               return(ISC_R_SUCCESS);
+
+       tmplookedup = *lookedup;
+       if ((*rdataset = sigchase_scanname(type, covers,
+                                          lookedup, name)) == NULL) {
+               if (tmplookedup)
+                       return (ISC_R_FAILURE);
+               return (ISC_R_NOTFOUND);
+       }
+       *lookedup = ISC_FALSE;
+       return(ISC_R_SUCCESS);
+}
+
+
+
+#if DIG_SIGCHASE_TD
+void
+sigchase_td(dns_message_t * msg)
+{
+       isc_result_t    result;
+       dns_name_t    * name = NULL;
+       isc_boolean_t   have_answer = ISC_FALSE;
+       isc_boolean_t   true = ISC_TRUE;
+
+       if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
+           == ISC_R_SUCCESS) {
+               dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+               if (current_lookup->trace_root_sigchase) {
+                       initialization(name);
+                       return;
+               }
+               have_answer = true;
+       }
+       else {
+               if (!current_lookup->trace_root_sigchase) {
+                       result = dns_message_firstname(msg,
+                                                      DNS_SECTION_AUTHORITY);
+                       if (result == ISC_R_SUCCESS)
+                               dns_message_currentname(msg,
+                                                       DNS_SECTION_AUTHORITY,
+                                                       &name);
+                       chase_nsrdataset
+                               = chase_scanname_section(msg, name,
+                                                        dns_rdatatype_ns,
+                                                        dns_rdatatype_any,
+                                                        DNS_SECTION_AUTHORITY);
+                       dup_name(name, &chase_authority_name, mctx);
+                       if (chase_nsrdataset != NULL) {
+                               have_delegation_ns = ISC_TRUE;
+                               printf("no response but there is a delegation"
+                                      " in authority section:");
+                               dns_name_print(name, stdout);
+                               printf("\n");
+                       }
+                       else {
+                               printf("no response and no delegation in "
+                                      "authority section but a reference"
+                                      " to: ");
+                               dns_name_print(name, stdout);
+                               printf("\n");
+                               error_message = msg;
+                       }
+               }
+               else {
+                       printf(";; NO ANSWERS: %s\n",
+                              isc_result_totext(result));
+                       dns_name_free(&chase_name, mctx);
+                       clean_trustedkey();
+                       return;
+               }
+       }
+
+   
+       if (have_answer) {
+               chase_rdataset
+                       = chase_scanname_section(msg, &chase_name,
+                                                current_lookup
+                                                ->rdtype_sigchase,
+                                                dns_rdatatype_any,
+                                                DNS_SECTION_ANSWER);
+               if (chase_rdataset != NULL)
+                       have_response = ISC_TRUE;
+       }
+
+       result = advanced_rrsearch(&chase_keyrdataset,
+                                  &chase_current_name,
+                                  dns_rdatatype_dnskey,
+                                  dns_rdatatype_any,
+                                  &chase_keylookedup);
+       if (result == ISC_R_FAILURE) {
+               printf("\n;; DNSKEY is missing to continue validation:"
+                      " FAILED\n\n");
+               goto cleanandgo;
+       }
+       if (result == ISC_R_NOTFOUND)
+               return;
+       INSIST(chase_keyrdataset != NULL);
+       printf("\n;; DNSKEYset:\n");
+       print_rdataset(&chase_current_name , chase_keyrdataset, mctx);
+
+
+       result = advanced_rrsearch(&chase_sigkeyrdataset,
+                                  &chase_current_name,
+                                  dns_rdatatype_rrsig,
+                                  dns_rdatatype_dnskey,
+                                  &chase_sigkeylookedup);
+       if (result == ISC_R_FAILURE) {
+               printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
+                      " FAILED\n\n");
+               goto cleanandgo;
+       }
+       if (result == ISC_R_NOTFOUND)
+               return;
+       INSIST(chase_sigkeyrdataset != NULL);
+       printf("\n;; RRSIG of the DNSKEYset:\n");
+       print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx);
+
+
+       if (!chase_dslookedup && !chase_nslookedup) {
+               if (!delegation_follow) {
+                       result = contains_trusted_key(&chase_current_name,
+                                                     chase_keyrdataset,
+                                                     chase_sigkeyrdataset,
+                                                     mctx);
+               } 
+               else {
+                       INSIST(chase_dsrdataset != NULL);
+                       INSIST(chase_sigdsrdataset != NULL);
+                       result = sigchase_verify_ds(&chase_current_name,
+                                                   chase_keyrdataset,
+                                                   chase_dsrdataset,
+                                                   mctx);
+               }
+      
+               if (result != ISC_R_SUCCESS) {
+                       printf("\n;; chain of trust can't be validated:"
+                              " FAILED\n\n");
+                       goto cleanandgo;
+               }
+               else {
+                       chase_dsrdataset = NULL;
+                       chase_sigdsrdataset = NULL;
+               }
+       }
+
+       if (have_response || (!have_delegation_ns && !have_response)) {
+               /* test if it's a grand father case */
+
+               if (have_response) {
+                       result = advanced_rrsearch(&chase_sigrdataset,
+                                                  &chase_name,
+                                                  dns_rdatatype_rrsig,
+                                                  current_lookup
+                                                  ->rdtype_sigchase,
+                                                  &true);
+                       if (result == ISC_R_FAILURE) {
+                               printf("\n;; RRset is missing to continue"
+                                      " validation SHOULD NOT APPEND:"
+                                      " FAILED\n\n");
+                               goto cleanandgo;
+                       }
+        
+               }
+               else {
+                       result = advanced_rrsearch(&chase_sigrdataset,
+                                                  &chase_authority_name,
+                                                  dns_rdatatype_rrsig,
+                                                  dns_rdatatype_any,
+                                                  &true);
+                       if (result == ISC_R_FAILURE) {
+                               printf("\n;; RRSIG is missing  to continue"
+                                      " validation SHOULD NOT APPEND:"
+                                      " FAILED\n\n");
+                               goto cleanandgo;
+                       }
+               }
+               result =  grandfather_pb_test(&chase_current_name,
+                                             chase_sigrdataset);
+               if (result != ISC_R_SUCCESS) {
+                       dns_name_t tmp_name;
+
+                       printf("\n;; We are in a Grand Father Problem:"
+                              " See 2.2.1 in RFC 3568\n");
+                       chase_rdataset = NULL;
+                       chase_sigrdataset = NULL;
+                       have_response = ISC_FALSE;
+                       have_delegation_ns = ISC_FALSE;
+         
+                       dns_name_init(&tmp_name, NULL);
+                       result = child_of_zone(&chase_name, &chase_current_name,
+                                              &tmp_name);
+                       if (chase_authority_name.labels != 0)
+                               dns_name_free( &chase_authority_name, mctx);
+                       dup_name(&tmp_name, &chase_authority_name, mctx);
+                       printf(";; and we try to continue chain of trust"
+                              " validation of the zone: ");
+                       dns_name_print(&chase_authority_name, stdout);
+                       printf("\n");
+                       have_delegation_ns = ISC_TRUE;
+               }
+               else {
+                       if (have_response)
+                               goto finalstep;
+                       else
+                               chase_sigrdataset = NULL;
+               }
+       }
+
+       if (have_delegation_ns) {
+               chase_nsrdataset = NULL;
+               result = advanced_rrsearch(&chase_nsrdataset,
+                                          &chase_authority_name,
+                                          dns_rdatatype_ns,
+                                          dns_rdatatype_any,
+                                          &chase_nslookedup);
+               if (result == ISC_R_FAILURE) {
+                       printf("\n;;NSset is missing to continue validation:"
+                              " FAILED\n\n");
+                       goto cleanandgo;
+               }
+               if (result == ISC_R_NOTFOUND) {
+                       return;
+               }
+               INSIST(chase_nsrdataset != NULL);
+  
+               result = advanced_rrsearch(&chase_dsrdataset,
+                                          &chase_authority_name,
+                                          dns_rdatatype_ds,
+                                          dns_rdatatype_any,
+                                          &chase_dslookedup);
+               if (result == ISC_R_FAILURE) {
+                       printf("\n;; DSset is missing to continue validation:"
+                              " FAILED\n\n");
+                       goto cleanandgo;
+               }
+               if (result == ISC_R_NOTFOUND)
+                       return;
+               INSIST(chase_dsrdataset != NULL);
+               printf("\n;; DSset:\n");
+               print_rdataset(&chase_authority_name , chase_dsrdataset, mctx);
+
+               result = advanced_rrsearch(&chase_sigdsrdataset,
+                                          &chase_authority_name,
+                                          dns_rdatatype_rrsig,
+                                          dns_rdatatype_ds,
+                                          &true);
+               if (result != ISC_R_SUCCESS) {
+                       printf("\n;; DSset is missing to continue validation:"
+                              " FAILED\n\n");
+                       goto cleanandgo;
+               }
+               printf("\n;; RRSIGset of DSset\n");
+               print_rdataset(&chase_authority_name,
+                              chase_sigdsrdataset, mctx);
+               INSIST(chase_sigdsrdataset != NULL);
+
+               result = sigchase_verify_sig(&chase_authority_name,
+                                            chase_dsrdataset,
+                                            chase_keyrdataset,
+                                            chase_sigdsrdataset, mctx);
+               if (result != ISC_R_SUCCESS) {
+                       printf("\n;; Impossible to verify the DSset:"
+                              " FAILED\n\n");
+                       goto cleanandgo;
+               }
+               chase_keyrdataset = NULL;
+               chase_sigkeyrdataset = NULL;
+    
+               prepare_lookup(&chase_authority_name);
+       
+               have_response = ISC_FALSE;
+               have_delegation_ns = ISC_FALSE;
+               delegation_follow = ISC_TRUE;
+               error_message = NULL;
+               dns_name_free(&chase_current_name, mctx);
+               dup_name(&chase_authority_name, &chase_current_name, mctx);
+               dns_name_free(&chase_authority_name, mctx);
+               return;
+       }
+
+  
+       if (error_message != NULL) {
+               dns_rdataset_t * rdataset;
+               dns_rdataset_t * sigrdataset;
+               dns_name_t       rdata_name;
+               isc_result_t     ret = ISC_R_FAILURE;
+
+               result = prove_nx(error_message, &chase_name,
+                                 current_lookup->rdclass_sigchase,
+                                 current_lookup->rdtype_sigchase, &rdata_name,
+                                 &rdataset, &sigrdataset);
+               if (&rdata_name == NULL || rdataset == NULL ||
+                   sigrdataset == NULL) {
+                       printf("\n;; Impossible to verify the non-existence,"
+                              " the NSEC RRset can't be validated:"
+                              " FAILED\n\n");
+                       goto cleanandgo;
+               }
+               ret = sigchase_verify_sig(&rdata_name, rdataset,
+                                         chase_keyrdataset,
+                                         sigrdataset, mctx);
+               if (ret != ISC_R_SUCCESS) {
+                       dns_name_free(&rdata_name, mctx);
+                       printf("\n;; Impossible to verify the NSEC RR to prove"
+                              " the non-existence : FAILED\n\n");
+                       goto cleanandgo;
+               }
+               dns_name_free(&rdata_name, mctx);
+               if (result != ISC_R_SUCCESS) {
+                       printf("\n;; Impossible to verify the non-existence:"
+                              " FAILED\n\n");
+                       goto cleanandgo;
+               }
+               else {
+                       printf("\n;; OK the query doesn't have response but"
+                              " we have validate this fact : SUCCESS\n\n");
+                       goto cleanandgo;
+               }
+       }
+
+ cleanandgo:
+       printf(";; cleanandgo \n");
+       dns_name_free(&chase_name, mctx);
+       if (chase_current_name.labels != 0)
+               dns_name_free(&chase_current_name, mctx);
+       if (chase_authority_name.labels != 0)
+               dns_name_free(&chase_authority_name, mctx);
+       clean_trustedkey();
+       return;
+
+       finalstep :
+               result = advanced_rrsearch(&chase_rdataset, &chase_name,
+                                          current_lookup->rdtype_sigchase,
+                                          dns_rdatatype_any ,
+                                          &true);
+       if (result == ISC_R_FAILURE) {
+               printf("\n;; RRsig of RRset is missing to continue validation"
+                      " SHOULD NOT APPEND: FAILED\n\n");
+               goto cleanandgo;
+       }
+       result = sigchase_verify_sig(&chase_name, chase_rdataset,
+                                    chase_keyrdataset,
+                                    chase_sigrdataset, mctx);
+       if (result != ISC_R_SUCCESS) {
+               printf("\n;; Impossible to verify the RRset : FAILED\n\n");
+               /*
+                 printf("RRset:\n");
+                 print_rdataset(&chase_name , chase_rdataset, mctx);
+                 printf("DNSKEYset:\n");
+                 print_rdataset(&chase_name , chase_keyrdataset, mctx);
+                 printf("RRSIG of RRset:\n");
+                 print_rdataset(&chase_name , chase_sigrdataset, mctx);
+                 printf("\n");
+               */
+               goto cleanandgo;
+       }
+       else {
+               printf("\n;; The Answer:\n");
+               print_rdataset(&chase_name , chase_rdataset, mctx);
+
+               printf("\n;; FINISH : we have validate the DNSSEC chain"
+                      " of trust: SUCCESS\n\n");
+               goto cleanandgo;
+       }
+}
+
+#endif 
+
+
+#if DIG_SIGCHASE_BU
+
+isc_result_t
+getneededrr(dns_message_t *msg)
+{
+       isc_result_t result;
+       dns_name_t *name = NULL;
+       dns_rdata_t sigrdata;
+       dns_rdata_sig_t siginfo;
+       isc_boolean_t   true = ISC_TRUE;
+
+       if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
+           != ISC_R_SUCCESS) {
+               printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
+    
+               if (chase_name.ndata == NULL) {
+                       return ISC_R_ADDRNOTAVAIL;
+               }
+       }
+       else {
+               dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+       }
+
+       /* What do we chase? */
+       if (chase_rdataset == NULL) {
+               result = advanced_rrsearch(&chase_rdataset, name,
+                                          dns_rdatatype_any,
+                                          dns_rdatatype_any, &true);
+               if (result != ISC_R_SUCCESS) {
+                       printf("\n;; No Answers: Validation FAILED\n\n");
+                       return ISC_R_NOTFOUND;
+               }
+               dup_name(name, &chase_name, mctx);
+               printf(";; RRset to chase:\n");
+               print_rdataset(&chase_name, chase_rdataset, mctx);
+       }
+       INSIST(chase_rdataset != NULL);
+
+
+       if (chase_sigrdataset == NULL) {
+               result = advanced_rrsearch(&chase_sigrdataset, name,
+                                          dns_rdatatype_rrsig,
+                                          chase_rdataset->type,
+                                          &chase_siglookedup);
+               if (result == ISC_R_FAILURE) {
+                       printf("\n;; RRSIG is missing for continue validation:"
+                              " FAILED\n\n");
+                       if (chase_name.ndata != NULL)
+                               dns_name_free(&chase_name, mctx);
+                       return ISC_R_NOTFOUND;
+               }
+               if (result == ISC_R_NOTFOUND) {
+                       return(ISC_R_NOTFOUND);
+               }
+               printf("\n;; RRSIG of the RRset to chase:\n");
+               print_rdataset(&chase_name, chase_sigrdataset, mctx);
+       }
+       INSIST(chase_sigrdataset != NULL);
+
+       /* first find the DNSKEY name */
+       result = dns_rdataset_first(chase_sigrdataset);
+       check_result(result, "empty RRSIG dataset");
+       dns_rdata_init(&sigrdata);
+       dns_rdataset_current(chase_sigrdataset, &sigrdata);
+       result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+       check_result(result, "sigrdata tostruct siginfo");
+       dup_name(&siginfo.signer, &chase_signame, mctx);
+       dns_rdata_freestruct(&siginfo);
+       dns_rdata_reset(&sigrdata);
+       /* Do we have a key?  */
+       if (chase_keyrdataset == NULL) {
+               result = advanced_rrsearch(&chase_keyrdataset,
+                                          &chase_signame,
+                                          dns_rdatatype_dnskey,
+                                          dns_rdatatype_any,
+                                          &chase_keylookedup);
+               if (result == ISC_R_FAILURE) {
+                       printf("\n;; DNSKEY is missing to continue validation:"
+                              " FAILED\n\n");
+                       dns_name_free(&chase_signame, mctx);
+                       if (chase_name.ndata != NULL)
+                               dns_name_free(&chase_name, mctx);
+                       return ISC_R_NOTFOUND;
+               }
+               if (result == ISC_R_NOTFOUND) {
+                       dns_name_free(&chase_signame, mctx);
+                       return(ISC_R_NOTFOUND);
+               }
+               printf("\n;; DNSKEYset that signs the RRset to chase:\n");
+               print_rdataset(&chase_signame, chase_keyrdataset, mctx);
+       }
+       INSIST(chase_keyrdataset != NULL);
+
+       if (chase_sigkeyrdataset == NULL) {
+               result = advanced_rrsearch(&chase_sigkeyrdataset,
+                                          &chase_signame,
+                                          dns_rdatatype_rrsig,
+                                          dns_rdatatype_dnskey,
+                                          &chase_sigkeylookedup);
+               if (result == ISC_R_FAILURE) {
+                       printf("\n;; RRSIG for DNSKEY  is missing  to continue"
+                              " validation : FAILED\n\n");
+                       dns_name_free(&chase_signame, mctx);
+                       if (chase_name.ndata != NULL)
+                               dns_name_free(&chase_name, mctx);
+                       return ISC_R_NOTFOUND;
+               }
+               if (result == ISC_R_NOTFOUND) {
+                       dns_name_free(&chase_signame, mctx);
+                       return(ISC_R_NOTFOUND);
+               }
+               printf("\n;; RRSIG of the DNSKEYset that signs the "
+                      "RRset to chase:\n");
+               print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
+       }
+       INSIST(chase_sigkeyrdataset != NULL);
+
+
+       if (chase_dsrdataset == NULL) {
+               result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
+                                          dns_rdatatype_ds,
+                                          dns_rdatatype_any,
+               &chase_dslookedup);
+               if (result == ISC_R_FAILURE) {
+                       printf("\n;; WARNING There is no DS for the zone: ");
+                       dns_name_print(&chase_signame, stdout);
+                       printf("\n");
+               }
+               if (result == ISC_R_NOTFOUND) {
+                       dns_name_free(&chase_signame, mctx);
+                       return(ISC_R_NOTFOUND);
+               }
+               if (chase_dsrdataset != NULL) {
+                       printf("\n;; DSset of the DNSKEYset\n");
+                       print_rdataset(&chase_signame, chase_dsrdataset, mctx);
+               }
+       }
+       if (chase_dsrdataset != NULL) {
+               /*
+                * if there is no RRSIG of DS,
+                * we don't want to search on the network
+                */
+               result = advanced_rrsearch(&chase_sigdsrdataset,
+                                          &chase_signame,
+                                          dns_rdatatype_rrsig,
+                                          dns_rdatatype_ds, &true);
+               if (result == ISC_R_FAILURE) {
+                       printf(";; WARNING : NO RRSIG DS : RRSIG DS"
+                              " should come with DS\n");
+                       /*
+                        * We continue even the DS couldn't be validated,
+                        * because the DNSKEY could be a Trusted Key.
+                        */
+                       chase_dsrdataset = NULL;
+               }
+               else {
+                       printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
+                       print_rdataset(&chase_signame, chase_sigdsrdataset,
+                                      mctx);
+               }
+       }
+       return(1);
+}
+
+
+
+void
+sigchase_bu(dns_message_t *msg)
+{
+       isc_result_t result;
+       int ret;
+
+       if (tk_list.nb_tk == 0) {
+               result = get_trusted_key(mctx);
+               if (result != ISC_R_SUCCESS) {
+                       printf("No trusted keys present\n");
+                       return;
+               }
+       }
+
+  
+       ret = getneededrr(msg);
+       if (ret == ISC_R_NOTFOUND)
+               return;
+
+       if (ret == ISC_R_ADDRNOTAVAIL) {
+               /* We have no response */
+               dns_rdataset_t * rdataset;
+               dns_rdataset_t * sigrdataset;
+               dns_name_t       rdata_name;
+               dns_name_t       query_name;
+
+
+               nameFromString(current_lookup->textname, &query_name);
+   
+               result = prove_nx(msg, &query_name, current_lookup->rdclass,
+                                 current_lookup->rdtype, &rdata_name,
+                                 &rdataset, &sigrdataset);
+               dns_name_free(&query_name, mctx);
+               if (&rdata_name == NULL || rdataset == NULL ||
+                   sigrdataset == NULL) {
+                       printf("\n;; Impossible to verify the Non-existence,"
+                              " the NSEC RRset can't be validated: "
+                              "FAILED\n\n");
+                       clean_trustedkey();
+                       return;
+               }
+
+               if (result != ISC_R_SUCCESS) {
+                       printf("\n No Answers and impossible to prove the"
+                              " unsecurity : Validation FAILED\n\n");
+                       clean_trustedkey();
+                       return;
+               }
+               printf(";; An NSEC prove the non-existence of a answers,"
+                      " Now we want validate this NSEC\n");
+       
+               dup_name(&rdata_name, &chase_name, mctx);
+               dns_name_free(&rdata_name, mctx);
+               chase_rdataset =  rdataset;
+               chase_sigrdataset = sigrdataset;
+               chase_keyrdataset = NULL;
+               chase_sigkeyrdataset = NULL;
+               chase_dsrdataset = NULL;
+               chase_sigdsrdataset = NULL;
+               chase_siglookedup = ISC_FALSE;
+               chase_keylookedup = ISC_FALSE;
+               chase_dslookedup = ISC_FALSE;
+               chase_sigdslookedup = ISC_FALSE;
+               sigchase(msg);
+               clean_trustedkey();
+               return;
+       }
+  
+
+       printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
+
+       result = sigchase_verify_sig(&chase_name, chase_rdataset,
+                                    chase_keyrdataset,
+                                    chase_sigrdataset, mctx);
+       if (result != ISC_R_SUCCESS) {
+               dns_name_free(&chase_name, mctx);
+               dns_name_free(&chase_signame, mctx);
+               printf(";; No DNSKEY is valid to check the RRSIG"
+                      " of the RRset: FAILED\n");
+               clean_trustedkey();
+               return;
+       }
+       printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
+
+       result = contains_trusted_key(&chase_signame, chase_keyrdataset,
+                                     chase_sigkeyrdataset, mctx);
+       if (result ==  ISC_R_SUCCESS) {
+               dns_name_free(&chase_name, mctx);
+               dns_name_free(&chase_signame, mctx);
+               printf("\n;; Ok this DNSKEY is a Trusted Key,"
+                      " DNSSEC validation is ok: SUCCESS\n\n");
+               clean_trustedkey();
+               return;
+       }
+
+       printf(";; Now, we are going to validate this DNSKEY by the DS\n");
+
+       if (chase_dsrdataset == NULL) {
+               dns_name_free(&chase_name, mctx);
+               dns_name_free(&chase_signame, mctx);
+               printf(";; the DNSKEY isn't trusted-key and there isn't"
+                      " DS to validate the DNSKEY: FAILED\n");
+               clean_trustedkey();
+               return;
+       }
+
+       result =  sigchase_verify_ds(&chase_signame, chase_keyrdataset,
+                                    chase_dsrdataset, mctx);
+       if (result !=  ISC_R_SUCCESS) {
+               dns_name_free(&chase_signame, mctx);
+               dns_name_free(&chase_name, mctx);
+               printf(";; ERROR no DS validates a DNSKEY in the"
+                      " DNSKEY RRset: FAILED\n");
+               clean_trustedkey();
+               return;
+       } 
+       else
+               printf(";; OK this DNSKEY (validated by the DS) validates"
+                      " the RRset of the DNSKEYs, thus the DNSKEY validates"
+                      " the RRset\n");
+       INSIST(chase_sigdsrdataset != NULL);
+
+       dns_name_free(&chase_name, mctx);
+       dup_name(&chase_signame, &chase_name, mctx);
+       dns_name_free(&chase_signame, mctx);
+       chase_rdataset = chase_dsrdataset;
+       chase_sigrdataset = chase_sigdsrdataset;
+       chase_keyrdataset = NULL;
+       chase_sigkeyrdataset = NULL;
+       chase_dsrdataset = NULL;
+       chase_sigdsrdataset = NULL;
+       chase_siglookedup = chase_keylookedup = ISC_FALSE;
+       chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
+       printf(";; Now, we want to validate the DS :  recursive call\n");
+       sigchase(msg);
+       return;
+}
+#endif
+
+void
+sigchase(dns_message_t * msg)
+{
+#if DIG_SIGCHASE_TD
+       if (current_lookup->do_topdown) {
+               sigchase_td(msg);
+               return;
+       }
+#endif
+#if DIG_SIGCHASE_BU
+       sigchase_bu(msg);
+       return;
+#endif
+}
+
+
+/*
+ * return 1  if name1  <  name2
+ *        0  if name1  == name2
+ *        -1 if name1  >  name2
+ *    and -2 if problem
+ */
+int
+inf_name(dns_name_t * name1, dns_name_t * name2)
+{
+       dns_label_t  label1;
+       dns_label_t  label2;
+       unsigned int nblabel1;
+       unsigned int nblabel2;
+       int min_lum_label;
+       int i;
+       int ret = -2;
+
+       nblabel1 = dns_name_countlabels(name1);
+       nblabel2 = dns_name_countlabels(name2);
+
+       if (nblabel1 >= nblabel2)
+               min_lum_label = nblabel2;
+       else
+               min_lum_label = nblabel1;
+
+
+       for (i=1 ; i < min_lum_label; i++) {
+               dns_name_getlabel(name1, nblabel1 -1  - i, &label1);
+               dns_name_getlabel(name2, nblabel2 -1  - i, &label2);
+               if ((ret = isc_region_compare(&label1, &label2)) != 0) {
+                       if (ret <0 )
+                               return -1;
+                       else if (ret >0 )
+                               return 1;
+               }
+       }
+       if (nblabel1 == nblabel2)
+               return 0;
+
+       if (nblabel1 < nblabel2)
+               return -1;
+       else
+               return 1;
+}
+
+/**
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx_domain(dns_message_t *msg,
+               dns_name_t *name,
+               dns_name_t *rdata_name,
+               dns_rdataset_t ** rdataset,
+               dns_rdataset_t **sigrdataset)
+{
+       isc_result_t      ret = ISC_R_FAILURE;
+       isc_result_t      result = ISC_R_NOTFOUND;
+       dns_rdataset_t  * nsecset = NULL;
+       dns_rdataset_t  * signsecset = NULL ;
+       dns_rdata_t       nsec = DNS_RDATA_INIT;
+       dns_name_t      * nsecname = NULL;
+       dns_rdata_nsec_t  nsecstruct;
+  
+       if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
+           != ISC_R_SUCCESS) {
+               printf(";; nothing in authority section : impossible to"
+                      " validate the non-existence : FAILED\n");
+               return(ISC_R_FAILURE);
+       }
+       do {
+               dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
+               nsecset = search_type(nsecname, dns_rdatatype_nsec,
+                                     dns_rdatatype_any);
+               if (nsecset == NULL)
+                       continue;
+
+               printf("There is a NSEC for this zone in the"
+                      " AUTHORITY section:\n");
+               print_rdataset(nsecname, nsecset, mctx);
+
+               for (result = dns_rdataset_first(nsecset);
+                    result == ISC_R_SUCCESS;
+                    result = dns_rdataset_next(nsecset)) {
+                       dns_rdataset_current(nsecset, &nsec);
+
+
+                       signsecset
+                               = chase_scanname_section(msg, nsecname,
+                                                dns_rdatatype_rrsig,
+                                                dns_rdatatype_nsec,
+                                                DNS_SECTION_AUTHORITY);
+                       if (signsecset == NULL) {
+                               printf(";; no RRSIG NSEC in authority section:"
+                                      " impossible to validate the "
+                                      "non-existence: FAILED\n");
+                               return(ISC_R_FAILURE);
+                       }
+
+                       ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
+                       check_result(ret,"dns_rdata_tostruct");
+
+                       if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
+                            inf_name(name, &nsecstruct.next) == 1) ||
+                           (inf_name(name, nsecname) == 1 &&
+                            inf_name(&nsecstruct.next, name) == 1)) {
+                               dns_rdata_freestruct(&nsecstruct);
+                               *rdataset = nsecset;
+                               *sigrdataset = signsecset;
+                               dup_name(nsecname, rdata_name, mctx);
+               
+                               return ISC_R_SUCCESS;
+                       }
+
+                       dns_rdata_freestruct(&nsecstruct);
+               }
+               nsecname = NULL;
+       } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
+                == ISC_R_SUCCESS);
+
+       *rdataset = NULL;
+       *sigrdataset =  NULL;
+       rdata_name = NULL;
+       return(ISC_R_FAILURE);
+}
+
+/**
+ *
+ *
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx_type(dns_message_t * msg,
+             dns_name_t *name,
+             dns_rdataset_t *nsecset,
+             dns_rdataclass_t class,
+             dns_rdatatype_t type,
+             dns_name_t * rdata_name,
+             dns_rdataset_t ** rdataset,
+             dns_rdataset_t ** sigrdataset)
+{
+       isc_result_t       ret;
+       dns_rdataset_t   * signsecset;
+       dns_rdata_t        nsec = DNS_RDATA_INIT;
+
+       UNUSED(class);
+       UNUSED(rdata_name);
+  
+       ret = dns_rdataset_first(nsecset);
+       check_result(ret,"dns_rdataset_first");
+       
+       dns_rdataset_current(nsecset, &nsec);
+  
+       ret = dns_nsec_typepresent(&nsec, type);
+       if (ret == ISC_R_SUCCESS)
+               printf("OK the NSEC said that the type doesn't exist \n");
+
+       signsecset = chase_scanname_section(msg, name,
+                                           dns_rdatatype_rrsig,
+                                           dns_rdatatype_nsec,
+                                           DNS_SECTION_AUTHORITY);
+       if (signsecset == NULL) {
+               printf("There isn't RRSIG NSEC for the zone \n");
+               return ISC_R_FAILURE;
+       }
+       *rdataset = nsecset;
+       *sigrdataset = signsecset;
+
+       return (ret);
+}
+
+/**
+ *
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx(dns_message_t * msg,
+        dns_name_t * name,
+        dns_rdataclass_t class,
+        dns_rdatatype_t type,
+        dns_name_t * rdata_name,
+        dns_rdataset_t ** rdataset,
+        dns_rdataset_t ** sigrdataset)
+{
+       isc_result_t ret;
+       dns_rdataset_t * nsecset = NULL;
+  
+
+       printf("We want to prove the non-existance of a type of rdata %d"
+              " or of the zone: \n", type);
+
+       if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
+           != ISC_R_SUCCESS) {
+               printf(";; nothing in authority section : impossible to"
+                      " validate the non-existence : FAILED\n");
+               return(ISC_R_FAILURE);
+       }
+
+       nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
+                                        dns_rdatatype_any,
+                                        DNS_SECTION_AUTHORITY);
+       if (nsecset != NULL) {
+               printf("We have a NSEC for this zone :OK\n");
+               ret = prove_nx_type(msg, name, nsecset, class,
+                                   type, rdata_name, rdataset,
+                                   sigrdataset);
+               if (ret != ISC_R_SUCCESS) {
+                       printf("prove_nx: ERROR type exist\n");
+                       return(ret);
+               } else {
+                       printf("prove_nx: OK type does not exist\n");
+                       return(ISC_R_SUCCESS);
+               }
+       } else {
+               printf("there is no NSEC for this zone: validating "
+                      "that the zone doesn't exist\n");
+               ret = prove_nx_domain(msg, name, rdata_name,
+                                     rdataset, sigrdataset);
+               return(ret);
+       }
+       /* Never get here */ 
+}
+#endif
index b0a79611aa78380ee3610aee7385fcd4cea03429..719fe75b03d237098c61b23e1093e339c2d0bed2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: host.c,v 1.95 2004/04/13 01:09:37 marka Exp $ */
+/* $Id: host.c,v 1.96 2004/04/13 02:39:35 marka Exp $ */
 
 #include <config.h>
 #include <limits.h>
@@ -209,8 +209,18 @@ say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata,
        printf("\n");
        isc_buffer_free(&b);
 }
-
-
+#ifdef _SIGCHASE_
+/* Just for compatibility : not use in host program */
+isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+             isc_buffer_t *target)
+{
+  UNUSED(owner_name);
+  UNUSED(rdataset);
+  UNUSED(target);
+  return(ISC_FALSE);
+}
+#endif
 static isc_result_t
 printsection(dns_message_t *msg, dns_section_t sectionid,
             const char *section_name, isc_boolean_t headers,
@@ -698,8 +708,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
 
        lookup->pending = ISC_FALSE;
        if (get_reverse(store, sizeof(store), hostname,
-                       lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) 
-       {
+                       lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) {
                strncpy(lookup->textname, store, sizeof(lookup->textname));
                lookup->textname[sizeof(lookup->textname)-1] = 0;
                lookup->rdtype = dns_rdatatype_ptr;
index 9a1284d53b6292b95cc9725dae985a9e68fdf584..4c6b43aa7bf24f7d5f69387991440019674e2aa2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dig.h,v 1.82 2004/03/05 04:57:34 marka Exp $ */
+/* $Id: dig.h,v 1.83 2004/04/13 02:39:35 marka Exp $ */
 
 #ifndef DIG_H
 #define DIG_H
@@ -79,6 +79,9 @@ ISC_LANG_BEGINDECLS
 typedef struct dig_lookup dig_lookup_t;
 typedef struct dig_query dig_query_t;
 typedef struct dig_server dig_server_t;
+#ifdef _SIGCHASE_
+typedef struct dig_message dig_message_t;
+#endif
 typedef ISC_LIST(dig_server_t) dig_serverlist_t;
 typedef struct dig_searchlist dig_searchlist_t;
 
@@ -110,10 +113,27 @@ struct dig_lookup {
                new_search,
                besteffort,
                dnssec;
+#ifdef _SIGCHASE_
+isc_boolean_t  sigchase;
+#ifdef _SIGCHASE_TD_
+isc_boolean_t  do_topdown,
+               trace_root_sigchase,
+               rdtype_sigchaseset,
+               rdclass_sigchaseset;
+       /* Name we are going to validate RRset */
+       char textnamesigchase[MXNAME];
+#endif
+#endif
+       
        char textname[MXNAME]; /* Name we're going to be looking up */
        char cmdline[MXNAME];
        dns_rdatatype_t rdtype;
        dns_rdatatype_t qrdtype;
+#ifdef _SIGCHASE_TD_
+        dns_rdatatype_t rdtype_sigchase;
+        dns_rdatatype_t qrdtype_sigchase;
+        dns_rdataclass_t rdclass_sigchase;
+#endif
        dns_rdataclass_t rdclass;
        isc_boolean_t rdtypeset;
        isc_boolean_t rdclassset;
@@ -183,7 +203,12 @@ struct dig_searchlist {
        char origin[MXNAME];
        ISC_LINK(dig_searchlist_t) link;
 };
-
+#ifdef _SIGCHASE_
+struct dig_message {
+               dns_message_t *msg;
+               ISC_LINK(dig_message_t) link;
+};
+#endif
 /*
  * Routines in dighost.c.
  */
@@ -255,9 +280,19 @@ destroy_libs(void);
 void
 set_search_domain(char *domain);
 
+#ifdef _SIGCHASE_
+void
+clean_trustedkey(void);
+#endif
+
 /*
  * Routines to be defined in dig.c, host.c, and nslookup.c.
  */
+#ifdef _SIGCHASE_
+isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+             isc_buffer_t *target);
+#endif
 
 isc_result_t
 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers);
@@ -282,6 +317,14 @@ dighost_shutdown(void);
 char *
 next_token(char **stringp, const char *delim);
 
+#ifdef _SIGCHASE_
+/* Chasing functions */
+dns_rdataset_t *
+chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers);
+void
+chase_sig(dns_message_t *msg);
+#endif
+
 ISC_LANG_ENDDECLS
 
 #endif
index 7b3b5a37a7cdd7c91551a23674126b058f943d7e..7d7b1dab91463d79b612bb1af6437159b259d296 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: nslookup.c,v 1.101 2004/03/05 04:57:30 marka Exp $ */
+/* $Id: nslookup.c,v 1.102 2004/04/13 02:39:35 marka Exp $ */
 
 #include <config.h>
 
@@ -189,7 +189,18 @@ printa(dns_rdata_t *rdata) {
        printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
               (char *)isc_buffer_base(&b));
 }
-
+#ifdef _SIGCHASE_
+/* Just for compatibility : not use in host program */
+isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+             isc_buffer_t *target)
+{
+       UNUSED(owner_name);
+       UNUSED(rdataset);
+       UNUSED(target);
+       return(ISC_FALSE);
+}
+#endif
 static void
 printrdata(dns_rdata_t *rdata) {
        isc_result_t result;
@@ -520,7 +531,8 @@ safecpy(char *dest, char *src, int size) {
 }
 
 static isc_result_t
-parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, const char *desc) {
+parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
+          const char *desc) {
        isc_uint32_t n;
        isc_result_t result = isc_parse_uint32(&n, value, 10);
        if (result == ISC_R_SUCCESS && n > max)
@@ -663,8 +675,7 @@ addlookup(char *opt) {
        }
        lookup = make_empty_lookup();
        if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
-           == ISC_R_SUCCESS)
-       {
+           == ISC_R_SUCCESS) {
                safecpy(lookup->textname, store, sizeof(lookup->textname));
                lookup->rdtype = dns_rdatatype_ptr;
                lookup->rdtypeset = ISC_TRUE;
@@ -732,15 +743,13 @@ get_next_command(void) {
                in_use = ISC_FALSE;
                goto cleanup;
        } else if (strcasecmp(ptr, "help") == 0 ||
-                  strcasecmp(ptr, "?") == 0)
-       {
+                  strcasecmp(ptr, "?") == 0) {
                printf("The '%s' command is not yet implemented.\n", ptr);
                goto cleanup;
        } else if (strcasecmp(ptr, "finger") == 0 ||
                   strcasecmp(ptr, "root") == 0 ||
                   strcasecmp(ptr, "ls") == 0 ||
-                  strcasecmp(ptr, "view") == 0)
-       {
+                  strcasecmp(ptr, "view") == 0) {
                printf("The '%s' command is not implemented.\n", ptr);
                goto cleanup;
        } else