fix: populate ldns submodule and add autotools to LDNS build stage
- Re-cloned zonemaster-ldns with --recurse-submodules so the bundled ldns C library source (including Changelog and configure.ac) is present - Added autoconf, automake, libtool to Dockerfile.backend ldns-build stage so libtoolize + autoreconf can generate ldns/configure during make Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
105
zonemaster-ldns/ldns/drill/ChangeLog.22-nov-2005
Normal file
105
zonemaster-ldns/ldns/drill/ChangeLog.22-nov-2005
Normal file
@@ -0,0 +1,105 @@
|
||||
--------- Drill now is a subdirectory in ldns. To make life easier
|
||||
--------- we are using ldns' version numbering for drill from now on.
|
||||
--------- Sadly this means we GO BACKWARDS in the versions
|
||||
--------- This ChangeLog will not be updated anymore - all changes are
|
||||
--------- documented in ldns' ChangeLog
|
||||
|
||||
1.0-pre3: to be released: drill-team
|
||||
* Secure tracing works
|
||||
* Added section about DNSSEC in the manual page
|
||||
* Allow the class information to be given to do_chase()
|
||||
* Lint fixes for the code
|
||||
* Bugzilla was setup for drill
|
||||
* Bug #97 (drill); -S crash was fixed
|
||||
* Add -Q (quiet) flag was added. This suppresses output from drill.
|
||||
|
||||
1.0-pre2: 20 Jun 2005: drill-team
|
||||
* Second prerelease
|
||||
* Bugs where fix in the chasing functionality
|
||||
|
||||
1.0-pre1: 1 Jun 2005: drill-team
|
||||
* First drill release based on ldns
|
||||
* drill's core code is not much more simple, as
|
||||
all the difficult stuff is moved to ldns.
|
||||
* Much saner argument parsing
|
||||
|
||||
---------- Above Newer drill based on ldns --------------
|
||||
---------- Below Older drill with it's own DNS handling --------------
|
||||
|
||||
0.9.2: Feb 3 2005: drill-team
|
||||
* Added two more options (borrowed from dig)
|
||||
--rd, don't set the RD bit in queries
|
||||
--fail, don't query the next nameserver on SERVFAIL
|
||||
* Fixed handling of obscure data types
|
||||
* Handle classes other the 'IN' when making a query
|
||||
|
||||
* For people using FreeBSD: drill is now in the ports
|
||||
(Thanks to Jaap Akkerhuis)
|
||||
|
||||
0.9.1: Jan 5 2005: drill-team
|
||||
* Makefile tweaks
|
||||
* drill ns . works
|
||||
* re-check the root in when tracing
|
||||
* added handling for some lesser known types (including WKS)
|
||||
|
||||
0.9: Dec 6 2004: drill-team
|
||||
* big configure.ac and Makefile.in updates (made more general)
|
||||
* escapes in names argument and txt and dname data
|
||||
* gcc 2(.95) support
|
||||
* packet wire data is now checked for dangerous elements (like
|
||||
looping compression etc)
|
||||
* (Multiple) Octal char representation
|
||||
* Responses can be saved to file
|
||||
* 'Answers' can be read from file instead of server
|
||||
* Lots and lots of bugfixes and improvements
|
||||
|
||||
0.8.1: Oct 27 2004: Miek
|
||||
* configure.ac updates
|
||||
* secure resolving updates (still doesn't work)
|
||||
* printing additions
|
||||
- CERT RR supported
|
||||
- LOC RR support
|
||||
* All non supported RRs are handled as unknown
|
||||
* If no nameservers found in /etc/resolv.conf
|
||||
default to 127.0.0.1
|
||||
* Various bugs fixed
|
||||
- Close sockets after using them
|
||||
- Some memory leaks were plugged
|
||||
|
||||
0.8: Oct 26 2004: Miek
|
||||
* Lots of features added. Drill is almost feature complete
|
||||
* Unknown RR's are supported
|
||||
* Numerous smaller updates in documentation
|
||||
* Numerous code cleanups
|
||||
* Dig is no longer needed to build drill
|
||||
|
||||
0.7: Oct 21 2004: Miek
|
||||
* reworked internal code
|
||||
* DNSSEC is working, except the secure resolving
|
||||
* build updates
|
||||
* more sane options parsing
|
||||
* more sane argument handling
|
||||
|
||||
0.6-alpha: Oct 2004: Jelte
|
||||
* No log
|
||||
|
||||
0.5-alpha: Sept 22 2004: Miek
|
||||
* most of the DNS stuff is working
|
||||
* moved to configure
|
||||
* tested on Linux/FreeBSD
|
||||
* fully IPV6 capable
|
||||
* new DNSSEC types supported
|
||||
* DNSSEC somewhat working
|
||||
* gcc => 3 is needed for building
|
||||
|
||||
0.4-alpha: Sept 9 2004: Miek
|
||||
* moved to autoconf for building
|
||||
* lots of various updates
|
||||
* really a workable program now
|
||||
|
||||
0.3-alpha: Sept 6 2004: Miek
|
||||
* IPv6 support
|
||||
* automatic secure resolving
|
||||
* --trace updates
|
||||
* --chase updates
|
||||
* more checks
|
||||
12
zonemaster-ldns/ldns/drill/README
Normal file
12
zonemaster-ldns/ldns/drill/README
Normal file
@@ -0,0 +1,12 @@
|
||||
QUICK INSTALL GUIDE
|
||||
|
||||
drill is a subdirectory in ldns.
|
||||
|
||||
To compile drill you need:
|
||||
autoreconf && ./configure && make
|
||||
|
||||
If ldns is installed in a different location, use --with-ldns=directory
|
||||
See also ./configure --help
|
||||
|
||||
In the first case you must run drill as:
|
||||
LD_LIBRARY_PATH=../.libs ./drill <options>
|
||||
25
zonemaster-ldns/ldns/drill/REGRESSIONS
Normal file
25
zonemaster-ldns/ldns/drill/REGRESSIONS
Normal file
@@ -0,0 +1,25 @@
|
||||
REGRESSIONS
|
||||
|
||||
This version of drill is based on ldns and as such some things
|
||||
are slightly changed. This file documents the changes.
|
||||
|
||||
o When tracing (-T option) we use the local resolver (as specified
|
||||
in /etc/resolv.conf) to lookup names. This increases the speed
|
||||
dramatically, but you obviously need to be able to reach a recursive
|
||||
server/cache.
|
||||
Previously drill would try to resolve the names by itself.
|
||||
|
||||
o Printing of DSs after DNSKEY records. Because we don't parse our
|
||||
own packets anymore, we cannot print the DS directly after the DNSKEY
|
||||
record. The DSs are now printed AFTER the packet.
|
||||
|
||||
o The long options are removed.
|
||||
|
||||
o The chase function has a different output, and will be subject to change
|
||||
in the near future.
|
||||
|
||||
o The useless (for jokes only) -I option was dropped.
|
||||
|
||||
FIXED:
|
||||
o the argument parsing is much smarter, the order doesn't matter (much)
|
||||
anymore
|
||||
507
zonemaster-ldns/ldns/drill/chasetrace.c
Normal file
507
zonemaster-ldns/ldns/drill/chasetrace.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* chasetrace.c
|
||||
* Where all the hard work concerning chasing
|
||||
* and tracing is done
|
||||
* (c) 2005, 2006 NLnet Labs
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drill.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
/* Cache all RRs from rr_list "rr_list" to "referrals" database for lookup
|
||||
* later on. Print the NS RRs that were not already present.
|
||||
*/
|
||||
static void add_rr_list_to_referrals(
|
||||
ldns_dnssec_zone *referrals, ldns_rr_list *rr_list)
|
||||
{
|
||||
size_t i;
|
||||
ldns_rr *rr;
|
||||
ldns_dnssec_rrsets *rrset;
|
||||
ldns_dnssec_rrs *rrs;
|
||||
|
||||
for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
|
||||
rr = ldns_rr_list_rr(rr_list, i);
|
||||
/* Check if a RR equal to "rr" is present in "referrals" */
|
||||
rrset = ldns_dnssec_zone_find_rrset(
|
||||
referrals, ldns_rr_owner(rr), ldns_rr_get_type(rr));
|
||||
if (rrset) {
|
||||
for (rrs = rrset->rrs; rrs; rrs = rrs->next)
|
||||
if (ldns_rr_compare(rr, rrs->rr) == 0)
|
||||
break;
|
||||
if (rrs) continue; /* "rr" is present, next! */
|
||||
}
|
||||
if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS && verbosity != -1)
|
||||
ldns_rr_print(stdout, rr);
|
||||
(void) ldns_dnssec_zone_add_rr(referrals, rr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cache all RRs from packet "p" to "referrals" database for lookup later on.
|
||||
* Print the NS RRs that were not already present.
|
||||
*/
|
||||
static void add_referrals(ldns_dnssec_zone *referrals, ldns_pkt *p)
|
||||
{
|
||||
ldns_rr_list *l = ldns_pkt_all_noquestion(p);
|
||||
if (l) {
|
||||
add_rr_list_to_referrals(referrals, l);
|
||||
ldns_rr_list_free(l);
|
||||
}
|
||||
}
|
||||
|
||||
/* Equip name-server "res" with the name-servers authoritative for as much
|
||||
* of "name" as possible. Lookup addresses if needed.
|
||||
*/
|
||||
static bool set_nss_for_name(
|
||||
ldns_resolver *res, ldns_dnssec_zone *referrals, ldns_rdf *name,
|
||||
ldns_resolver *local_res, ldns_rr_class c)
|
||||
{
|
||||
ldns_dnssec_rrsets *nss = NULL;
|
||||
ldns_dnssec_rrs *nss_rrs;
|
||||
ldns_dnssec_rrsets *as = NULL;
|
||||
ldns_dnssec_rrs *as_rrs;
|
||||
ldns_rdf *lookup = ldns_rdf_clone(name);
|
||||
ldns_rdf *new_lookup;
|
||||
ldns_rdf *addr;
|
||||
ldns_rr_list *addrs;
|
||||
|
||||
/* nss will become the rrset of as much of "name" as possible */
|
||||
for (;;) {
|
||||
nss = ldns_dnssec_zone_find_rrset(
|
||||
referrals, lookup, LDNS_RR_TYPE_NS);
|
||||
if (nss != NULL) {
|
||||
ldns_rdf_deep_free(lookup);
|
||||
break;
|
||||
}
|
||||
new_lookup = ldns_dname_left_chop(lookup);
|
||||
ldns_rdf_deep_free(lookup);
|
||||
lookup = new_lookup;
|
||||
if (!lookup) {
|
||||
error("No referrals for name found");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* remove the old nameserver from the resolver */
|
||||
while ((addr = ldns_resolver_pop_nameserver(res)))
|
||||
ldns_rdf_deep_free(addr);
|
||||
|
||||
/* Find and add the address records for the rrset as name-servers */
|
||||
for (nss_rrs = nss->rrs; nss_rrs; nss_rrs = nss_rrs->next) {
|
||||
|
||||
if ((as = ldns_dnssec_zone_find_rrset(
|
||||
referrals, ldns_rr_rdf(nss_rrs->rr, 0), LDNS_RR_TYPE_A)))
|
||||
for (as_rrs = as->rrs; as_rrs; as_rrs = as_rrs->next)
|
||||
(void) ldns_resolver_push_nameserver(
|
||||
res, ldns_rr_rdf(as_rrs->rr, 0));
|
||||
|
||||
if ((as = ldns_dnssec_zone_find_rrset(
|
||||
referrals, ldns_rr_rdf(nss_rrs->rr, 0), LDNS_RR_TYPE_AAAA)))
|
||||
for (as_rrs = as->rrs; as_rrs; as_rrs = as_rrs->next)
|
||||
(void) ldns_resolver_push_nameserver(
|
||||
res, ldns_rr_rdf(as_rrs->rr, 0));
|
||||
}
|
||||
/* Is our resolver equipped with name-servers? Good! We're done */
|
||||
if (ldns_resolver_nameserver_count(res) > 0)
|
||||
return true;
|
||||
|
||||
/* Lookup addresses with local resolver add add to "referrals" database */
|
||||
addrs = ldns_rr_list_new();
|
||||
for (nss_rrs = nss->rrs; nss_rrs; nss_rrs = nss_rrs->next) {
|
||||
ldns_rr_list *addrs_by_name =
|
||||
ldns_get_rr_list_addr_by_name(
|
||||
local_res, ldns_rr_rdf(nss_rrs->rr, 0), c, 0);
|
||||
ldns_rr_list_cat(addrs, addrs_by_name);
|
||||
ldns_rr_list_free(addrs_by_name);
|
||||
}
|
||||
|
||||
if (ldns_rr_list_rr_count(addrs) == 0)
|
||||
error("Could not find the nameserver ip addr; abort");
|
||||
|
||||
else if (ldns_resolver_push_nameserver_rr_list(res, addrs) !=
|
||||
LDNS_STATUS_OK)
|
||||
|
||||
error("Error adding new nameservers");
|
||||
else {
|
||||
ldns_rr_list_deep_free(addrs);
|
||||
return true;
|
||||
}
|
||||
add_rr_list_to_referrals(referrals, addrs);
|
||||
ldns_rr_list_deep_free(addrs);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* trace down from the root to name
|
||||
*/
|
||||
|
||||
/* same naive method as in drill0.9
|
||||
* We resolve _ALL_ the names, which is of course not needed.
|
||||
* We _do_ use the local resolver to do that, so it still is
|
||||
* fast, but it can be made to run much faster.
|
||||
*/
|
||||
void
|
||||
do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
|
||||
ldns_rr_class c)
|
||||
{
|
||||
|
||||
static uint8_t zero[1] = { 0 };
|
||||
static const ldns_rdf root_dname = { 1, LDNS_RDF_TYPE_DNAME, &zero };
|
||||
|
||||
ldns_resolver *res = NULL;
|
||||
ldns_pkt *p = NULL;
|
||||
ldns_rr_list *final_answer;
|
||||
ldns_rr_list *new_nss;
|
||||
ldns_rr_list *cname = NULL;
|
||||
ldns_rr_list *answers = NULL;
|
||||
uint16_t loop_count;
|
||||
ldns_status status;
|
||||
ldns_dnssec_zone* referrals = NULL;
|
||||
ldns_rdf *addr;
|
||||
|
||||
loop_count = 0;
|
||||
final_answer = NULL;
|
||||
res = ldns_resolver_new();
|
||||
|
||||
if (!res) {
|
||||
error("Memory allocation failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* transfer some properties of local_res to res,
|
||||
* because they were given on the command line */
|
||||
ldns_resolver_set_ip6(res,
|
||||
ldns_resolver_ip6(local_res));
|
||||
ldns_resolver_set_port(res,
|
||||
ldns_resolver_port(local_res));
|
||||
ldns_resolver_set_debug(res,
|
||||
ldns_resolver_debug(local_res));
|
||||
ldns_resolver_set_dnssec(res,
|
||||
ldns_resolver_dnssec(local_res));
|
||||
ldns_resolver_set_fail(res,
|
||||
ldns_resolver_fail(local_res));
|
||||
ldns_resolver_set_usevc(res,
|
||||
ldns_resolver_usevc(local_res));
|
||||
ldns_resolver_set_random(res,
|
||||
ldns_resolver_random(local_res));
|
||||
ldns_resolver_set_source(res,
|
||||
ldns_resolver_source(local_res));
|
||||
ldns_resolver_set_recursive(res, false);
|
||||
|
||||
/* setup the root nameserver in the new resolver */
|
||||
status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root);
|
||||
if (status != LDNS_STATUS_OK) {
|
||||
fprintf(stderr, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status));
|
||||
ldns_rr_list_print(stdout, global_dns_root);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* this must be a real query to local_res */
|
||||
status = ldns_resolver_send(&p, res, &root_dname, LDNS_RR_TYPE_NS, c, 0);
|
||||
/* p can still be NULL */
|
||||
|
||||
if (ldns_pkt_empty(p)) {
|
||||
warning("No root server information received");
|
||||
}
|
||||
|
||||
if (status == LDNS_STATUS_OK) {
|
||||
if (!ldns_pkt_empty(p)) {
|
||||
drill_pkt_print(stdout, local_res, p);
|
||||
}
|
||||
referrals = ldns_dnssec_zone_new();
|
||||
add_referrals(referrals, p);
|
||||
} else {
|
||||
error("cannot use local resolver");
|
||||
goto cleanup;
|
||||
}
|
||||
if (! set_nss_for_name(res, referrals, name, local_res, c)) {
|
||||
goto cleanup;
|
||||
}
|
||||
ldns_pkt_free(p);
|
||||
p = NULL;
|
||||
status = ldns_resolver_send(&p, res, name, t, c, 0);
|
||||
while(status == LDNS_STATUS_OK &&
|
||||
ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) {
|
||||
|
||||
if (!p) {
|
||||
/* some error occurred -- bail out */
|
||||
goto cleanup;
|
||||
}
|
||||
add_referrals(referrals, p);
|
||||
|
||||
/* checks itself for verbosity */
|
||||
drill_pkt_print_footer(stdout, local_res, p);
|
||||
|
||||
if (! set_nss_for_name(res, referrals, name, local_res, c)) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (loop_count++ > 20) {
|
||||
/* unlikely that we are doing anything useful */
|
||||
error("Looks like we are looping");
|
||||
goto cleanup;
|
||||
}
|
||||
ldns_pkt_free(p);
|
||||
p = NULL;
|
||||
status = ldns_resolver_send(&p, res, name, t, c, 0);
|
||||
|
||||
/* Exit trace on error */
|
||||
if (status != LDNS_STATUS_OK)
|
||||
break;
|
||||
|
||||
/* An answer might be the desired answer (and no referral) */
|
||||
if (ldns_pkt_reply_type(p) != LDNS_PACKET_ANSWER)
|
||||
continue;
|
||||
|
||||
/* Exit trace when the requested type is found */
|
||||
answers = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANSWER);
|
||||
if (answers && ldns_rr_list_rr_count(answers) > 0) {
|
||||
ldns_rr_list_free(answers);
|
||||
answers = NULL;
|
||||
break;
|
||||
}
|
||||
ldns_rr_list_free(answers);
|
||||
answers = NULL;
|
||||
|
||||
/* Get the CNAMEs from the answer */
|
||||
cname = ldns_pkt_rr_list_by_type(
|
||||
p, LDNS_RR_TYPE_CNAME, LDNS_SECTION_ANSWER);
|
||||
|
||||
/* No CNAME either: exit trace */
|
||||
if (ldns_rr_list_rr_count(cname) == 0)
|
||||
break;
|
||||
|
||||
/* Print CNAME referral */
|
||||
ldns_rr_list_print(stdout, cname);
|
||||
|
||||
/* restart with the CNAME */
|
||||
name = ldns_rr_rdf(ldns_rr_list_rr(cname, 0), 0);
|
||||
ldns_rr_list_free(cname);
|
||||
cname = NULL;
|
||||
|
||||
/* remove the old nameserver from the resolver */
|
||||
while((addr = ldns_resolver_pop_nameserver(res)))
|
||||
ldns_rdf_deep_free(addr);
|
||||
|
||||
/* Restart trace from the root up */
|
||||
(void) ldns_resolver_push_nameserver_rr_list(
|
||||
res, global_dns_root);
|
||||
|
||||
ldns_pkt_free(p);
|
||||
p = NULL;
|
||||
status = ldns_resolver_send(&p, res, name, t, c, 0);
|
||||
}
|
||||
|
||||
ldns_pkt_free(p);
|
||||
p = NULL;
|
||||
(void) ldns_resolver_send(&p, res, name, t, c, 0);
|
||||
if (!p) {
|
||||
goto cleanup;
|
||||
}
|
||||
new_nss = ldns_pkt_authority(p);
|
||||
final_answer = ldns_pkt_answer(p);
|
||||
|
||||
if (verbosity != -1) {
|
||||
ldns_rr_list_print(stdout, final_answer);
|
||||
ldns_rr_list_print(stdout, new_nss);
|
||||
|
||||
}
|
||||
drill_pkt_print_footer(stdout, local_res, p);
|
||||
cleanup:
|
||||
if (res) {
|
||||
while((addr = ldns_resolver_pop_nameserver(res)))
|
||||
ldns_rdf_deep_free(addr);
|
||||
ldns_resolver_free(res);
|
||||
}
|
||||
if (referrals)
|
||||
ldns_dnssec_zone_deep_free(referrals);
|
||||
if (p)
|
||||
ldns_pkt_free(p);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Chase the given rr to a known and trusted key
|
||||
*
|
||||
* Based on drill 0.9
|
||||
*
|
||||
* the last argument prev_key_list, if not null, and type == DS, then the ds
|
||||
* rr list we have must all be a ds for the keys in this list
|
||||
*/
|
||||
#ifdef HAVE_SSL
|
||||
ldns_status
|
||||
do_chase(ldns_resolver *res,
|
||||
ldns_rdf *name,
|
||||
ldns_rr_type type,
|
||||
ldns_rr_class c,
|
||||
ldns_rr_list *trusted_keys,
|
||||
ldns_pkt *pkt_o,
|
||||
uint16_t qflags,
|
||||
ldns_rr_list * ATTR_UNUSED(prev_key_list))
|
||||
{
|
||||
ldns_rr_list *rrset = NULL;
|
||||
ldns_status result;
|
||||
ldns_rr *orig_rr = NULL;
|
||||
|
||||
/*
|
||||
ldns_rr_list *sigs;
|
||||
ldns_rr *cur_sig;
|
||||
uint16_t sig_i;
|
||||
ldns_rr_list *keys;
|
||||
*/
|
||||
ldns_pkt *pkt;
|
||||
ldns_status tree_result;
|
||||
ldns_dnssec_data_chain *chain;
|
||||
ldns_dnssec_trust_tree *tree;
|
||||
|
||||
const ldns_rr_descriptor *descriptor;
|
||||
descriptor = ldns_rr_descript(type);
|
||||
|
||||
ldns_dname2canonical(name);
|
||||
|
||||
pkt = ldns_pkt_clone(pkt_o);
|
||||
if (!name) {
|
||||
mesg("No name to chase");
|
||||
ldns_pkt_free(pkt);
|
||||
return LDNS_STATUS_EMPTY_LABEL;
|
||||
}
|
||||
if (verbosity != -1) {
|
||||
printf(";; Chasing: ");
|
||||
ldns_rdf_print(stdout, name);
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf(" %s\n", descriptor->_name);
|
||||
} else {
|
||||
printf(" type %d\n", type);
|
||||
}
|
||||
}
|
||||
|
||||
if (!trusted_keys || ldns_rr_list_rr_count(trusted_keys) < 1) {
|
||||
warning("No trusted keys specified");
|
||||
}
|
||||
|
||||
if (pkt) {
|
||||
rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
|
||||
name,
|
||||
type,
|
||||
LDNS_SECTION_ANSWER
|
||||
);
|
||||
if (!rrset) {
|
||||
/* nothing in answer, try authority */
|
||||
rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
|
||||
name,
|
||||
type,
|
||||
LDNS_SECTION_AUTHORITY
|
||||
);
|
||||
}
|
||||
/* answer might be a cname, chase that first, then chase
|
||||
cname target? (TODO) */
|
||||
if (!rrset) {
|
||||
rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
|
||||
name,
|
||||
LDNS_RR_TYPE_CNAME,
|
||||
LDNS_SECTION_ANSWER
|
||||
);
|
||||
if (!rrset) {
|
||||
/* nothing in answer, try authority */
|
||||
rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
|
||||
name,
|
||||
LDNS_RR_TYPE_CNAME,
|
||||
LDNS_SECTION_AUTHORITY
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* no packet? */
|
||||
if (verbosity >= 0) {
|
||||
fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR));
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
return LDNS_STATUS_MEM_ERR;
|
||||
}
|
||||
|
||||
if (!rrset) {
|
||||
/* not found in original packet, try again */
|
||||
ldns_pkt_free(pkt);
|
||||
pkt = NULL;
|
||||
pkt = ldns_resolver_query(res, name, type, c, qflags);
|
||||
|
||||
if (!pkt) {
|
||||
if (verbosity >= 0) {
|
||||
fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_NETWORK_ERR));
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
return LDNS_STATUS_NETWORK_ERR;
|
||||
}
|
||||
if (verbosity >= 5) {
|
||||
ldns_pkt_print(stdout, pkt);
|
||||
}
|
||||
|
||||
rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
|
||||
name,
|
||||
type,
|
||||
LDNS_SECTION_ANSWER
|
||||
);
|
||||
}
|
||||
|
||||
orig_rr = ldns_rr_new();
|
||||
|
||||
/* if the answer had no answer section, we need to construct our own rr (for instance if
|
||||
* the rr qe asked for doesn't exist. This rr will be destroyed when the chain is freed */
|
||||
if (ldns_pkt_ancount(pkt) < 1) {
|
||||
ldns_rr_set_type(orig_rr, type);
|
||||
ldns_rr_set_owner(orig_rr, ldns_rdf_clone(name));
|
||||
|
||||
chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, ldns_rr_clone(orig_rr));
|
||||
} else {
|
||||
/* chase the first answer */
|
||||
chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, NULL);
|
||||
}
|
||||
|
||||
if (verbosity >= 4) {
|
||||
printf("\n\nDNSSEC Data Chain:\n");
|
||||
ldns_dnssec_data_chain_print(stdout, chain);
|
||||
}
|
||||
|
||||
result = LDNS_STATUS_OK;
|
||||
|
||||
tree = ldns_dnssec_derive_trust_tree(chain, NULL);
|
||||
|
||||
if (verbosity >= 2) {
|
||||
printf("\n\nDNSSEC Trust tree:\n");
|
||||
ldns_dnssec_trust_tree_print(stdout, tree, 0, true);
|
||||
}
|
||||
|
||||
if (ldns_rr_list_rr_count(trusted_keys) > 0) {
|
||||
tree_result = ldns_dnssec_trust_tree_contains_keys(tree, trusted_keys);
|
||||
|
||||
if (tree_result == LDNS_STATUS_DNSSEC_EXISTENCE_DENIED) {
|
||||
if (verbosity >= 1) {
|
||||
printf("Existence denied or verifiably insecure\n");
|
||||
}
|
||||
result = LDNS_STATUS_OK;
|
||||
} else if (tree_result != LDNS_STATUS_OK) {
|
||||
if (verbosity >= 1) {
|
||||
printf("No trusted keys found in tree: first error was: %s\n", ldns_get_errorstr_by_id(tree_result));
|
||||
}
|
||||
result = tree_result;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (verbosity >= 0) {
|
||||
printf("You have not provided any trusted keys.\n");
|
||||
}
|
||||
}
|
||||
|
||||
ldns_rr_free(orig_rr);
|
||||
ldns_dnssec_trust_tree_free(tree);
|
||||
ldns_dnssec_data_chain_deep_free(chain);
|
||||
|
||||
ldns_rr_list_deep_free(rrset);
|
||||
ldns_pkt_free(pkt);
|
||||
/* ldns_rr_free(orig_rr);*/
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
534
zonemaster-ldns/ldns/drill/dnssec.c
Normal file
534
zonemaster-ldns/ldns/drill/dnssec.c
Normal file
@@ -0,0 +1,534 @@
|
||||
/*
|
||||
* dnssec.c
|
||||
* Some DNSSEC helper function are defined here
|
||||
* and tracing is done
|
||||
* (c) 2005 NLnet Labs
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drill.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
/* get rr_type from a server from a server */
|
||||
ldns_rr_list *
|
||||
get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c)
|
||||
{
|
||||
/* query, retrieve, extract and return */
|
||||
ldns_pkt *p;
|
||||
ldns_rr_list *found;
|
||||
|
||||
p = ldns_pkt_new();
|
||||
found = NULL;
|
||||
|
||||
if (ldns_resolver_send(&p, res, zname, t, c, 0) == LDNS_STATUS_OK) {
|
||||
found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION);
|
||||
}
|
||||
ldns_pkt_free(p);
|
||||
return found;
|
||||
}
|
||||
|
||||
void
|
||||
drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
|
||||
{
|
||||
ldns_rr_list *new_nss;
|
||||
ldns_rr_list *hostnames;
|
||||
char *answerfrom_str;
|
||||
|
||||
if (verbosity < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
|
||||
|
||||
new_nss = ldns_pkt_rr_list_by_type(p,
|
||||
LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
|
||||
ldns_rr_list_print(fd, new_nss);
|
||||
ldns_rr_list_deep_free(new_nss);
|
||||
|
||||
fprintf(fd, ";; Received %d bytes from %s#%d(",
|
||||
(int) ldns_pkt_size(p),
|
||||
ldns_rdf2str(ldns_pkt_answerfrom(p)),
|
||||
(int) ldns_resolver_port(r));
|
||||
/* if we can resolve this print it, other print the ip again */
|
||||
if (hostnames) {
|
||||
ldns_rdf_print(fd,
|
||||
ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
|
||||
ldns_rr_list_deep_free(hostnames);
|
||||
} else {
|
||||
answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
|
||||
if (answerfrom_str) {
|
||||
fprintf(fd, "%s", answerfrom_str);
|
||||
LDNS_FREE(answerfrom_str);
|
||||
}
|
||||
}
|
||||
fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
|
||||
}
|
||||
|
||||
void
|
||||
drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
|
||||
{
|
||||
ldns_rr_list *hostnames;
|
||||
char *answerfrom_str;
|
||||
|
||||
if (verbosity < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
|
||||
|
||||
fprintf(fd, ";; Received %d bytes from %s#%d(",
|
||||
(int) ldns_pkt_size(p),
|
||||
ldns_rdf2str(ldns_pkt_answerfrom(p)),
|
||||
(int) ldns_resolver_port(r));
|
||||
/* if we can resolve this print it, other print the ip again */
|
||||
if (hostnames) {
|
||||
ldns_rdf_print(fd,
|
||||
ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
|
||||
ldns_rr_list_deep_free(hostnames);
|
||||
} else {
|
||||
answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
|
||||
if (answerfrom_str) {
|
||||
fprintf(fd, "%s", answerfrom_str);
|
||||
LDNS_FREE(answerfrom_str);
|
||||
}
|
||||
}
|
||||
fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
|
||||
}
|
||||
/*
|
||||
* generic function to get some RRset from a nameserver
|
||||
* and possible some signatures too (that would be the day...)
|
||||
*/
|
||||
ldns_pkt_type
|
||||
get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t,
|
||||
ldns_rr_list **rrlist, ldns_rr_list **sig)
|
||||
{
|
||||
ldns_pkt_type pt = LDNS_PACKET_UNKNOWN;
|
||||
ldns_rr_list *sigs = NULL;
|
||||
size_t i;
|
||||
|
||||
if (!p) {
|
||||
if (rrlist) {
|
||||
*rrlist = NULL;
|
||||
}
|
||||
return LDNS_PACKET_UNKNOWN;
|
||||
}
|
||||
|
||||
pt = ldns_pkt_reply_type(p);
|
||||
if (name) {
|
||||
if (rrlist) {
|
||||
*rrlist = ldns_pkt_rr_list_by_name_and_type(p, name, t,
|
||||
LDNS_SECTION_ANSWER);
|
||||
if (!*rrlist) {
|
||||
*rrlist = ldns_pkt_rr_list_by_name_and_type(
|
||||
p, name, t,
|
||||
LDNS_SECTION_AUTHORITY);
|
||||
}
|
||||
}
|
||||
if (sig) {
|
||||
sigs = ldns_pkt_rr_list_by_name_and_type(p, name,
|
||||
LDNS_RR_TYPE_RRSIG,
|
||||
LDNS_SECTION_ANSWER);
|
||||
if (!sigs) {
|
||||
sigs = ldns_pkt_rr_list_by_name_and_type(
|
||||
p, name, LDNS_RR_TYPE_RRSIG,
|
||||
LDNS_SECTION_AUTHORITY);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* A DS-referral - get the DS records if they are there */
|
||||
if (rrlist) {
|
||||
*rrlist = ldns_pkt_rr_list_by_type(
|
||||
p, t, LDNS_SECTION_AUTHORITY);
|
||||
}
|
||||
if (sig) {
|
||||
sigs = ldns_pkt_rr_list_by_type(p,
|
||||
LDNS_RR_TYPE_RRSIG,
|
||||
LDNS_SECTION_AUTHORITY);
|
||||
}
|
||||
}
|
||||
if (sig) {
|
||||
*sig = ldns_rr_list_new();
|
||||
for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) {
|
||||
/* only add the sigs that cover this type */
|
||||
if (t == ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(
|
||||
ldns_rr_list_rr(sigs, i)))) {
|
||||
|
||||
ldns_rr_list_push_rr(*sig,
|
||||
ldns_rr_clone(
|
||||
ldns_rr_list_rr(
|
||||
sigs, i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
ldns_rr_list_deep_free(sigs);
|
||||
|
||||
if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) {
|
||||
return pt;
|
||||
} else {
|
||||
return LDNS_PACKET_ANSWER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ldns_status
|
||||
ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
uint16_t nsec_i;
|
||||
|
||||
ldns_rr_list *nsecs;
|
||||
ldns_status result;
|
||||
const ldns_rr_descriptor *descriptor;
|
||||
|
||||
if (!pkt) {
|
||||
descriptor = ldns_rr_descript(type);
|
||||
|
||||
printf("NETWORk ERROR! Cannot verify denial for: ");
|
||||
ldns_rdf_print(stdout, name);
|
||||
printf(" type ");
|
||||
if (descriptor && descriptor->_name)
|
||||
printf("%s", descriptor->_name);
|
||||
else
|
||||
printf("TYPE%u", type);
|
||||
return LDNS_STATUS_CRYPTO_NO_RRSIG;
|
||||
}
|
||||
if (verbosity >= 5) {
|
||||
printf("VERIFY DENIAL FROM:\n");
|
||||
ldns_pkt_print(stdout, pkt);
|
||||
}
|
||||
|
||||
result = LDNS_STATUS_CRYPTO_NO_RRSIG;
|
||||
/* Try to see if there are NSECS in the packet */
|
||||
nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION);
|
||||
if (nsecs) {
|
||||
for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) {
|
||||
/* there are four options:
|
||||
* - name equals ownername and is covered by the type bitmap
|
||||
* - name equals ownername but is not covered by the type bitmap
|
||||
* - name falls within nsec coverage but is not equal to the owner name
|
||||
* - name falls outside of nsec coverage
|
||||
*/
|
||||
if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) {
|
||||
/*
|
||||
printf("CHECKING NSEC:\n");
|
||||
ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i));
|
||||
printf("DAWASEM\n");
|
||||
*/
|
||||
if (ldns_nsec_bitmap_covers_type(
|
||||
ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs,
|
||||
nsec_i)),
|
||||
type)) {
|
||||
/* Error, according to the nsec this rrset is signed */
|
||||
result = LDNS_STATUS_CRYPTO_NO_RRSIG;
|
||||
} else {
|
||||
/* ok nsec denies existence */
|
||||
if (verbosity >= 3) {
|
||||
printf(";; Existence of data set with this type denied by NSEC\n");
|
||||
}
|
||||
/*printf(";; Verifiably insecure.\n");*/
|
||||
if (nsec_rrs && nsec_rr_sigs) {
|
||||
(void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
|
||||
}
|
||||
ldns_rr_list_deep_free(nsecs);
|
||||
return LDNS_STATUS_OK;
|
||||
}
|
||||
} else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) {
|
||||
if (verbosity >= 3) {
|
||||
printf(";; Existence of data set with this name denied by NSEC\n");
|
||||
}
|
||||
if (nsec_rrs && nsec_rr_sigs) {
|
||||
(void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
|
||||
}
|
||||
ldns_rr_list_deep_free(nsecs);
|
||||
return LDNS_STATUS_OK;
|
||||
} else {
|
||||
/* nsec has nothing to do with this data */
|
||||
}
|
||||
}
|
||||
ldns_rr_list_deep_free(nsecs);
|
||||
} else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) {
|
||||
ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION);
|
||||
ldns_rr* q = ldns_rr_new();
|
||||
ldns_rr* match = NULL;
|
||||
|
||||
if(!sigs) {
|
||||
if (q) {
|
||||
ldns_rr_free(q);
|
||||
}
|
||||
ldns_rr_list_deep_free(nsecs);
|
||||
return LDNS_STATUS_MEM_ERR;
|
||||
}
|
||||
if(!q) {
|
||||
ldns_rr_list_deep_free(nsecs);
|
||||
ldns_rr_list_deep_free(sigs);
|
||||
return LDNS_STATUS_MEM_ERR;
|
||||
}
|
||||
ldns_rr_set_question(q, 1);
|
||||
ldns_rr_set_ttl(q, 0);
|
||||
ldns_rr_set_owner(q, ldns_rdf_clone(name));
|
||||
if(!ldns_rr_owner(q)) {
|
||||
ldns_rr_free(q);
|
||||
ldns_rr_list_deep_free(sigs);
|
||||
ldns_rr_list_deep_free(nsecs);
|
||||
return LDNS_STATUS_MEM_ERR;
|
||||
}
|
||||
ldns_rr_set_type(q, type);
|
||||
|
||||
/* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */
|
||||
result = ldns_dnssec_verify_denial_nsec3_match(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0, &match);
|
||||
if (result == LDNS_STATUS_OK && match && nsec_rrs && nsec_rr_sigs) {
|
||||
(void) get_dnssec_rr(pkt, ldns_rr_owner(match), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs);
|
||||
}
|
||||
ldns_rr_free(q);
|
||||
ldns_rr_list_deep_free(nsecs);
|
||||
ldns_rr_list_deep_free(sigs);
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
(void)pkt;
|
||||
(void)name;
|
||||
(void)type;
|
||||
(void)nsec_rrs;
|
||||
(void)nsec_rr_sigs;
|
||||
return LDNS_STATUS_ERR;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
|
||||
/* NSEC3 draft -07 */
|
||||
/*return hash name match*/
|
||||
ldns_rr *
|
||||
ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) {
|
||||
uint8_t algorithm;
|
||||
uint32_t iterations;
|
||||
uint8_t salt_length;
|
||||
uint8_t *salt;
|
||||
|
||||
ldns_rdf *sname = NULL, *hashed_sname = NULL;
|
||||
|
||||
size_t nsec_i;
|
||||
ldns_rr *nsec;
|
||||
ldns_rr *result = NULL;
|
||||
|
||||
const ldns_rr_descriptor *descriptor;
|
||||
|
||||
ldns_rdf *zone_name = NULL;
|
||||
|
||||
if (verbosity >= 4) {
|
||||
printf(";; finding exact match for ");
|
||||
descriptor = ldns_rr_descript(qtype);
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf("%s ", descriptor->_name);
|
||||
} else {
|
||||
printf("TYPE%d ", qtype);
|
||||
}
|
||||
ldns_rdf_print(stdout, qname);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
|
||||
if (verbosity >= 4) {
|
||||
printf("no qname, nsec3s or list empty\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsec = ldns_rr_list_rr(nsec3s, 0);
|
||||
algorithm = ldns_nsec3_algorithm(nsec);
|
||||
salt_length = ldns_nsec3_salt_length(nsec);
|
||||
salt = ldns_nsec3_salt_data(nsec);
|
||||
iterations = ldns_nsec3_iterations(nsec);
|
||||
if (salt == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
sname = ldns_rdf_clone(qname);
|
||||
if (sname == NULL) {
|
||||
goto done;
|
||||
}
|
||||
if (verbosity >= 4) {
|
||||
printf(";; owner name hashes to: ");
|
||||
}
|
||||
hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
|
||||
if (hashed_sname == NULL) {
|
||||
goto done;
|
||||
}
|
||||
zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
|
||||
if (zone_name == NULL) {
|
||||
goto done;
|
||||
}
|
||||
if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK) {
|
||||
goto done;
|
||||
};
|
||||
|
||||
if (verbosity >= 4) {
|
||||
ldns_rdf_print(stdout, hashed_sname);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
|
||||
nsec = ldns_rr_list_rr(nsec3s, nsec_i);
|
||||
|
||||
/* check values of iterations etc! */
|
||||
|
||||
/* exact match? */
|
||||
if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
|
||||
result = nsec;
|
||||
goto done;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
done:
|
||||
ldns_rdf_deep_free(zone_name);
|
||||
ldns_rdf_deep_free(sname);
|
||||
ldns_rdf_deep_free(hashed_sname);
|
||||
LDNS_FREE(salt);
|
||||
|
||||
if (verbosity >= 4) {
|
||||
if (result) {
|
||||
printf(";; Found.\n");
|
||||
} else {
|
||||
printf(";; Not foud.\n");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*return the owner name of the closest encloser for name from the list of rrs */
|
||||
/* this is NOT the hash, but the original name! */
|
||||
ldns_rdf *
|
||||
ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s)
|
||||
{
|
||||
/* remember parameters, they must match */
|
||||
uint8_t algorithm;
|
||||
uint32_t iterations;
|
||||
uint8_t salt_length;
|
||||
uint8_t *salt;
|
||||
|
||||
ldns_rdf *sname = NULL, *hashed_sname = NULL, *tmp;
|
||||
bool flag;
|
||||
|
||||
bool exact_match_found;
|
||||
bool in_range_found;
|
||||
|
||||
ldns_rdf *zone_name = NULL;
|
||||
|
||||
size_t nsec_i;
|
||||
ldns_rr *nsec;
|
||||
ldns_rdf *result = NULL;
|
||||
|
||||
if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (verbosity >= 4) {
|
||||
printf(";; finding closest encloser for type %d ", qtype);
|
||||
ldns_rdf_print(stdout, qname);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
nsec = ldns_rr_list_rr(nsec3s, 0);
|
||||
algorithm = ldns_nsec3_algorithm(nsec);
|
||||
salt_length = ldns_nsec3_salt_length(nsec);
|
||||
salt = ldns_nsec3_salt_data(nsec);
|
||||
iterations = ldns_nsec3_iterations(nsec);
|
||||
if (salt == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
sname = ldns_rdf_clone(qname);
|
||||
if (sname == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
flag = false;
|
||||
|
||||
zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
|
||||
if (zone_name == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* algorithm from nsec3-07 8.3 */
|
||||
while (ldns_dname_label_count(sname) > 0) {
|
||||
exact_match_found = false;
|
||||
in_range_found = false;
|
||||
|
||||
if (verbosity >= 3) {
|
||||
printf(";; ");
|
||||
ldns_rdf_print(stdout, sname);
|
||||
printf(" hashes to: ");
|
||||
}
|
||||
hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
|
||||
if (hashed_sname == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK){
|
||||
ldns_rdf_deep_free(hashed_sname);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (verbosity >= 3) {
|
||||
ldns_rdf_print(stdout, hashed_sname);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
|
||||
nsec = ldns_rr_list_rr(nsec3s, nsec_i);
|
||||
|
||||
/* check values of iterations etc! */
|
||||
|
||||
/* exact match? */
|
||||
if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
|
||||
if (verbosity >= 4) {
|
||||
printf(";; exact match found\n");
|
||||
}
|
||||
exact_match_found = true;
|
||||
} else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
|
||||
if (verbosity >= 4) {
|
||||
printf(";; in range of an nsec\n");
|
||||
}
|
||||
in_range_found = true;
|
||||
}
|
||||
|
||||
}
|
||||
if (!exact_match_found && in_range_found) {
|
||||
flag = true;
|
||||
} else if (exact_match_found && flag) {
|
||||
result = ldns_rdf_clone(sname);
|
||||
} else if (exact_match_found && !flag) {
|
||||
// error!
|
||||
if (verbosity >= 4) {
|
||||
printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n");
|
||||
}
|
||||
ldns_rdf_deep_free(hashed_sname);
|
||||
goto done;
|
||||
} else {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
ldns_rdf_deep_free(hashed_sname);
|
||||
tmp = sname;
|
||||
sname = ldns_dname_left_chop(sname);
|
||||
ldns_rdf_deep_free(tmp);
|
||||
if (sname == NULL) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
LDNS_FREE(salt);
|
||||
ldns_rdf_deep_free(zone_name);
|
||||
ldns_rdf_deep_free(sname);
|
||||
|
||||
if (!result) {
|
||||
if (verbosity >= 4) {
|
||||
printf(";; no closest encloser found\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* todo checks from end of 6.2. here or in caller? */
|
||||
return result;
|
||||
}
|
||||
262
zonemaster-ldns/ldns/drill/drill.1.in
Normal file
262
zonemaster-ldns/ldns/drill/drill.1.in
Normal file
@@ -0,0 +1,262 @@
|
||||
.\" @(#)drill.1 1.7.0 14-Jul-2004 OF;
|
||||
.TH drill 1 "28 May 2006"
|
||||
.SH NAME
|
||||
drill \- get (debug) information out of DNS(SEC)
|
||||
.SH SYNOPSIS
|
||||
.B drill
|
||||
[
|
||||
.IR OPTIONS
|
||||
]
|
||||
.IR name
|
||||
[
|
||||
.IR @server
|
||||
]
|
||||
[
|
||||
.IR type
|
||||
]
|
||||
[
|
||||
.IR class
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBdrill\fR is a tool designed to get all sorts of information out of the
|
||||
DNS. It is specifically designed to be used with DNSSEC.
|
||||
.PP
|
||||
The name \fBdrill\fR is a pun on \fBdig\fR. With \fBdrill\fR you should be able
|
||||
get even more information than with \fBdig\fR.
|
||||
.PP
|
||||
If no arguments are given class defaults to 'IN' and type to 'A'. The
|
||||
server(s) specified in /etc/resolv.conf are used to query against.
|
||||
|
||||
.PP
|
||||
\fIname\fR
|
||||
Ask for this name.
|
||||
|
||||
.PP
|
||||
\fI@server\fR
|
||||
Send to query to this server. If not specified use the nameservers from
|
||||
\fI/etc/resolv.conf\fR.
|
||||
|
||||
.PP
|
||||
\fItype\fR
|
||||
Ask for this RR type. If type is not given on the command line it defaults
|
||||
to 'A'. Except when doing a reverse lookup when it defaults to 'PTR'.
|
||||
|
||||
.PP
|
||||
\fIclass\fR
|
||||
Use this class when querying.
|
||||
|
||||
.SH SAMPLE USAGE
|
||||
\fBdrill mx miek.nl\fR
|
||||
Show the MX records of the domain miek.nl
|
||||
|
||||
.TP
|
||||
\fBdrill \-S jelte.nlnetlabs.nl\fR
|
||||
Chase any signatures in the jelte.nlnetlab.nl domain. This option is
|
||||
only available when ldns has been compiled with openssl-support.
|
||||
|
||||
.TP
|
||||
\fBdrill \-TD www.example.com\fR
|
||||
Do a DNSSEC (\-D) trace (\-T) from the rootservers down to www.example.com.
|
||||
This option only works when ldns has been compiled with openssl support.
|
||||
|
||||
.TP
|
||||
\fBdrill \-s dnskey jelte.nlnetlabs.nl\fR
|
||||
Show the DNSKEY record(s) for jelte.nlnetlabs.nl. For each found DNSKEY
|
||||
record also print the DS record.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.TP
|
||||
\fB\-D
|
||||
Enable DNSSEC in the query. When querying for DNSSEC types (DNSKEY, RRSIG,
|
||||
DS and NSEC) this is \fInot\fR automatically enabled.
|
||||
|
||||
.TP
|
||||
\fB\-T
|
||||
Trace \fIname\fR from the root down. When using this option the @server
|
||||
arguments is not used.
|
||||
|
||||
.TP
|
||||
\fB\-S
|
||||
Chase the signature(s) of 'name' to a known key or as high up in
|
||||
the tree as possible.
|
||||
|
||||
.TP
|
||||
\fB\-I \fIIPv4 or IPv6 address\fR
|
||||
Source address to query from. The source address has to be present
|
||||
on an interface of the host running drill.
|
||||
|
||||
.TP
|
||||
\fB\-V \fIlevel\fR
|
||||
Be more verbose. Set level to 5 to see the actual query that is sent.
|
||||
|
||||
.TP
|
||||
\fB\-Q
|
||||
Quiet mode, this overrules \-V.
|
||||
|
||||
.TP
|
||||
\fB\-f \fIfile\fR
|
||||
Read the query from a file. The query must be dumped with \-w.
|
||||
|
||||
.TP
|
||||
\fB\-i \fIfile\fR
|
||||
read the answer from the file instead from the network. This aids
|
||||
in debugging and can be used to check if a query on disk is valid.
|
||||
If the file contains binary data it is assumed to be a query in
|
||||
network order.
|
||||
|
||||
.TP
|
||||
\fB\-w \fIfile\fR
|
||||
Write an answer packet to file.
|
||||
|
||||
.TP
|
||||
\fB\-q \fIfile\fR
|
||||
Write the query packet to file.
|
||||
|
||||
.TP
|
||||
\fB\-v
|
||||
Show drill's version.
|
||||
|
||||
.TP
|
||||
\fB\-h
|
||||
Show a short help message.
|
||||
|
||||
.SS QUERY OPTIONS
|
||||
|
||||
.TP
|
||||
\fB\-4
|
||||
Stay on ip4. Only send queries to ip4 enabled nameservers.
|
||||
|
||||
.TP
|
||||
\fB\-6
|
||||
Stay on ip6. Only send queries to ip6 enabled nameservers.
|
||||
|
||||
.TP
|
||||
\fB\-a
|
||||
Use the resolver structure's fallback mechanism if the answer
|
||||
is truncated (TC=1). If a truncated packet is received and this
|
||||
option is set, drill will first send a new query with EDNS0
|
||||
buffer size 4096.
|
||||
|
||||
If the EDNS0 buffer size was already set to 512+ bytes, or the
|
||||
above retry also results in a truncated answer, the resolver
|
||||
structure will fall back to TCP.
|
||||
|
||||
.TP
|
||||
\fB\-b \fIsize\fR
|
||||
Use size as the buffer size in the EDNS0 pseudo RR.
|
||||
|
||||
.TP
|
||||
\fB\-c \fIfile\fR
|
||||
Use file instead of /etc/resolv.conf for nameserver configuration.
|
||||
|
||||
.TP
|
||||
\fB\-d \fIdomain\fR
|
||||
When tracing (\-T), start from this domain instead of the root.
|
||||
|
||||
.TP
|
||||
\fB\-t
|
||||
Use TCP/IP when querying a server
|
||||
|
||||
.TP
|
||||
\fB\-k \fIkeyfile\fR
|
||||
Use this file to read a (trusted) key from. When this options is
|
||||
given \fBdrill\fR tries to validate the current answer with this
|
||||
key. No chasing is done. When \fBdrill\fR is doing a secure trace, this
|
||||
key will be used as trust anchor. Can contain a DNSKEY or a DS record.
|
||||
|
||||
Alternatively, when DNSSEC enabled tracing (\fB-TD\fR) or signature
|
||||
chasing (\fB-S\fR), if \fB-k\fR is not specified, and a default trust anchor
|
||||
(@LDNS_TRUST_ANCHOR_FILE@) exists and contains a valid DNSKEY or DS record,
|
||||
it will be used as the trust anchor.
|
||||
|
||||
.TP
|
||||
\fB\-o \fImnemonic\fR
|
||||
Use this option to set or unset specific header bits. A bit is
|
||||
set by using the bit mnemonic in CAPITAL letters. A bit is unset when
|
||||
the mnemonic is given in lowercase. The following mnemonics are
|
||||
understood by \fBdrill\fR:
|
||||
|
||||
QR, qr: set, unset QueRy (default: on)
|
||||
AA, aa: set, unset Authoritative Answer (default: off)
|
||||
TC, tc: set, unset TrunCated (default: off)
|
||||
RD, rd: set, unset Recursion Desired (default: on)
|
||||
CD, cd: set, unset Checking Disabled (default: off)
|
||||
RA, ra: set, unset Recursion Available (default: off)
|
||||
AD, ad: set, unset Authenticated Data (default: off)
|
||||
|
||||
Thus: \fB-o CD\fR, will enable Checking Disabled, which instructs the
|
||||
cache to not validate the answers it gives out.
|
||||
|
||||
.TP
|
||||
\fB\-p \fIport\fR
|
||||
Use this port instead of the default of 53.
|
||||
|
||||
.TP
|
||||
\fB\-r \fIfile\fR
|
||||
When tracing (\-T), use file as a root servers hint file.
|
||||
|
||||
.TP
|
||||
\fB\-s
|
||||
When encountering a DNSKEY print the equivalent DS also.
|
||||
|
||||
.TP
|
||||
\fB\-u
|
||||
Use UDP when querying a server. This is the default.
|
||||
|
||||
.TP
|
||||
\fB\-w \fIfile\fR
|
||||
write the answer to a file. The file will contain a hexadecimal dump
|
||||
of the query. This can be used in conjunction with \-f.
|
||||
|
||||
.TP
|
||||
\fB\-x
|
||||
Do a reverse lookup. The type argument is not used, it is preset to PTR.
|
||||
|
||||
.TP
|
||||
\fB\-y \fI<name:key[:algo]>\fR
|
||||
specify named base64 tsig key, and optional an algorithm (defaults to hmac-md5.sig-alg.reg.int)
|
||||
|
||||
.TP
|
||||
\fB\-z \fR
|
||||
don't randomize the nameserver list before sending queries.
|
||||
|
||||
|
||||
.SS EDNS QUERY OPTIONS
|
||||
|
||||
.TP
|
||||
\fB\+nsid \fR
|
||||
When set, this EDNS option includes an EDNS name server ID request in the query.
|
||||
|
||||
|
||||
|
||||
.SH "EXIT STATUS"
|
||||
The exit status is 0 if the looked up answer is secure and trusted,
|
||||
or insecure.
|
||||
The exit status is not 0 if the looked up answer is untrusted or bogus,
|
||||
or an error occurred while performing the lookup.
|
||||
|
||||
.SH "FILES"
|
||||
.TP
|
||||
@LDNS_TRUST_ANCHOR_FILE@
|
||||
The file from which trusted keys are loaded when no \fB-k\fR option is given.
|
||||
.SH "SEE ALSO"
|
||||
.LP
|
||||
unbound-anchor(8)
|
||||
|
||||
.SH AUTHOR
|
||||
Jelte Jansen and Miek Gieben. Both of NLnet Labs.
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Report bugs to <dns-team@nlnetlabs.nl>.
|
||||
|
||||
.SH BUGS
|
||||
|
||||
.SH COPYRIGHT
|
||||
Copyright (c) 2004-2008 NLnet Labs.
|
||||
Licensed under the revised BSD license. There is NO warranty; not even for MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
.SH SEE ALSO
|
||||
\fBdig\fR(1), \fIRFC403{3,4,5}\fR.
|
||||
1057
zonemaster-ldns/ldns/drill/drill.c
Normal file
1057
zonemaster-ldns/ldns/drill/drill.c
Normal file
File diff suppressed because it is too large
Load Diff
100
zonemaster-ldns/ldns/drill/drill.h
Normal file
100
zonemaster-ldns/ldns/drill/drill.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* drill.h
|
||||
* the main header file of drill
|
||||
* (c) 2005, 2006 NLnet Labs
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*
|
||||
*/
|
||||
#ifndef _DRILL_H_
|
||||
#define _DRILL_H_
|
||||
#include "config.h"
|
||||
|
||||
#include "drill_util.h"
|
||||
|
||||
#define DRILL_VERSION PACKAGE_VERSION
|
||||
|
||||
/* what kind of stuff do we allow */
|
||||
#define DRILL_QUERY 0
|
||||
#define DRILL_TRACE 1
|
||||
#define DRILL_CHASE 2
|
||||
#define DRILL_AFROMFILE 3
|
||||
#define DRILL_QTOFILE 4
|
||||
#define DRILL_NSEC 5
|
||||
#define DRILL_SECTRACE 7
|
||||
|
||||
#define DRILL_ON(VAR, BIT) \
|
||||
(VAR) = (VAR) | (BIT)
|
||||
#define DRILL_OFF(VAR, BIT) \
|
||||
(VAR) = (VAR) & ~(BIT)
|
||||
|
||||
extern ldns_rr_list *global_dns_root;
|
||||
extern int verbosity;
|
||||
|
||||
void do_trace(ldns_resolver *res,
|
||||
ldns_rdf *name,
|
||||
ldns_rr_type type,
|
||||
ldns_rr_class c);
|
||||
ldns_status do_chase(ldns_resolver *res,
|
||||
ldns_rdf *name,
|
||||
ldns_rr_type type,
|
||||
ldns_rr_class c,
|
||||
ldns_rr_list *trusted_keys,
|
||||
ldns_pkt *pkt_o,
|
||||
uint16_t qflags,
|
||||
ldns_rr_list *prev_key_list);
|
||||
int do_secure_trace(ldns_resolver *res,
|
||||
ldns_rdf *name,
|
||||
ldns_rr_type type,
|
||||
ldns_rr_class c,
|
||||
ldns_rr_list *trusted_keys,
|
||||
ldns_rdf *start_name);
|
||||
|
||||
ldns_rr_list * get_rr(ldns_resolver *res,
|
||||
ldns_rdf *zname,
|
||||
ldns_rr_type t,
|
||||
ldns_rr_class c);
|
||||
|
||||
void drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p);
|
||||
void drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p);
|
||||
|
||||
ldns_pkt_type get_dnssec_rr(ldns_pkt *p,
|
||||
ldns_rdf *name,
|
||||
ldns_rr_type t,
|
||||
ldns_rr_list **rrlist,
|
||||
ldns_rr_list **sig);
|
||||
|
||||
ldns_rr *ldns_nsec3_exact_match(ldns_rdf *qname,
|
||||
ldns_rr_type qtype,
|
||||
ldns_rr_list *nsec3s);
|
||||
|
||||
ldns_rdf *ldns_nsec3_closest_encloser(ldns_rdf *qname,
|
||||
ldns_rr_type qtype,
|
||||
ldns_rr_list *nsec3s);
|
||||
|
||||
/* verifies denial of existence of *name in *pkt (must contain NSEC or NSEC3 records
|
||||
* if *nsec_rrs and *nsec_rr_sigs are given, pointers to the relevant nsecs and their signatures are
|
||||
* placed there
|
||||
*/
|
||||
ldns_status ldns_verify_denial(ldns_pkt *pkt,
|
||||
ldns_rdf *name,
|
||||
ldns_rr_type type,
|
||||
ldns_rr_list **nsec_rrs,
|
||||
ldns_rr_list **nsec_rr_sigs);
|
||||
|
||||
ldns_pkt *read_hex_pkt(char *filename);
|
||||
ldns_buffer *read_hex_buffer(char *filename);
|
||||
void init_root(void);
|
||||
ldns_rr_list *read_root_hints(const char *filename);
|
||||
void clear_root(void);
|
||||
void dump_hex(const ldns_pkt *pkt, const char *file);
|
||||
void warning(const char *fmt, ...);
|
||||
void error(const char *fmt, ...);
|
||||
void mesg(const char *fmt, ...);
|
||||
|
||||
/* screen.c */
|
||||
void resolver_print_nameservers(ldns_resolver *r);
|
||||
void print_dnskey(ldns_rr_list *key_list);
|
||||
void print_ds(ldns_rr_list *ds_list);
|
||||
|
||||
#endif /* _DRILL_H_ */
|
||||
311
zonemaster-ldns/ldns/drill/drill_util.c
Normal file
311
zonemaster-ldns/ldns/drill/drill_util.c
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* util.c
|
||||
* some handy function needed in drill and not implemented
|
||||
* in ldns
|
||||
* (c) 2005 NLnet Labs
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drill.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static int
|
||||
read_line(FILE *input, char *line, size_t len)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
for (i = 0; i < (int)len-1; i++) {
|
||||
c = getc(input);
|
||||
if (c == EOF) {
|
||||
return -1;
|
||||
} else if (c != '\n') {
|
||||
line[i] = c;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
line[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
/* key_list must be initialized with ldns_rr_list_new() */
|
||||
ldns_status
|
||||
read_key_file(const char *filename, ldns_rr_list *key_list, bool silently)
|
||||
{
|
||||
int line_len = 0;
|
||||
int line_nr = 0;
|
||||
int key_count = 0;
|
||||
char line[LDNS_MAX_LINELEN];
|
||||
ldns_status status;
|
||||
FILE *input_file;
|
||||
ldns_rr *rr;
|
||||
|
||||
input_file = fopen(filename, "r");
|
||||
if (!input_file) {
|
||||
if (! silently) {
|
||||
fprintf(stderr, "Error opening %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
}
|
||||
return LDNS_STATUS_ERR;
|
||||
}
|
||||
while (line_len >= 0) {
|
||||
line_len = (int) read_line(input_file, line, sizeof(line));
|
||||
line_nr++;
|
||||
if (line_len > 0 && line[0] != ';') {
|
||||
status = ldns_rr_new_frm_str(&rr, line, 0, NULL, NULL);
|
||||
if (status != LDNS_STATUS_OK) {
|
||||
if (! silently) {
|
||||
fprintf(stderr,
|
||||
"Error parsing DNSKEY RR "
|
||||
"in line %d: %s\n", line_nr,
|
||||
ldns_get_errorstr_by_id(status)
|
||||
);
|
||||
}
|
||||
} else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY ||
|
||||
ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS) {
|
||||
ldns_rr_list_push_rr(key_list, rr);
|
||||
key_count++;
|
||||
} else {
|
||||
ldns_rr_free(rr);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(input_file);
|
||||
if (key_count > 0) {
|
||||
return LDNS_STATUS_OK;
|
||||
} else {
|
||||
/*fprintf(stderr, "No keys read\n");*/
|
||||
return LDNS_STATUS_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
ldns_rdf *
|
||||
ldns_rdf_new_addr_frm_str(char *str)
|
||||
{
|
||||
ldns_rdf *a;
|
||||
|
||||
a = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, str);
|
||||
if (!a) {
|
||||
/* maybe ip6 */
|
||||
a = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, str);
|
||||
if (!a) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline void
|
||||
local_print_ds(FILE* out, const char* pre, ldns_rr* ds)
|
||||
{
|
||||
if (out && ds) {
|
||||
fprintf(out, "%s", pre);
|
||||
ldns_rr_print(out, ds);
|
||||
ldns_rr_free(ds);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For all keys in a packet print the DS
|
||||
*/
|
||||
void
|
||||
print_ds_of_keys(ldns_pkt *p)
|
||||
{
|
||||
ldns_rr_list *keys;
|
||||
uint16_t i;
|
||||
ldns_rr *ds;
|
||||
|
||||
/* TODO fix the section stuff, here or in ldns */
|
||||
keys = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_DNSKEY,
|
||||
LDNS_SECTION_ANSWER);
|
||||
|
||||
/* this also returns the question section rr, which does not
|
||||
* have any data.... and this inturn crashes everything */
|
||||
|
||||
if (keys) {
|
||||
for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
|
||||
fprintf(stdout, ";\n; equivalent DS records for key %u:\n",
|
||||
(unsigned int)ldns_calc_keytag(ldns_rr_list_rr(keys, i)));
|
||||
|
||||
ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA1);
|
||||
local_print_ds(stdout, "; sha1: ", ds);
|
||||
ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA256);
|
||||
local_print_ds(stdout, "; sha256: ", ds);
|
||||
}
|
||||
ldns_rr_list_deep_free(keys);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_class_type(FILE *fp, ldns_rr *r)
|
||||
{
|
||||
ldns_lookup_table *lt;
|
||||
lt = ldns_lookup_by_id(ldns_rr_classes, ldns_rr_get_class(r));
|
||||
if (lt) {
|
||||
fprintf(fp, " %s", lt->name);
|
||||
} else {
|
||||
fprintf(fp, " CLASS%d", ldns_rr_get_class(r));
|
||||
}
|
||||
/* okay not THE way - but the quickest */
|
||||
switch (ldns_rr_get_type(r)) {
|
||||
case LDNS_RR_TYPE_RRSIG:
|
||||
fprintf(fp, " RRSIG ");
|
||||
break;
|
||||
case LDNS_RR_TYPE_DNSKEY:
|
||||
fprintf(fp, " DNSKEY ");
|
||||
break;
|
||||
case LDNS_RR_TYPE_DS:
|
||||
fprintf(fp, " DS ");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
print_ds_abbr(FILE *fp, ldns_rr *ds)
|
||||
{
|
||||
if (!ds || (ldns_rr_get_type(ds) != LDNS_RR_TYPE_DS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ldns_rdf_print(fp, ldns_rr_owner(ds));
|
||||
fprintf(fp, " %d", (int)ldns_rr_ttl(ds));
|
||||
print_class_type(fp, ds);
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(ds, 0)); fprintf(fp, " ");
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(ds, 1)); fprintf(fp, " ");
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(ds, 2)); fprintf(fp, " ");
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(ds, 3)); fprintf(fp, " ");
|
||||
}
|
||||
|
||||
/* print some of the elements of a signature */
|
||||
void
|
||||
print_rrsig_abbr(FILE *fp, ldns_rr *sig) {
|
||||
if (!sig || (ldns_rr_get_type(sig) != LDNS_RR_TYPE_RRSIG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ldns_rdf_print(fp, ldns_rr_owner(sig));
|
||||
fprintf(fp, " %d", (int)ldns_rr_ttl(sig));
|
||||
print_class_type(fp, sig);
|
||||
|
||||
/* print a number of rdf's */
|
||||
/* typecovered */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(sig, 0)); fprintf(fp, " ");
|
||||
/* algo */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(sig, 1)); fprintf(fp, " ");
|
||||
/* labels */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(sig, 2)); fprintf(fp, " (\n\t\t\t");
|
||||
/* expir */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(sig, 4)); fprintf(fp, " ");
|
||||
/* incep */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(sig, 5)); fprintf(fp, " ");
|
||||
/* key-id */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(sig, 6)); fprintf(fp, " ");
|
||||
/* key owner */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(sig, 7)); fprintf(fp, ")");
|
||||
}
|
||||
|
||||
void
|
||||
print_dnskey_abbr(FILE *fp, ldns_rr *key)
|
||||
{
|
||||
if (!key || (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ldns_rdf_print(fp, ldns_rr_owner(key));
|
||||
fprintf(fp, " %d", (int)ldns_rr_ttl(key));
|
||||
print_class_type(fp, key);
|
||||
|
||||
/* print a number of rdf's */
|
||||
/* flags */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(key, 0)); fprintf(fp, " ");
|
||||
/* proto */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(key, 1)); fprintf(fp, " ");
|
||||
/* algo */
|
||||
ldns_rdf_print(fp, ldns_rr_rdf(key, 2));
|
||||
|
||||
if (ldns_rdf2native_int16(ldns_rr_rdf(key, 0)) == 256) {
|
||||
fprintf(fp, " ;{id = %u (zsk), size = %db}", (unsigned int)ldns_calc_keytag(key),
|
||||
(int)ldns_rr_dnskey_key_size(key));
|
||||
return;
|
||||
}
|
||||
if (ldns_rdf2native_int16(ldns_rr_rdf(key, 0)) == 257) {
|
||||
fprintf(fp, " ;{id = %u (ksk), size = %db}", (unsigned int)ldns_calc_keytag(key),
|
||||
(int)ldns_rr_dnskey_key_size(key));
|
||||
return;
|
||||
}
|
||||
fprintf(fp, " ;{id = %u, size = %db}", (unsigned int)ldns_calc_keytag(key),
|
||||
(int)ldns_rr_dnskey_key_size(key));
|
||||
}
|
||||
|
||||
void
|
||||
print_rr_list_abbr(FILE *fp, ldns_rr_list *rrlist, const char *usr)
|
||||
{
|
||||
size_t i;
|
||||
ldns_rr_type tp;
|
||||
|
||||
for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
|
||||
tp = ldns_rr_get_type(ldns_rr_list_rr(rrlist, i));
|
||||
if (i == 0 && tp != LDNS_RR_TYPE_RRSIG) {
|
||||
if (usr) {
|
||||
fprintf(fp, "%s ", usr);
|
||||
}
|
||||
}
|
||||
switch(tp) {
|
||||
case LDNS_RR_TYPE_DNSKEY:
|
||||
print_dnskey_abbr(fp, ldns_rr_list_rr(rrlist, i));
|
||||
break;
|
||||
case LDNS_RR_TYPE_RRSIG:
|
||||
print_rrsig_abbr(fp, ldns_rr_list_rr(rrlist, i));
|
||||
break;
|
||||
case LDNS_RR_TYPE_DS:
|
||||
print_ds_abbr(fp, ldns_rr_list_rr(rrlist, i));
|
||||
break;
|
||||
default:
|
||||
/* not handled */
|
||||
break;
|
||||
}
|
||||
fputs("\n", fp);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc(size_t s)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc(s);
|
||||
if (!p) {
|
||||
printf("Mem failure\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
xrealloc(void *p, size_t size)
|
||||
{
|
||||
void *q;
|
||||
|
||||
q = realloc(p, size);
|
||||
if (!q) {
|
||||
printf("Mem failure\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
void
|
||||
xfree(void *p)
|
||||
{
|
||||
if (p) {
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
65
zonemaster-ldns/ldns/drill/drill_util.h
Normal file
65
zonemaster-ldns/ldns/drill/drill_util.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* util.h
|
||||
* util.c header file
|
||||
* in ldns
|
||||
* (c) 2005 NLnet Labs
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DRILL_UTIL_H_
|
||||
#define _DRILL_UTIL_H_
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
|
||||
/**
|
||||
* Read keys from filename and append to key_list.
|
||||
*/
|
||||
ldns_status read_key_file(const char *filename, ldns_rr_list *key_list,
|
||||
bool silently);
|
||||
|
||||
/**
|
||||
* return a address rdf, either A or AAAA
|
||||
* NULL if anything goes wrong
|
||||
*/
|
||||
ldns_rdf * ldns_rdf_new_addr_frm_str(char *);
|
||||
|
||||
/**
|
||||
* print all the ds of the keys in the packet
|
||||
*/
|
||||
void print_ds_of_keys(ldns_pkt *p);
|
||||
|
||||
/**
|
||||
* print some rdfs of a signature
|
||||
*/
|
||||
void print_rrsig_abbr(FILE *fp, ldns_rr *sig);
|
||||
/**
|
||||
* print some rdfs of a dnskey
|
||||
*/
|
||||
void print_dnskey_abbr(FILE *fp, ldns_rr *key);
|
||||
/**
|
||||
* print some rdfs of a ds
|
||||
*/
|
||||
void print_ds_abbr(FILE *fp, ldns_rr *ds);
|
||||
|
||||
/**
|
||||
* print some rdfs of a rr in a rr_list
|
||||
*/
|
||||
void print_rr_list_abbr(FILE *fp, ldns_rr_list *sig, const char *usr);
|
||||
|
||||
/**
|
||||
* Alloc some memory, with error checking
|
||||
*/
|
||||
void *xmalloc(size_t s);
|
||||
|
||||
/**
|
||||
* Realloc some memory, with error checking
|
||||
*/
|
||||
void *xrealloc(void *p, size_t s);
|
||||
|
||||
/**
|
||||
* Free the data
|
||||
*/
|
||||
void xfree(void *q);
|
||||
#endif /* _DRILL_UTIL_H_ */
|
||||
86
zonemaster-ldns/ldns/drill/error.c
Normal file
86
zonemaster-ldns/ldns/drill/error.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* error.c
|
||||
*
|
||||
* error reporting routines
|
||||
* basically wrappers around printf
|
||||
*
|
||||
* (c) 2005 NLnet Labs
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drill.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
static void
|
||||
warning_va_list(const char *fmt, va_list args)
|
||||
{
|
||||
fprintf(stderr, "Warning: ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
warning(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
warning_va_list(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void
|
||||
error_va_list(const char *fmt, va_list args)
|
||||
{
|
||||
fprintf(stderr, "Error: ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
error(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
error_va_list(fmt, args);
|
||||
va_end(args);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void
|
||||
verbose_va_list(const char *fmt, va_list args)
|
||||
{
|
||||
vfprintf(stdout, fmt, args);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
/* print stuff */
|
||||
void
|
||||
mesg(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
if (verbosity == -1) {
|
||||
return;
|
||||
}
|
||||
fprintf(stdout, ";; ");
|
||||
va_start(args, fmt);
|
||||
verbose_va_list(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* print stuff when in verbose mode (1) */
|
||||
void
|
||||
verbose(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
if (verbosity < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
verbose_va_list(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
||||
520
zonemaster-ldns/ldns/drill/install-sh
Executable file
520
zonemaster-ldns/ldns/drill/install-sh
Executable file
@@ -0,0 +1,520 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2009-04-28.21; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dst=$dst_arg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst;;
|
||||
esac
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
-*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test -z "$d" && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
134
zonemaster-ldns/ldns/drill/root.c
Normal file
134
zonemaster-ldns/ldns/drill/root.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* root.c
|
||||
* Function to handle to the rootservers
|
||||
* and to update and prime them
|
||||
* (c) 2005 NLnet Labs
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drill.h"
|
||||
#include <ldns/ldns.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* a global list of the root-servers */
|
||||
ldns_rr_list *global_dns_root = NULL;
|
||||
|
||||
/* put a hardcoded list in the root and
|
||||
* init the root rrlist structure */
|
||||
void
|
||||
init_root(void)
|
||||
{
|
||||
ldns_rr *r;
|
||||
|
||||
global_dns_root = ldns_rr_list_new();
|
||||
|
||||
(void)ldns_rr_new_frm_str(&r, "A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:BA3E::2:30", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "B.ROOT-SERVERS.NET. 3600000 A 170.247.170.2", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "B.ROOT-SERVERS.NET. 3600000 AAAA 2801:1b8:10::B", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "C.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2::C", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "D.ROOT-SERVERS.NET. 3600000 A 199.7.91.13", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2D::D", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "E.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:A8::E", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2F::F", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "G.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:12::D0D", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "H.ROOT-SERVERS.NET. 3600000 A 198.97.190.53", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::53", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "I.ROOT-SERVERS.NET. 3600000 AAAA 2001:7FE::53", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:C27::2:30", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129 ", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7FD::1", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "L.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:9F::42", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
(void)ldns_rr_new_frm_str(&r, "M.ROOT-SERVERS.NET. 3600000 AAAA 2001:DC3::35", 0, NULL, NULL);
|
||||
ldns_rr_list_push_rr(global_dns_root, r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a hints file as root
|
||||
*
|
||||
* The file with the given path should contain a list of NS RRs
|
||||
* for the root zone and A records for those NS RRs.
|
||||
* Read them, check them, and append the a records to the rr list given.
|
||||
*/
|
||||
ldns_rr_list *
|
||||
read_root_hints(const char *filename)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
int line_nr = 0;
|
||||
ldns_zone *z;
|
||||
ldns_status status;
|
||||
ldns_rr_list *addresses = NULL;
|
||||
ldns_rr *rr;
|
||||
size_t i;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Unable to open %s for reading: %s\n", filename, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, 0, &line_nr);
|
||||
fclose(fp);
|
||||
if (status != LDNS_STATUS_OK) {
|
||||
fprintf(stderr, "Error reading root hints file: %s\n", ldns_get_errorstr_by_id(status));
|
||||
return NULL;
|
||||
} else {
|
||||
addresses = ldns_rr_list_new();
|
||||
for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) {
|
||||
rr = ldns_rr_list_rr(ldns_zone_rrs(z), i);
|
||||
/*if ((address_family == 0 || address_family == 1) &&
|
||||
*/
|
||||
if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_A ) {
|
||||
ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr));
|
||||
}
|
||||
/*if ((address_family == 0 || address_family == 2) &&*/
|
||||
if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
|
||||
ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr));
|
||||
}
|
||||
}
|
||||
ldns_zone_deep_free(z);
|
||||
return addresses;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
clear_root(void)
|
||||
{
|
||||
ldns_rr_list_deep_free(global_dns_root);
|
||||
}
|
||||
797
zonemaster-ldns/ldns/drill/securetrace.c
Normal file
797
zonemaster-ldns/ldns/drill/securetrace.c
Normal file
@@ -0,0 +1,797 @@
|
||||
/*
|
||||
* securechasetrace.c
|
||||
* Where all the hard work concerning secure tracing is done
|
||||
*
|
||||
* (c) 2005, 2006 NLnet Labs
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drill.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
#define SELF "[S]" /* self sig ok */
|
||||
#define TRUST "[T]" /* chain from parent */
|
||||
#define BOGUS "[B]" /* bogus */
|
||||
#define UNSIGNED "[U]" /* no relevant dnssec data found */
|
||||
|
||||
#if 0
|
||||
/* See if there is a key/ds in trusted that matches
|
||||
* a ds in *ds.
|
||||
*/
|
||||
static ldns_rr_list *
|
||||
ds_key_match(ldns_rr_list *ds, ldns_rr_list *trusted)
|
||||
{
|
||||
size_t i, j;
|
||||
bool match;
|
||||
ldns_rr *rr_i, *rr_j;
|
||||
ldns_rr_list *keys;
|
||||
|
||||
if (!trusted || !ds) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
match = false;
|
||||
keys = ldns_rr_list_new();
|
||||
if (!keys) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ds || !trusted) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ldns_rr_list_rr_count(trusted); i++) {
|
||||
rr_i = ldns_rr_list_rr(trusted, i);
|
||||
for (j = 0; j < ldns_rr_list_rr_count(ds); j++) {
|
||||
|
||||
rr_j = ldns_rr_list_rr(ds, j);
|
||||
if (ldns_rr_compare_ds(rr_i, rr_j)) {
|
||||
match = true;
|
||||
/* only allow unique RRs to match */
|
||||
ldns_rr_set_push_rr(keys, rr_i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
return keys;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static ldns_pkt *
|
||||
get_dnssec_pkt(ldns_resolver *r, ldns_rdf *name, ldns_rr_type t)
|
||||
{
|
||||
ldns_pkt *p = NULL;
|
||||
p = ldns_resolver_query(r, name, t, LDNS_RR_CLASS_IN, 0);
|
||||
if (!p) {
|
||||
return NULL;
|
||||
} else {
|
||||
if (verbosity >= 5) {
|
||||
ldns_pkt_print(stdout, p);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
/*
|
||||
* retrieve keys for this zone
|
||||
*/
|
||||
static ldns_pkt_type
|
||||
get_key(ldns_pkt *p, ldns_rdf *apexname, ldns_rr_list **rrlist, ldns_rr_list **opt_sig)
|
||||
{
|
||||
return get_dnssec_rr(p, apexname, LDNS_RR_TYPE_DNSKEY, rrlist, opt_sig);
|
||||
}
|
||||
|
||||
/*
|
||||
* check to see if we can find a DS rrset here which we can then follow
|
||||
*/
|
||||
static ldns_pkt_type
|
||||
get_ds(ldns_pkt *p, ldns_rdf *ownername, ldns_rr_list **rrlist, ldns_rr_list **opt_sig)
|
||||
{
|
||||
return get_dnssec_rr(p, ownername, LDNS_RR_TYPE_DS, rrlist, opt_sig);
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
static void
|
||||
remove_resolver_nameservers(ldns_resolver *res)
|
||||
{
|
||||
ldns_rdf *pop;
|
||||
|
||||
/* remove the old nameserver from the resolver */
|
||||
while((pop = ldns_resolver_pop_nameserver(res))) {
|
||||
ldns_rdf_deep_free(pop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*ldns_pkt **/
|
||||
#ifdef HAVE_SSL
|
||||
int
|
||||
do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
|
||||
ldns_rr_class c, ldns_rr_list *trusted_keys, ldns_rdf *start_name
|
||||
)
|
||||
{
|
||||
ldns_resolver *res;
|
||||
ldns_pkt *p, *local_p;
|
||||
ldns_rr_list *new_nss;
|
||||
ldns_rr_list *ns_addr;
|
||||
ldns_rdf *pop;
|
||||
ldns_rdf **labels = NULL;
|
||||
ldns_status status, st;
|
||||
ssize_t i;
|
||||
size_t j;
|
||||
size_t k;
|
||||
size_t l;
|
||||
uint8_t labels_count = 0;
|
||||
|
||||
/* dnssec */
|
||||
ldns_rr_list *key_list;
|
||||
ldns_rr_list *key_sig_list;
|
||||
ldns_rr_list *ds_list;
|
||||
ldns_rr_list *ds_sig_list;
|
||||
ldns_rr_list *correct_key_list;
|
||||
ldns_rr_list *trusted_ds_rrs;
|
||||
bool new_keys_trusted = false;
|
||||
ldns_rr_list *current_correct_keys = NULL;
|
||||
ldns_rr_list *dataset;
|
||||
|
||||
ldns_rr_list *nsec_rrs = NULL;
|
||||
ldns_rr_list *nsec_rr_sigs = NULL;
|
||||
|
||||
/* empty non-terminal check */
|
||||
bool ent;
|
||||
ldns_rr *nsecrr; /* The nsec that proofs the non-terminal */
|
||||
ldns_rdf *hashed_name; /* The query hashed with nsec3 params */
|
||||
ldns_rdf *label0; /* The first label of an nsec3 owner name */
|
||||
|
||||
/* glue handling */
|
||||
ldns_rr_list *new_ns_addr;
|
||||
ldns_rr_list *old_ns_addr;
|
||||
ldns_rr *ns_rr;
|
||||
|
||||
int result = 0;
|
||||
|
||||
/* printing niceness */
|
||||
const ldns_rr_descriptor *descriptor;
|
||||
|
||||
descriptor = ldns_rr_descript(t);
|
||||
|
||||
new_nss = NULL;
|
||||
ns_addr = NULL;
|
||||
key_list = NULL;
|
||||
ds_list = NULL;
|
||||
|
||||
p = NULL;
|
||||
local_p = NULL;
|
||||
res = ldns_resolver_new();
|
||||
key_sig_list = NULL;
|
||||
ds_sig_list = NULL;
|
||||
|
||||
if (!res) {
|
||||
error("Memory allocation failed");
|
||||
result = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
correct_key_list = ldns_rr_list_new();
|
||||
if (!correct_key_list) {
|
||||
error("Memory allocation failed");
|
||||
result = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
trusted_ds_rrs = ldns_rr_list_new();
|
||||
if (!trusted_ds_rrs) {
|
||||
error("Memory allocation failed");
|
||||
result = -1;
|
||||
return result;
|
||||
}
|
||||
/* Add all preset trusted DS signatures to the list of trusted DS RRs. */
|
||||
for (j = 0; j < ldns_rr_list_rr_count(trusted_keys); j++) {
|
||||
ldns_rr* one_rr = ldns_rr_list_rr(trusted_keys, j);
|
||||
if (ldns_rr_get_type(one_rr) == LDNS_RR_TYPE_DS) {
|
||||
ldns_rr_list_push_rr(trusted_ds_rrs, ldns_rr_clone(one_rr));
|
||||
}
|
||||
}
|
||||
|
||||
/* transfer some properties of local_res to res */
|
||||
ldns_resolver_set_ip6(res,
|
||||
ldns_resolver_ip6(local_res));
|
||||
ldns_resolver_set_port(res,
|
||||
ldns_resolver_port(local_res));
|
||||
ldns_resolver_set_debug(res,
|
||||
ldns_resolver_debug(local_res));
|
||||
ldns_resolver_set_fail(res,
|
||||
ldns_resolver_fail(local_res));
|
||||
ldns_resolver_set_usevc(res,
|
||||
ldns_resolver_usevc(local_res));
|
||||
ldns_resolver_set_random(res,
|
||||
ldns_resolver_random(local_res));
|
||||
ldns_resolver_set_source(res,
|
||||
ldns_resolver_source(local_res));
|
||||
ldns_resolver_set_recursive(local_res, true);
|
||||
|
||||
ldns_resolver_set_recursive(res, false);
|
||||
ldns_resolver_set_dnssec_cd(res, false);
|
||||
ldns_resolver_set_dnssec(res, true);
|
||||
|
||||
/* setup the root nameserver in the new resolver */
|
||||
status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root);
|
||||
if (status != LDNS_STATUS_OK) {
|
||||
printf("ERRRRR: %s\n", ldns_get_errorstr_by_id(status));
|
||||
ldns_rr_list_print(stdout, global_dns_root);
|
||||
result = status;
|
||||
goto done;
|
||||
}
|
||||
labels_count = ldns_dname_label_count(name);
|
||||
if (start_name) {
|
||||
if (ldns_dname_is_subdomain(name, start_name)) {
|
||||
labels_count -= ldns_dname_label_count(start_name);
|
||||
} else {
|
||||
fprintf(stderr, "Error; ");
|
||||
ldns_rdf_print(stderr, name);
|
||||
fprintf(stderr, " is not a subdomain of ");
|
||||
ldns_rdf_print(stderr, start_name);
|
||||
fprintf(stderr, "\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
labels = LDNS_CALLOC(ldns_rdf*, labels_count + 2);
|
||||
if (!labels) {
|
||||
goto done;
|
||||
}
|
||||
labels[0] = ldns_dname_new_frm_str(LDNS_ROOT_LABEL_STR);
|
||||
labels[1] = ldns_rdf_clone(name);
|
||||
for(i = 2 ; i < (ssize_t)labels_count + 2; i++) {
|
||||
labels[i] = ldns_dname_left_chop(labels[i - 1]);
|
||||
}
|
||||
|
||||
/* get the nameserver for the label
|
||||
* ask: dnskey and ds for the label
|
||||
*/
|
||||
for(i = (ssize_t)labels_count + 1; i > 0; i--) {
|
||||
status = ldns_resolver_send(&local_p, res, labels[i], LDNS_RR_TYPE_NS, c, 0);
|
||||
if (status != LDNS_STATUS_OK) {
|
||||
fprintf(stderr, "Error sending query: %s\n", ldns_get_errorstr_by_id(status));
|
||||
result = status;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* TODO: handle status */
|
||||
|
||||
if (verbosity >= 5) {
|
||||
ldns_pkt_print(stdout, local_p);
|
||||
}
|
||||
|
||||
new_nss = ldns_pkt_rr_list_by_type(local_p,
|
||||
LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
|
||||
if (!new_nss) {
|
||||
/* if it's a delegation, servers put them in the auth section */
|
||||
new_nss = ldns_pkt_rr_list_by_type(local_p,
|
||||
LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY);
|
||||
}
|
||||
|
||||
/* if this is the final step there might not be nameserver records
|
||||
of course if the data is in the apex, there are, so cover both
|
||||
cases */
|
||||
if (new_nss || i > 1) {
|
||||
for(j = 0; j < ldns_rr_list_rr_count(new_nss); j++) {
|
||||
ns_rr = ldns_rr_list_rr(new_nss, j);
|
||||
pop = ldns_rr_rdf(ns_rr, 0);
|
||||
if (!pop) {
|
||||
printf("nopo\n");
|
||||
break;
|
||||
}
|
||||
/* retrieve it's addresses */
|
||||
/* trust glue? */
|
||||
new_ns_addr = NULL;
|
||||
if (ldns_dname_is_subdomain(pop, labels[i])) {
|
||||
new_ns_addr = ldns_pkt_rr_list_by_name_and_type(local_p, pop, LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL);
|
||||
}
|
||||
if (!new_ns_addr || ldns_rr_list_rr_count(new_ns_addr) == 0) {
|
||||
new_ns_addr = ldns_get_rr_list_addr_by_name(res, pop, c, 0);
|
||||
}
|
||||
if (!new_ns_addr || ldns_rr_list_rr_count(new_ns_addr) == 0) {
|
||||
new_ns_addr = ldns_get_rr_list_addr_by_name(local_res, pop, c, 0);
|
||||
}
|
||||
|
||||
if (new_ns_addr) {
|
||||
old_ns_addr = ns_addr;
|
||||
ns_addr = ldns_rr_list_cat_clone(ns_addr, new_ns_addr);
|
||||
ldns_rr_list_deep_free(old_ns_addr);
|
||||
}
|
||||
ldns_rr_list_deep_free(new_ns_addr);
|
||||
}
|
||||
ldns_rr_list_deep_free(new_nss);
|
||||
|
||||
if (ns_addr) {
|
||||
remove_resolver_nameservers(res);
|
||||
|
||||
if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) !=
|
||||
LDNS_STATUS_OK) {
|
||||
error("Error adding new nameservers");
|
||||
ldns_pkt_free(local_p);
|
||||
goto done;
|
||||
}
|
||||
ldns_rr_list_deep_free(ns_addr);
|
||||
} else {
|
||||
status = ldns_verify_denial(local_p, labels[i], LDNS_RR_TYPE_NS, &nsec_rrs, &nsec_rr_sigs);
|
||||
|
||||
/* verify the nsec3 themselves*/
|
||||
if (verbosity >= 4) {
|
||||
printf("NSEC(3) Records to verify:\n");
|
||||
ldns_rr_list_print(stdout, nsec_rrs);
|
||||
printf("With signatures:\n");
|
||||
ldns_rr_list_print(stdout, nsec_rr_sigs);
|
||||
printf("correct keys:\n");
|
||||
ldns_rr_list_print(stdout, correct_key_list);
|
||||
}
|
||||
|
||||
if (status == LDNS_STATUS_OK) {
|
||||
if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) {
|
||||
fprintf(stdout, "%s ", TRUST);
|
||||
fprintf(stdout, "Existence denied: ");
|
||||
ldns_rdf_print(stdout, labels[i]);
|
||||
/*
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf(" %s", descriptor->_name);
|
||||
} else {
|
||||
printf(" TYPE%u", t);
|
||||
}
|
||||
*/ fprintf(stdout, " NS\n");
|
||||
} else if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, correct_key_list, NULL)) == LDNS_STATUS_OK) {
|
||||
fprintf(stdout, "%s ", SELF);
|
||||
fprintf(stdout, "Existence denied: ");
|
||||
ldns_rdf_print(stdout, labels[i]);
|
||||
/*
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf(" %s", descriptor->_name);
|
||||
} else {
|
||||
printf(" TYPE%u", t);
|
||||
}
|
||||
*/
|
||||
fprintf(stdout, " NS\n");
|
||||
} else {
|
||||
fprintf(stdout, "%s ", BOGUS);
|
||||
result = 1;
|
||||
printf(";; Error verifying denial of existence for name ");
|
||||
ldns_rdf_print(stdout, labels[i]);
|
||||
/*
|
||||
printf(" type ");
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf("%s", descriptor->_name);
|
||||
} else {
|
||||
printf("TYPE%u", t);
|
||||
}
|
||||
*/ printf("NS: %s\n", ldns_get_errorstr_by_id(st));
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "%s ", BOGUS);
|
||||
result = 1;
|
||||
printf(";; Error verifying denial of existence for name ");
|
||||
ldns_rdf_print(stdout, labels[i]);
|
||||
printf("NS: %s\n", ldns_get_errorstr_by_id(status));
|
||||
}
|
||||
|
||||
/* there might be an empty non-terminal, in which case we need to continue */
|
||||
ent = false;
|
||||
for (j = 0; j < ldns_rr_list_rr_count(nsec_rrs); j++) {
|
||||
nsecrr = ldns_rr_list_rr(nsec_rrs, j);
|
||||
/* For NSEC when the next name is a subdomain of the question */
|
||||
if (ldns_rr_get_type(nsecrr) == LDNS_RR_TYPE_NSEC &&
|
||||
ldns_dname_is_subdomain(ldns_rr_rdf(nsecrr, 0), labels[i])) {
|
||||
ent = true;
|
||||
|
||||
/* For NSEC3, the hash matches the name and the type bitmap is empty*/
|
||||
} else if (ldns_rr_get_type(nsecrr) == LDNS_RR_TYPE_NSEC3) {
|
||||
hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsecrr, labels[i]);
|
||||
label0 = ldns_dname_label(ldns_rr_owner(nsecrr), 0);
|
||||
if (hashed_name && label0 &&
|
||||
ldns_dname_compare(hashed_name, label0) == 0 &&
|
||||
ldns_nsec3_bitmap(nsecrr) == NULL) {
|
||||
ent = true;
|
||||
}
|
||||
if (label0) {
|
||||
LDNS_FREE(label0);
|
||||
}
|
||||
if (hashed_name) {
|
||||
LDNS_FREE(hashed_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ent) {
|
||||
ldns_rr_list_deep_free(nsec_rrs);
|
||||
ldns_rr_list_deep_free(nsec_rr_sigs);
|
||||
ldns_pkt_free(local_p);
|
||||
goto done;
|
||||
} else {
|
||||
printf(";; There is an empty non-terminal here, continue\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ldns_resolver_nameserver_count(res) == 0) {
|
||||
error("No nameservers found for this node");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
ldns_pkt_free(local_p);
|
||||
|
||||
fprintf(stdout, ";; Domain: ");
|
||||
ldns_rdf_print(stdout, labels[i]);
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
/* retrieve keys for current domain, and verify them
|
||||
if they match an already trusted DS, or if one of the
|
||||
keys used to sign these is trusted, add the keys to
|
||||
the trusted list */
|
||||
p = get_dnssec_pkt(res, labels[i], LDNS_RR_TYPE_DNSKEY);
|
||||
(void) get_key(p, labels[i], &key_list, &key_sig_list);
|
||||
if (key_sig_list) {
|
||||
if (key_list) {
|
||||
current_correct_keys = ldns_rr_list_new();
|
||||
if ((st = ldns_verify(key_list, key_sig_list, key_list, current_correct_keys)) ==
|
||||
LDNS_STATUS_OK) {
|
||||
/* add all signed keys (don't just add current_correct, you'd miss
|
||||
* the zsk's then */
|
||||
for (j = 0; j < ldns_rr_list_rr_count(key_list); j++) {
|
||||
ldns_rr_list_push_rr(correct_key_list, ldns_rr_clone(ldns_rr_list_rr(key_list, j)));
|
||||
}
|
||||
|
||||
/* check whether these keys were signed
|
||||
* by a trusted keys. if so, these
|
||||
* keys are also trusted */
|
||||
new_keys_trusted = false;
|
||||
for (k = 0; k < ldns_rr_list_rr_count(current_correct_keys); k++) {
|
||||
for (j = 0; j < ldns_rr_list_rr_count(trusted_ds_rrs); j++) {
|
||||
if (ldns_rr_compare_ds(ldns_rr_list_rr(current_correct_keys, k),
|
||||
ldns_rr_list_rr(trusted_ds_rrs, j))) {
|
||||
new_keys_trusted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* also all keys are trusted if one of the current correct keys is trusted */
|
||||
for (k = 0; k < ldns_rr_list_rr_count(current_correct_keys); k++) {
|
||||
for (j = 0; j < ldns_rr_list_rr_count(trusted_keys); j++) {
|
||||
if (ldns_rr_compare(ldns_rr_list_rr(current_correct_keys, k),
|
||||
ldns_rr_list_rr(trusted_keys, j)) == 0) {
|
||||
new_keys_trusted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (new_keys_trusted) {
|
||||
ldns_rr_list_push_rr_list(trusted_keys, key_list);
|
||||
print_rr_list_abbr(stdout, key_list, TRUST);
|
||||
ldns_rr_list_free(key_list);
|
||||
key_list = NULL;
|
||||
} else {
|
||||
if (verbosity >= 2) {
|
||||
printf(";; Signature ok but no chain to a trusted key or ds record\n");
|
||||
}
|
||||
print_rr_list_abbr(stdout, key_list, SELF);
|
||||
ldns_rr_list_deep_free(key_list);
|
||||
key_list = NULL;
|
||||
}
|
||||
} else {
|
||||
print_rr_list_abbr(stdout, key_list, BOGUS);
|
||||
result = 2;
|
||||
ldns_rr_list_deep_free(key_list);
|
||||
key_list = NULL;
|
||||
}
|
||||
ldns_rr_list_free(current_correct_keys);
|
||||
current_correct_keys = NULL;
|
||||
} else {
|
||||
printf(";; No DNSKEY record found for ");
|
||||
ldns_rdf_print(stdout, labels[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
ldns_pkt_free(p);
|
||||
ldns_rr_list_deep_free(key_sig_list);
|
||||
key_sig_list = NULL;
|
||||
|
||||
/* check the DS records for the next child domain */
|
||||
if (i > 1) {
|
||||
p = get_dnssec_pkt(res, labels[i-1], LDNS_RR_TYPE_DS);
|
||||
(void) get_ds(p, labels[i-1], &ds_list, &ds_sig_list);
|
||||
if (!ds_list) {
|
||||
ldns_rr_list_deep_free(ds_sig_list);
|
||||
(void) get_dnssec_rr( p, labels[i-1]
|
||||
, LDNS_RR_TYPE_CNAME
|
||||
, &ds_list, &ds_sig_list);
|
||||
if (ds_list) {
|
||||
st = ldns_verify( ds_list, ds_sig_list
|
||||
, correct_key_list
|
||||
, current_correct_keys);
|
||||
|
||||
if (st == LDNS_STATUS_OK) {
|
||||
printf(";; No DS record found "
|
||||
"for ");
|
||||
ldns_rdf_print(stdout,
|
||||
labels[i-1]);
|
||||
printf(", but valid CNAME");
|
||||
} else {
|
||||
printf(BOGUS " Unable to verify "
|
||||
"denial of existence for ");
|
||||
ldns_rdf_print(stdout,
|
||||
labels[i-1]);
|
||||
printf(", because of BOGUS CNAME");
|
||||
}
|
||||
printf("\n");
|
||||
ldns_rr_list_deep_free(ds_sig_list);
|
||||
ldns_pkt_free(p);
|
||||
ldns_rr_list_deep_free(ds_list);
|
||||
ds_list = NULL;
|
||||
ds_sig_list = NULL;
|
||||
p = NULL;
|
||||
} else {
|
||||
ldns_rr_list_deep_free(ds_sig_list);
|
||||
ldns_pkt_free(p);
|
||||
p = get_dnssec_pkt(res, name,
|
||||
LDNS_RR_TYPE_DNSKEY);
|
||||
(void) get_ds(p, NULL
|
||||
, &ds_list, &ds_sig_list);
|
||||
}
|
||||
}
|
||||
if (ds_sig_list) {
|
||||
if (ds_list) {
|
||||
if (verbosity >= 4) {
|
||||
printf("VERIFYING:\n");
|
||||
printf("DS LIST:\n");
|
||||
ldns_rr_list_print(stdout, ds_list);
|
||||
printf("SIGS:\n");
|
||||
ldns_rr_list_print(stdout, ds_sig_list);
|
||||
printf("KEYS:\n");
|
||||
ldns_rr_list_print(stdout, correct_key_list);
|
||||
}
|
||||
|
||||
current_correct_keys = ldns_rr_list_new();
|
||||
|
||||
if ((st = ldns_verify(ds_list, ds_sig_list, correct_key_list, current_correct_keys)) ==
|
||||
LDNS_STATUS_OK) {
|
||||
/* if the ds is signed by a trusted key and a key from correct keys
|
||||
matches that ds, add that key to the trusted keys */
|
||||
new_keys_trusted = false;
|
||||
if (verbosity >= 2) {
|
||||
printf("Checking if signing key is trusted:\n");
|
||||
}
|
||||
for (j = 0; j < ldns_rr_list_rr_count(current_correct_keys); j++) {
|
||||
if (verbosity >= 2) {
|
||||
printf("New key: ");
|
||||
ldns_rr_print(stdout, ldns_rr_list_rr(current_correct_keys, j));
|
||||
}
|
||||
for (k = 0; k < ldns_rr_list_rr_count(trusted_keys); k++) {
|
||||
if (verbosity >= 2) {
|
||||
printf("\tTrusted key: ");
|
||||
ldns_rr_print(stdout, ldns_rr_list_rr(trusted_keys, k));
|
||||
}
|
||||
if (ldns_rr_compare(ldns_rr_list_rr(current_correct_keys, j),
|
||||
ldns_rr_list_rr(trusted_keys, k)) == 0) {
|
||||
if (verbosity >= 2) {
|
||||
printf("Key is now trusted!\n");
|
||||
}
|
||||
for (l = 0; l < ldns_rr_list_rr_count(ds_list); l++) {
|
||||
ldns_rr_list_push_rr(trusted_ds_rrs, ldns_rr_clone(ldns_rr_list_rr(ds_list, l)));
|
||||
new_keys_trusted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (new_keys_trusted) {
|
||||
print_rr_list_abbr(stdout, ds_list, TRUST);
|
||||
} else {
|
||||
print_rr_list_abbr(stdout, ds_list, SELF);
|
||||
}
|
||||
} else {
|
||||
result = 3;
|
||||
print_rr_list_abbr(stdout, ds_list, BOGUS);
|
||||
}
|
||||
|
||||
ldns_rr_list_free(current_correct_keys);
|
||||
current_correct_keys = NULL;
|
||||
} else {
|
||||
/* wait apparently there were no keys either, go back to the ds packet */
|
||||
ldns_pkt_free(p);
|
||||
ldns_rr_list_deep_free(ds_sig_list);
|
||||
p = get_dnssec_pkt(res, labels[i-1], LDNS_RR_TYPE_DS);
|
||||
(void) get_ds(p, labels[i-1], &ds_list, &ds_sig_list);
|
||||
|
||||
status = ldns_verify_denial(p, labels[i-1], LDNS_RR_TYPE_DS, &nsec_rrs, &nsec_rr_sigs);
|
||||
|
||||
if (verbosity >= 4) {
|
||||
printf("NSEC(3) Records to verify:\n");
|
||||
ldns_rr_list_print(stdout, nsec_rrs);
|
||||
printf("With signatures:\n");
|
||||
ldns_rr_list_print(stdout, nsec_rr_sigs);
|
||||
printf("correct keys:\n");
|
||||
ldns_rr_list_print(stdout, correct_key_list);
|
||||
}
|
||||
|
||||
if (status == LDNS_STATUS_OK) {
|
||||
if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) {
|
||||
fprintf(stdout, "%s ", TRUST);
|
||||
fprintf(stdout, "Existence denied: ");
|
||||
ldns_rdf_print(stdout, labels[i-1]);
|
||||
printf(" DS");
|
||||
fprintf(stdout, "\n");
|
||||
} else if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, correct_key_list, NULL)) == LDNS_STATUS_OK) {
|
||||
fprintf(stdout, "%s ", SELF);
|
||||
fprintf(stdout, "Existence denied: ");
|
||||
ldns_rdf_print(stdout, labels[i-1]);
|
||||
printf(" DS");
|
||||
fprintf(stdout, "\n");
|
||||
} else {
|
||||
result = 4;
|
||||
fprintf(stdout, "%s ", BOGUS);
|
||||
printf("Error verifying denial of existence for ");
|
||||
ldns_rdf_print(stdout, labels[i-1]);
|
||||
printf(" DS");
|
||||
printf(": %s\n", ldns_get_errorstr_by_id(st));
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
if (status == LDNS_STATUS_CRYPTO_NO_RRSIG) {
|
||||
printf(";; No DS for ");
|
||||
ldns_rdf_print(stdout, labels[i - 1]);
|
||||
} else {
|
||||
printf(BOGUS " Unable to verify denial of existence for ");
|
||||
ldns_rdf_print(stdout, labels[i - 1]);
|
||||
printf(" DS: %s\n", ldns_get_errorstr_by_id(status));
|
||||
}
|
||||
}
|
||||
if (verbosity >= 2) {
|
||||
printf(";; No ds record for delegation\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
ldns_rr_list_deep_free(ds_list);
|
||||
ldns_pkt_free(p);
|
||||
} else {
|
||||
/* if this is the last label, just verify the data and stop */
|
||||
p = get_dnssec_pkt(res, labels[i], t);
|
||||
(void) get_dnssec_rr(p, labels[i], t, &dataset, &key_sig_list);
|
||||
if (dataset && ldns_rr_list_rr_count(dataset) > 0) {
|
||||
if (key_sig_list && ldns_rr_list_rr_count(key_sig_list) > 0) {
|
||||
|
||||
/* If this is a wildcard, you must be able to deny exact match */
|
||||
if ((st = ldns_verify(dataset, key_sig_list, trusted_keys, NULL)) == LDNS_STATUS_OK) {
|
||||
fprintf(stdout, "%s ", TRUST);
|
||||
ldns_rr_list_print(stdout, dataset);
|
||||
} else if ((st = ldns_verify(dataset, key_sig_list, correct_key_list, NULL)) == LDNS_STATUS_OK) {
|
||||
fprintf(stdout, "%s ", SELF);
|
||||
ldns_rr_list_print(stdout, dataset);
|
||||
} else {
|
||||
result = 5;
|
||||
fprintf(stdout, "%s ", BOGUS);
|
||||
ldns_rr_list_print(stdout, dataset);
|
||||
printf(";; Error: %s\n", ldns_get_errorstr_by_id(st));
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "%s ", UNSIGNED);
|
||||
ldns_rr_list_print(stdout, dataset);
|
||||
}
|
||||
ldns_rr_list_deep_free(dataset);
|
||||
} else {
|
||||
status = ldns_verify_denial(p, name, t, &nsec_rrs, &nsec_rr_sigs);
|
||||
if (status == LDNS_STATUS_OK) {
|
||||
/* verify the nsec3 themselves*/
|
||||
if (verbosity >= 5) {
|
||||
printf("NSEC(3) Records to verify:\n");
|
||||
ldns_rr_list_print(stdout, nsec_rrs);
|
||||
printf("With signatures:\n");
|
||||
ldns_rr_list_print(stdout, nsec_rr_sigs);
|
||||
printf("correct keys:\n");
|
||||
ldns_rr_list_print(stdout, correct_key_list);
|
||||
/*
|
||||
printf("trusted keys at %p:\n", trusted_keys);
|
||||
ldns_rr_list_print(stdout, trusted_keys);
|
||||
*/ }
|
||||
|
||||
if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) {
|
||||
fprintf(stdout, "%s ", TRUST);
|
||||
fprintf(stdout, "Existence denied: ");
|
||||
ldns_rdf_print(stdout, name);
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf(" %s", descriptor->_name);
|
||||
} else {
|
||||
printf(" TYPE%u", t);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
} else if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, correct_key_list, NULL)) == LDNS_STATUS_OK) {
|
||||
fprintf(stdout, "%s ", SELF);
|
||||
fprintf(stdout, "Existence denied: ");
|
||||
ldns_rdf_print(stdout, name);
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf(" %s", descriptor->_name);
|
||||
} else {
|
||||
printf(" TYPE%u", t);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
} else {
|
||||
result = 6;
|
||||
fprintf(stdout, "%s ", BOGUS);
|
||||
printf("Error verifying denial of existence for ");
|
||||
ldns_rdf_print(stdout, name);
|
||||
printf(" type ");
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf("%s", descriptor->_name);
|
||||
} else {
|
||||
printf("TYPE%u", t);
|
||||
}
|
||||
printf(": %s\n", ldns_get_errorstr_by_id(st));
|
||||
}
|
||||
|
||||
ldns_rr_list_deep_free(nsec_rrs);
|
||||
ldns_rr_list_deep_free(nsec_rr_sigs);
|
||||
} else {
|
||||
/*
|
||||
*/
|
||||
if (status == LDNS_STATUS_CRYPTO_NO_RRSIG) {
|
||||
printf("%s ", UNSIGNED);
|
||||
printf("No data found for: ");
|
||||
ldns_rdf_print(stdout, name);
|
||||
printf(" type ");
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf("%s", descriptor->_name);
|
||||
} else {
|
||||
printf("TYPE%u", t);
|
||||
}
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(BOGUS " Unable to verify denial of existence for ");
|
||||
ldns_rdf_print(stdout, name);
|
||||
printf(" type ");
|
||||
if (descriptor && descriptor->_name) {
|
||||
printf("%s", descriptor->_name);
|
||||
} else {
|
||||
printf("TYPE%u", t);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
ldns_pkt_free(p);
|
||||
}
|
||||
|
||||
new_nss = NULL;
|
||||
ns_addr = NULL;
|
||||
ldns_rr_list_deep_free(key_list);
|
||||
key_list = NULL;
|
||||
ldns_rr_list_deep_free(key_sig_list);
|
||||
key_sig_list = NULL;
|
||||
ds_list = NULL;
|
||||
ldns_rr_list_deep_free(ds_sig_list);
|
||||
ds_sig_list = NULL;
|
||||
}
|
||||
printf(";;" SELF " self sig OK; " BOGUS " bogus; " TRUST " trusted; " UNSIGNED " unsigned\n");
|
||||
/* verbose mode?
|
||||
printf("Trusted keys:\n");
|
||||
ldns_rr_list_print(stdout, trusted_keys);
|
||||
printf("trusted dss:\n");
|
||||
ldns_rr_list_print(stdout, trusted_ds_rrs);
|
||||
*/
|
||||
|
||||
done:
|
||||
ldns_rr_list_deep_free(trusted_ds_rrs);
|
||||
ldns_rr_list_deep_free(correct_key_list);
|
||||
ldns_resolver_deep_free(res);
|
||||
if (labels) {
|
||||
for(i = 0 ; i < (ssize_t)labels_count + 2; i++) {
|
||||
ldns_rdf_deep_free(labels[i]);
|
||||
}
|
||||
LDNS_FREE(labels);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
261
zonemaster-ldns/ldns/drill/work.c
Normal file
261
zonemaster-ldns/ldns/drill/work.c
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* work.c
|
||||
* Where all the hard work is done
|
||||
* (c) 2005 NLnet Labs
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drill.h"
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
/**
|
||||
* Converts a hex string to binary data
|
||||
* len is the length of the string
|
||||
* buf is the buffer to store the result in
|
||||
* offset is the starting position in the result buffer
|
||||
*
|
||||
* This function returns the length of the result
|
||||
*/
|
||||
static size_t
|
||||
hexstr2bin(char *hexstr, int len, uint8_t *buf, size_t offset, size_t buf_len)
|
||||
{
|
||||
char c;
|
||||
int i;
|
||||
uint8_t int8 = 0;
|
||||
int sec = 0;
|
||||
size_t bufpos = 0;
|
||||
|
||||
if (len % 2 != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
c = hexstr[i];
|
||||
|
||||
/* case insensitive, skip spaces */
|
||||
if (c != ' ') {
|
||||
if (c >= '0' && c <= '9') {
|
||||
int8 += c & 0x0f;
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
int8 += (c & 0x0f) + 9;
|
||||
} else if (c >= 'A' && c <= 'Z') {
|
||||
int8 += (c & 0x0f) + 9;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sec == 0) {
|
||||
int8 = int8 << 4;
|
||||
sec = 1;
|
||||
} else {
|
||||
if (bufpos + offset + 1 <= buf_len) {
|
||||
buf[bufpos+offset] = int8;
|
||||
int8 = 0;
|
||||
sec = 0;
|
||||
bufpos++;
|
||||
} else {
|
||||
error("Buffer too small in hexstr2bin");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bufpos;
|
||||
}
|
||||
|
||||
static size_t
|
||||
packetbuffromfile(char *filename, uint8_t *wire)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
int c;
|
||||
|
||||
/* stat hack
|
||||
* 0 = normal
|
||||
* 1 = comment (skip to end of line)
|
||||
* 2 = unprintable character found, read binary data directly
|
||||
*/
|
||||
int state = 0;
|
||||
uint8_t *hexbuf = xmalloc(LDNS_MAX_PACKETLEN);
|
||||
int hexbufpos = 0;
|
||||
size_t wirelen;
|
||||
|
||||
if (strncmp(filename, "-", 2) == 0) {
|
||||
fp = stdin;
|
||||
} else {
|
||||
fp = fopen(filename, "r");
|
||||
}
|
||||
if (fp == NULL) {
|
||||
perror("Unable to open file for reading");
|
||||
xfree(hexbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*verbose("Opened %s\n", filename);*/
|
||||
|
||||
c = fgetc(fp);
|
||||
while (c != EOF && hexbufpos < LDNS_MAX_PACKETLEN) {
|
||||
if (state < 2 && !isascii(c)) {
|
||||
/*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/
|
||||
state = 2;
|
||||
}
|
||||
switch (state) {
|
||||
case 0:
|
||||
if ( (c >= '0' && c <= '9') ||
|
||||
(c >= 'a' && c <= 'f') ||
|
||||
(c >= 'A' && c <= 'F') )
|
||||
{
|
||||
hexbuf[hexbufpos] = (uint8_t) c;
|
||||
hexbufpos++;
|
||||
} else if (c == ';') {
|
||||
state = 1;
|
||||
} else if (c == ' ' || c == '\t' || c == '\n') {
|
||||
/* skip whitespace */
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (c == '\n' || c == EOF) {
|
||||
state = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
hexbuf[hexbufpos] = (uint8_t) c;
|
||||
hexbufpos++;
|
||||
break;
|
||||
}
|
||||
c = fgetc(fp);
|
||||
}
|
||||
|
||||
if (c == EOF) {
|
||||
/*
|
||||
if (have_drill_opt && drill_opt->verbose) {
|
||||
verbose("END OF FILE REACHED\n");
|
||||
if (state < 2) {
|
||||
verbose("read:\n");
|
||||
verbose("%s\n", hexbuf);
|
||||
} else {
|
||||
verbose("Not printing wire because it contains non ascii data\n");
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
if (hexbufpos >= LDNS_MAX_PACKETLEN) {
|
||||
/*verbose("packet size reached\n");*/
|
||||
}
|
||||
|
||||
/* lenient mode: length must be multiple of 2 */
|
||||
if (hexbufpos % 2 != 0) {
|
||||
hexbuf[hexbufpos] = (uint8_t) '0';
|
||||
hexbufpos++;
|
||||
}
|
||||
|
||||
if (state < 2) {
|
||||
wirelen = hexstr2bin((char *) hexbuf,
|
||||
hexbufpos,
|
||||
wire,
|
||||
0,
|
||||
LDNS_MAX_PACKETLEN);
|
||||
} else {
|
||||
memcpy(wire, hexbuf, (size_t) hexbufpos);
|
||||
wirelen = (size_t) hexbufpos;
|
||||
}
|
||||
if (fp != stdin) {
|
||||
fclose(fp);
|
||||
}
|
||||
xfree(hexbuf);
|
||||
return wirelen;
|
||||
}
|
||||
|
||||
ldns_buffer *
|
||||
read_hex_buffer(char *filename)
|
||||
{
|
||||
uint8_t *wire;
|
||||
size_t wiresize;
|
||||
ldns_buffer *result_buffer = NULL;
|
||||
|
||||
|
||||
wire = xmalloc(LDNS_MAX_PACKETLEN);
|
||||
|
||||
wiresize = packetbuffromfile(filename, wire);
|
||||
|
||||
result_buffer = LDNS_MALLOC(ldns_buffer);
|
||||
ldns_buffer_new_frm_data(result_buffer, wire, wiresize);
|
||||
ldns_buffer_set_position(result_buffer, ldns_buffer_capacity(result_buffer));
|
||||
xfree(wire);
|
||||
|
||||
return result_buffer;
|
||||
}
|
||||
|
||||
ldns_pkt *
|
||||
read_hex_pkt(char *filename)
|
||||
{
|
||||
uint8_t *wire;
|
||||
size_t wiresize;
|
||||
|
||||
ldns_pkt *pkt = NULL;
|
||||
|
||||
ldns_status status = LDNS_STATUS_ERR;
|
||||
|
||||
wire = xmalloc(LDNS_MAX_PACKETLEN);
|
||||
|
||||
wiresize = packetbuffromfile(filename, wire);
|
||||
|
||||
if (wiresize > 0) {
|
||||
status = ldns_wire2pkt(&pkt, wire, wiresize);
|
||||
}
|
||||
|
||||
xfree(wire);
|
||||
|
||||
if (status == LDNS_STATUS_OK) {
|
||||
return pkt;
|
||||
} else {
|
||||
fprintf(stderr, "Error parsing hex file: %s\n",
|
||||
ldns_get_errorstr_by_id(status));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dump_hex(const ldns_pkt *pkt, const char *filename)
|
||||
{
|
||||
uint8_t *wire = NULL;
|
||||
size_t size, i;
|
||||
FILE *fp;
|
||||
ldns_status status;
|
||||
|
||||
fp = fopen(filename, "w");
|
||||
|
||||
if (fp == NULL) {
|
||||
error("Unable to open %s for writing", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
status = ldns_pkt2wire(&wire, pkt, &size);
|
||||
|
||||
if (status != LDNS_STATUS_OK) {
|
||||
error("Unable to convert packet: error code %u", status);
|
||||
LDNS_FREE(wire);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(fp, "; 0");
|
||||
for (i = 1; i < 20; i++) {
|
||||
fprintf(fp, " %2u", (unsigned int) i);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, ";--");
|
||||
for (i = 1; i < 20; i++) {
|
||||
fprintf(fp, " --");
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
for (i = 0; i < size; i++) {
|
||||
if (i % 20 == 0 && i > 0) {
|
||||
fprintf(fp, "\t;\t%4u-%4u\n", (unsigned int) i-19, (unsigned int) i);
|
||||
}
|
||||
fprintf(fp, " %02x", (unsigned int)wire[i]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
fclose(fp);
|
||||
LDNS_FREE(wire);
|
||||
}
|
||||
Reference in New Issue
Block a user