diff --git a/CHANGES b/CHANGES index e6068f4bd3..0b4e537943 100644 --- 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 717d8fd47d..aa7ce9503b 100644 --- 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. diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in index c7b43377af..e74e55c977 100644 --- a/bin/dig/Makefile.in +++ b/bin/dig/Makefile.in @@ -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 diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 98c50168de..5d72a0f80d 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -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 #include @@ -43,6 +43,15 @@ #include +#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(); diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook index fbe3031a0c..7724593785 100644 --- a/bin/dig/dig.docbook +++ b/bin/dig/dig.docbook @@ -16,7 +16,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -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 dig output. - - + 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. - + - Attempt to display the contents of messages which are malformed. The default is to not display malformed answers. - + - Requests DNSSEC records be sent by setting the DNSSEC OK bit (DO) in the OPT record in the additional section of the query. - + + + + +Chase DNSSEC signature chains. Requires dig be compiled with +-DDIG_SIGCHASE. + + + + +Specify a trusted key to be used with . +Requires dig be compiled with -DDIG_SIGCHASE. + + + + +When chasing DNSSEC signature chains perform a top down validation. +Requires dig be compiled with -DDIG_SIGCHASE. + + + diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index be3d2d7062..cecde0c26e 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -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 @@ -32,7 +32,24 @@ #include #include +#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 +#ifdef DIG_SIGCHASE +#include +#include +#include +#include +#include +#include +#endif #include #include #include @@ -52,6 +69,9 @@ #include #include #include +#ifdef DIG_SIGCHASE +#include +#endif #include #include #include @@ -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 diff --git a/bin/dig/host.c b/bin/dig/host.c index b0a79611aa..719fe75b03 100644 --- a/bin/dig/host.c +++ b/bin/dig/host.c @@ -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 #include @@ -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; diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index 9a1284d53b..4c6b43aa7b 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -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 diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c index 7b3b5a37a7..7d7b1dab91 100644 --- a/bin/dig/nslookup.c +++ b/bin/dig/nslookup.c @@ -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 @@ -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