* 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>
#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>
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
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;
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;
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;
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");
}
}
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
*/
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 {
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);
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;
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);
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);
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;
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);
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);
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) {
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;
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;
}
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,
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.");
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;
}
*/
void
destroy_libs(void) {
+#ifdef DIG_SIGCHASE
+ void * ptr;
+ dig_message_t *chase_msg;
+#endif
debug("destroy_libs()");
if (global_task != NULL) {
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