ldns: Update vendor branch from 1.6.11 to 1.6.16 avalon/vendor/LDNS
authorJohn Marino <draco@marino.st>
Fri, 18 Oct 2013 20:40:13 +0000 (22:40 +0200)
committerJohn Marino <draco@marino.st>
Fri, 18 Oct 2013 22:02:50 +0000 (00:02 +0200)
52 files changed:
contrib/ldns/Changelog [deleted file]
contrib/ldns/README.snapshots [deleted file]
contrib/ldns/README.svn [deleted file]
contrib/ldns/buffer.c
contrib/ldns/compat/calloc.c [new file with mode: 0644]
contrib/ldns/compat/inet_ntop.c
contrib/ldns/compat/localtime_r.c [new file with mode: 0644]
contrib/ldns/dane.c [new file with mode: 0644]
contrib/ldns/dname.c
contrib/ldns/dnssec.c
contrib/ldns/dnssec_sign.c
contrib/ldns/dnssec_verify.c
contrib/ldns/dnssec_zone.c
contrib/ldns/drill/chasetrace.c
contrib/ldns/drill/dnssec.c
contrib/ldns/drill/drill.1 [deleted file]
contrib/ldns/drill/drill.c
contrib/ldns/drill/drill.h [new file with mode: 0644]
contrib/ldns/drill/drill_util.c
contrib/ldns/drill/drill_util.h
contrib/ldns/drill/securetrace.c
contrib/ldns/drill/work.c
contrib/ldns/duration.c [new file with mode: 0644]
contrib/ldns/error.c
contrib/ldns/higher.c
contrib/ldns/host2str.c
contrib/ldns/host2wire.c
contrib/ldns/keys.c
contrib/ldns/ldns/buffer.h
contrib/ldns/ldns/dane.h [new file with mode: 0644]
contrib/ldns/ldns/dname.h
contrib/ldns/ldns/dnssec.h
contrib/ldns/ldns/dnssec_verify.h
contrib/ldns/ldns/dnssec_zone.h
contrib/ldns/ldns/duration.h [new file with mode: 0644]
contrib/ldns/ldns/error.h
contrib/ldns/ldns/host2str.h
contrib/ldns/ldns/keys.h
contrib/ldns/ldns/rdata.h
contrib/ldns/ldns/resolver.h
contrib/ldns/ldns/rr.h
contrib/ldns/ldns/rr_functions.h
contrib/ldns/net.c
contrib/ldns/packet.c
contrib/ldns/parse.c
contrib/ldns/rbtree.c
contrib/ldns/resolver.c
contrib/ldns/rr.c
contrib/ldns/rr_functions.c
contrib/ldns/str2host.c
contrib/ldns/tsig.c
contrib/ldns/util.c

diff --git a/contrib/ldns/Changelog b/contrib/ldns/Changelog
deleted file mode 100644 (file)
index 240acde..0000000
+++ /dev/null
@@ -1,661 +0,0 @@
-1.6.11 2011-09-29
-       * bugfix #394: Fix socket leak on errors
-       * bugfix #392: Apex only and percentage checks for ldns-verify-zone 
-         (thanks Miek Gieben)
-       * bugfix #398: Allow NSEC RRSIGs before the NSEC3 in ldns-verify-zone
-       * Fix python site package path from sitelib to sitearch for pyldns.
-       * Fix python api to support python2 and python3 (thanks Karel Slany).
-       * bugfix #401: Correction of date/time functions algorithm and 
-         prevention of an infinite loop therein
-       * bugfix #402: Correct the minimum and maximum number of rdata fields
-         in TSIG. (thanks David Keeler)
-       * bugfix #403: Fix heap overflow (thanks David Keeler)
-       * bugfix #404: Make parsing APL strings more robust
-         (thanks David Keeler)
-       * bugfix #391: Complete library assessment to prevent assertion errors
-                 through ldns_rdf_size usage.
-       * Slightly more specific error messaging on wrong number of rdata
-         fields with the LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG and
-         LDNS_STATUS_MISSING_RDATA_FIELDS_KEY result codes.
-       * bugfix #406: More rigorous openssl result code handling to prevent
-         future crashes within openssl.
-       * Fix ldns_fetch_valid_domain_keys to search deeper than just one level
-          for a DNSKEY that signed a DS RR. (this function was used in the
-         check_dnssec_trace nagios module)
-       * bugfix #407: Canonicalize TSIG dnames and algorithm fields
-       * A new output specifier to accommodate configuration of what to show
-         in comment texts when converting host and/or wire-format data to
-         string. All conversion to string and printing functions have a new
-         version that have such a format specifier as an extra argument.
-         The default is changed so that only DNSKEY RR's are annotated with 
-         an comment show the Key Tag of the DNSKEY.
-       * Fixed the ldns resolver to not mark a nameserver unreachable when
-         edns0 is tried unsuccessfully with size 4096 (no return packet came),
-         but to still try TCP. A big UDP packet might have been corrupted by 
-         fragments dropping firewalls.
-       * Update of libdns.vim (thanks Miek Gieben)
-       * Added the ldnsx Python module to our contrib section, which adds even
-         more pythonisticism to the usage of ldns with  Python. (Many thanks 
-         to Christpher Olah and Paul Wouters)
-         The ldnsx module is automatically installed when --with-pyldns is
-         used with configuring, but may explicitly be excluded with the
-         --without-pyldnsx option to configure.
-       * bugfix #410: Fix clearing out temporary data on stack in sha2.c
-       * bugfix #411: Don't let empty non-terminal NSEC3s cause assertion failure.
-
-1.6.10 2011-05-31
-       * New example tool added: ldns-gen-zone.
-       * bugfix #359: Serial-arithmetic for the inception and expiration
-         fields of a RRSIG and correctly converting them to broken-out time
-         information.
-       * bugfix #364: Slight performance increase of ldns-verifyzone.
-       * bugfix #367: Fix to allow glue records with the same name as the
-         delegation.
-       * Fix ldns-verifyzone to allow NSEC3-less records for NS rrsets *and* 
-         glue when the zone is opt-out.
-       * bugfix #376: Adapt ldns_nsec3_salt, ldns_nsec3_iterations, 
-         ldns_nsec3_flags and ldns_nsec3_algorithm to work for NSEC3PARAMS too.
-       * pyldns memory leaks fixed by Bedrich Kosata (at the cost of a bit
-         performance)
-       * Better handling of reference variables in ldns_rr_new_frm_fp_l from
-         pyldns, with a very nice generator function by Bedrich Kosata.
-       * Decoupling of the rdfs in rrs in the python wrappers to enable
-         the python garbage collector by Bedrich Kosata.
-       * bugfix #380: Minimizing effect of discrepancies in sizeof(bool) at
-         build time and when used.
-       * bugfix #383: Fix detection of empty nonterminals of multiple labels.
-       * Fixed the ommission of rrsets in nsec(3)s and rrsigs to all occluded
-         names (in stead of just the ones that contain glue only) and all
-         occluded records on the delegation points (in stead of just the glue).
-       * Clarify the operation of ldns_dnssec_mark_glue and the usage of
-         ldns_dnssec_node_next_nonglue functions in the documentation.
-       * Added function ldns_dnssec_mark_and_get_glue as an real fast
-         alternative for ldns_zone_glue_rr_list.
-       * Fix parse buffer overflow for max length domain names.
-       * Fix Makefile for U in environment, since wrong U is more common than
-         deansification necessity.
-
-1.6.9  2011-03-16
-       * Fix creating NSEC(3) bitmaps: make array size 65536,
-         don't add doubles.
-       * Fix printout of escaped binary in TXT records.
-       * Parsing TXT records: don't skip starting whitespace that is quoted.
-       * bugfix #358: Check if memory was successfully allocated in
-         ldns_rdf2str().
-       * Added more memory allocation checks in host2str.c
-       * python wrapper for ldns_fetch_valid_domain_keys by Bedrich Kosata.
-       * fix to compile python wrapper with swig 2.0.2.
-       * Don't fallback to SHA-1 when creating NSEC3 hash with another
-         algorithm identifier, fail instead (no other algorithm identifiers
-         are assigned yet).
-
-1.6.8  2011-01-24
-       * Fix ldns zone, so that $TTL definition match RFC 2308.
-       * Fix lots of missing checks on allocation failures and parse of 
-         NSEC with many types and max parse length in hosts_frm_fp routine
-         and off by one in read_anchor_file routine (thanks Dan Kaminsky and
-         Justin Ferguson).
-       * bugfix #335: Drill: Print both SHA-1 and SHA-256 corresponding DS
-         records.
-       * Print correct WHEN in query packet (is not always 1-1-1970)
-       * ldns-test-edns: new example tool that detects EDNS support.
-       * fix ldns_resolver_send without openssl.
-       * bugfix #342: patch for support for more CERT key types (RFC4398).
-       * bugfix #351: fix udp_send hang if UDP checksum error.
-       * fix set_bit (from NSEC3 sign) patch from Jan Komissar.
-
-1.6.7  2010-11-08
-       * EXPERIMENTAL ecdsa implementation, please do not enable on real
-         servers.
-       * GOST code enabled by default (RFC 5933).
-       * bugfix #326: ignore whitespace between directives and their values.
-       * Header comment to advertise ldns_axfr_complete to check for
-         successfully completed zone transfers.
-       * read resolv.conf skips interface labels, e.g. %eth0.
-       * Fix drill verify NSEC3 denials.
-       * Use closesocket() on windows.
-       * Add ldns_get_signing_algorithm_by_name that understand aliases,
-         names changed to RFC names and aliases for compatibility added.
-       * bugfix: don't print final dot if the domain is relative.
-       * bugfix: resolver search continue when packet rcode != NOERROR.
-       * bugfix: resolver push all domains in search directive to list.
-       * bugfix: resolver search by default includes the root domain.
-       * bugfix: tcp read could fail on single octet recv.
-       * bugfix: read of RR in unknown syntax with missing fields.
-       * added ldns_pkt_tsig_sign_next() and ldns_pkt_tsig_verify_next()
-         to sign and verify TSIG RRs on subsequent messages
-         (section 4.4, RFC 2845, thanks to Michael Sheldon).
-       * bugfix: signer sigs nsecs with zsks only.
-       * bugfix #333: fix ldns_dname_absolute for name ending with backslash.
-
-1.6.6  2010-08-09
-       * Fix ldns_rr_clone to copy question rrs properly.
-       * Fix ldns_sign_zone(_nsec3) to clone the soa for the new zone.
-       * Fix ldns_wire2dname size check from reading 1 byte beyond buffer end.
-       * Fix ldns_wire2dname from reading 1 byte beyond end for pointer.
-       * Fix crash using GOST for particular platform configurations.
-       * extern C declarations used in the header file.
-       * Removed debug fprintf from resolver.c.
-       * ldns-signzone checks if public key file is for the right zone.
-       * NETLDNS, .NET port of ldns functionality, by Alex Nicoll, in contrib.
-       * Fix handling of comments in resolv.conf parse.
-       * GOST code enabled if SSL recent, RFC 5933.
-       * bugfix #317: segfault util.c ldns_init_random() fixed.
-       * Fix ldns_tsig_mac_new: allocate enough memory for the hash, fix use of
-         b64_pton_calculate_size.
-       * Fix ldns_dname_cat: size calculation and handling of realloc().
-       * Fix ldns_rr_pop_rdf: fix handling of realloc().
-       * Fix ldns-signzone for single type key scheme: sign whole zone if there
-         are only KSKs.
-       * Fix ldns_resolver: also close socket if AXFR failed (if you don't,
-          it would block subsequent transfers (thanks Roland van Rijswijk).
-        * Fix drill: allow for a secure trace if you use DS records as trust
-         anchors (thanks Jan Komissar).
-
-1.6.5  2010-06-15
-       * Catch \X where X is a digit as an error.
-       * Fix segfault when ip6 ldns resolver only has ip4 servers.
-       * Fix NSEC record after DNSKEY at zone apex not properly signed.
-       * Fix syntax error if last label too long and no dot at end of domain. 
-       * Fix parse of \# syntax with space for type LOC.
-       * Fix ldns_dname_absolute for escape sequences, fixes some parse errs.
-       * bugfix #297: linking ssl, bug due to patch submitted as #296.
-       * bugfix #299: added missing declarations to host2str.h
-       * ldns-compare-zones -s to not exclude SOA record from comparison.
-       * --disable-rpath fix
-       * fix ldns_pkt_empty(), reported by Alex Nicoll.
-       * fix ldns_resolver_new_frm_fp not ignore lines after a comment.
-       * python code for ldns_rr.new_question_frm_str()
-       * Fix ldns_dnssec_verify_denial: the signature selection routine.
-       * Type TALINK parsed (draft-ietf-dnsop-trust-history).
-       * bugfix #304: fixed dead loop in ldns_tcp_read_wire() and
-         ldns_tcp_read_wire_timeout().
-       * GOST support with correct algorithm numbers.  The plan is to make it
-         enabled if openssl support is detected, but it is disabled by
-         default in this release because the RFC is not ready.
-       * Fixed comment in rbtree.h about being first member and data ptr.
-       * Fixed possibly leak in case of out of memory in ldns_native2rdf...
-       * ldns_dname_is_wildcard added.
-       * Fixed: signatures over wildcards had the wrong labelcount.
-       * Fixed ldns_verify() inconsistent return values.
-       * Fixed ldns_resolver to copy and free tsig name, data and algorithm.
-       * Fixed ldns_resolver to push search onto searchlist.
-       * A ldns resolver now defaults to a non-recursive resolver that handles
-         the TC bit.
-       * ldns_resolver_print() prints more details.
-       * Fixed ldns_rdf2buffer_str_time(), which did not print timestamps
-         on 64bit systems.
-       * Make ldns_resolver_nameservers_randomize() more random.
-       * bugfix #310: POSIX specifies NULL second argument of gettimeofday.
-       * fix compiler warnings from llvm clang compiler.
-       * bugfix #309: ldns_pkt_clone did not clone the tsig_rr.
-       * Fix gentoo ebuild for drill, 'no m4 directory'.
-       * bugfix #313: drill trace on an empty nonterminal continuation.
-
-1.6.4  2010-01-20
-       * Imported pyldns contribution by Zdenek Vasicek and Karel Slany.
-         Changed its configure and Makefile to fit into ldns.
-         Added its dname_* methods to the rdf_* class (as is the ldns API).
-         Changed swig destroy of ldns_buffer class to ldns_buffer_free.
-         Declared ldns_pkt_all and ldns_pkt_all_noquestion so swig sees them.
-       * Bugfix: parse PTR target of .tomhendrikx.nl with error not crash.
-       * Bugfix: handle escaped characters in TXT rdata.
-       * bug292: no longer crash on malformed domain names where a label is
-         on position 255, which was a buffer overflow by one.
-       * Fix ldns_get_rr_list_hosts_frm_fp_l (strncpy to strlcpy change),
-         which fixes resolv.conf reading badly terminated string buffers.
-       * Fix ldns_pkt_set_random_id to be more random, and a little faster,
-         it did not do value 0 statistically correctly.
-       * Fix ldns_rdf2native_sockaddr_storage to set sockaddr type to zeroes,
-         for portability.
-       * bug295: nsec3-hash routine no longer case sensitive.
-       * bug298: drill failed nsec3 denial of existence proof.
-
-1.6.3  2009-12-04
-       * Bugfix: allow for unknown resource records in zonefile with rdlen=0.
-       * Bugfix: also mark an RR as question if it comes from the wire
-       * Bugfix: NSEC3 bitmap contained NSEC
-       * Bugfix: Inherit class when creating signatures
-
-1.6.2  2009-11-12
-       * Fix Makefile patch from Havard Eidnes, better install.sh usage.
-       * Fix parse error on SOA serial of 2910532839.
-         Fix print of ';' and readback of '\;' in names, also for '\\'.
-         Fix parse of '\(' and '\)' in names.  Also for file read. Also '\.'
-       * Fix signature creation when TTLs are different for RRs in RRset.
-       * bug273: fix so EDNS rdata is included in pkt to wire conversion.
-       * bug274: fix use of c++ keyword 'class' for RR class in the code.
-       * bug275: fix memory leak of packet edns rdata.
-       * Fix timeout procedure for TCP and AXFR on Solaris.
-       * Fix occasional NSEC bitmap bogus
-       * Fix rr comparing (was in reversed order since 1.6.0)
-       * bug278: fix parsing HINFO rdata (and other cases).
-       * Fix previous owner name: also pick up if owner name is @.
-       * RFC5702: enabled sha2 functions by default. This requires OpenSSL 0.9.8 or higher.
-      Reason for this default is the root to be signed with RSASHA256.
-       * Fix various LDNS RR parsing issues: IPSECKEY, WKS, NSAP, very long lines
-       * Fix: Make ldns_dname_is_subdomain case insensitive.
-       * Fix ldns-verify-zone so that address records at zone NS set are not considered glue
-               (Or glue records fall below delegation)
-    * Fix LOC RR altitude printing.
-       * Feature: Added period (e.g. '3m6d') support at explicit TTLs.
-    * Feature: DNSKEY rrset by default signed with minimal signatures
-               but -A option for ldns-signzone to sign it with all keys.
-               This makes the DNSKEY responses smaller for signed domains.
-
-1.6.1   2009-09-14
-       * --enable-gost : use the GOST algorithm (experimental).
-       * Added some missing options to drill manpage
-       * Some fixes to --without-ssl option
-       * Fixed quote parsing withing strings
-       * Bitmask fix in EDNS handling
-       * Fixed non-fqdn domain name completion for rdata field domain
-         names of length 1
-       * Fixed chain validation with SHA256 DS records
-
-1.6.0
-       Additions:
-       * Addition of an ldns-config script which gives cflags and libs
-         values, for use in configure scripts for applications that use
-         use ldns. Can be disabled with ./configure --disable-ldns-config
-       * Added direct sha1, sha256, and sha512 support in ldns.
-         With these functions, all NSEC3 functionality can still be
-         used, even if ldns is built without OpenSSL. Thanks to OpenBSD,
-         Steve Reid, and Aaron D. Gifford for the code.
-       * Added reading/writing support for the SPF Resource Record
-       * Base32 functions are now exported
-       Bugfixes:
-       * ldns_is_rrset did not go through the complete rrset, but
-         only compared the first two records. Thanks to Olafur
-         Gudmundsson for report and patch
-       * Fixed a small memory bug in ldns_rr_list_subtype_by_rdf(),
-         thanks to Marius Rieder for finding an patching this.
-       * --without-ssl should now work. Make sure that examples/ and
-         drill also get the --without-ssl flag on their configure, if
-         this is used.
-       * Some malloc() return value checks have been added
-       * NSEC3 creation has been improved wrt to empty nonterminals,
-         and opt-out.
-       * Fixed a bug in the parser when reading large NSEC3 salt
-         values.
-       * Made the allowed length for domain names on wire
-         and presentation format the same.
-       Example tools:
-       * ldns-key2ds can now also generate DS records for keys without
-         the SEP flag
-       * ldns-signzone now equalizes the TTL of the DNSKEY RRset (to
-         the first non-default DNSKEY TTL value it sees)
-       
-1.5.1
-       Example tools:
-       * ldns-signzone was broken in 1.5.0 for multiple keys, this
-          has been repaired
-
-       Build system:
-        * Removed a small erroneous output warning in
-          examples/configure and drill/configure
-
-1.5.0
-       Bug fixes:
-       * fixed a possible memory overflow in the RR parser
-       * build flag fix for Sun Studio
-       * fixed a building race condition in the copying of header
-         files
-       * EDNS0 extended rcode; the correct assembled code number
-         is now printed (still in the EDNS0 field, though)
-       * ldns_pkt_rr no longer leaks memory (in fact, it no longer
-         copies anything all)
-
-       API addition:
-       * ldns_key now has support for 'external' data, in which
-         case the OpenSSL EVP structures are not used;
-         ldns_key_set_external_key() and ldns_key_external_key()
-       * added ldns_key_get_file_base_name() which creates a 
-         'default' filename base string for key storage, of the
-         form "K<zone>+<algorithm>+<keytag>"
-       * the ldns_dnssec_* family of structures now have deep_free()
-         functions, which also free the ldns_rr's contained in them
-       * there is now an ldns_match_wildcard() function, which checks
-         whether a domain name matches a wildcard name
-       * ldns_sign_public has been split up; this resulted in the
-         addition of ldns_create_empty_rrsig() and
-         ldns_sign_public_buffer()
-
-       Examples:
-       * ldns-signzone can now automatically add DNSKEY records when
-         using an OpenSSL engine, as it already did when using key
-         files
-       * added new example tool: ldns-nsec3-hash
-       * ldns-dpa can now filter on specific query name and types
-       * ldnsd has fixes for the zone name, a fix for the return
-          value of recvfrom(), and an memory initialization fix
-          (Thanks to Colm MacCárthaigh for the patch)
-        * Fixed memory leaks in ldnsd
-
-
-
-1.4.1
-       Bug fixes:
-       * fixed a build issue where ldns lib existence was done too early
-       * removed unnecessary check for pcap.h
-       * NSEC3 optout flag now correctly printed in string output
-       * inttypes.h moved to configured inclusion
-       * fixed NSEC3 type bitmaps for empty nonterminals and unsigned
-         delegations 
-
-       API addition:
-       * for that last fix, we added a new function
-         ldns_dname_add_from() that can clone parts of a dname
-       
-1.4.0
-       Bug fixes:
-       * sig chase return code fix (patch from Rafael Justo, bug id 189)
-       * rdata.c memory leaks on error and allocation checks fixed (patch
-         from Shane Kerr, bug id 188)
-       * zone.c memory leaks on error and allocation checks fixed (patch
-       from Shane Kerr, bug id 189)
-       * ldns-zplit output and error messages fixed (patch from Shane Kerr,
-         bug id 190)
-       * Fixed potential buffer overflow in ldns_str2rdf_dname
-       * Signing code no longer signs delegation NS rrsets
-       * Some minor configure/makefile updates
-       * Fixed a bug in the randomness initialization
-       * Fixed a bug in the reading of resolv.conf
-       * Fixed a bug concerning whitespace in zone data (with patch from Ondrej
-         Sury, bug 213)
-       * Fixed a small fallback problem in axfr client code
-       
-       API CHANGES:
-       * added 2str convenience functions:
-               - ldns_rr_type2str
-               - ldns_rr_class2str
-               - ldns_rr_type2buffer_str
-               - ldns_rr_class2buffer_str
-       * buffer2str() is now called ldns_buffer2str
-       * base32 and base64 function names are now also prepended with ldns_
-       * ldns_rr_new_frm_str() now returns an error on missing RDATA fields.
-         Since you cannot read QUESTION section RRs with this anymore,
-         there is now a function called ldns_rr_new_question_frm_str()
-
-       LIBRARY FEATURES:
-       * DS RRs string representation now add bubblebabble in a comment
-         (patch from Jakob Schlyter)
-       * DLV RR type added
-       * TCP fallback system has been improved
-       * HMAC-SHA256 TSIG support has been added.
-       * TTLS are now correcly set in NSEC(3) records when signing zones
-       
-       EXAMPLE TOOLS:
-       * New example: ldns-revoke to revoke DNSKEYs according to RFC5011
-       * ldns-testpkts has been fixed and updated
-       * ldns-signzone now has the option to not add the DNSKEY
-       * ldns-signzone now has an (full zone only) opt-out option for
-                       NSEC3
-       * ldns-keygen can create HMAC-SHA1 and HMAC-SHA256 symmetric keys
-       * ldns-walk output has been fixed
-       * ldns-compare-zones has been fixed, and now has an option
-         to show all differences (-a)
-       * ldns-read-zone now has an option to print DNSSEC records only
-
-1.3
-       Base library:
-
-       * Added a new family of functions based around ldns_dnssec_zone,
-       which is a new structure that keeps a zone sorted through an
-       rbtree and links signatures and NSEC(3) records directly to their
-       RRset. These functions all start with ldns_dnssec_
-
-       * ldns_zone_sign and ldns_zone_sign_nsec3 are now deprecated, but
-       have been changed to internally use the new
-       ldns_dnssec_zone_sign(_nsec3)
-
-       * Moved some ldns_buffer functions inline, so a clean rebuild of
-       applications relying on those is needed (otherwise you'll get
-       linker errors)
-       * ldns_dname_label now returns one extra (zero)
-       byte, so it can be seen as an fqdn.
-       * NSEC3 type code update for signing algorithms.
-       * DSA key generation of DNSKEY RRs fixed (one byte too small).
-
-       * Added support for RSA/SHA256 and RSA/SHA512, as specified in
-       draft-ietf-dnsext-dnssec-rsasha256-04. The typecodes are not
-       final, and this feature is not enabled by default. It can be
-       enabled at compilation time with the flag --with-sha2
-
-       * Added 2wire_canonical family of functions that lowercase dnames
-       in rdata fields in resource records of the types in the list in
-       rfc3597
-
-       * Added base32 conversion functions.
-
-       * Fixed DSA RRSIG conversion when calling OpenSSL
-
-       Drill:
-
-       * Chase output is completely different, it shows, in ascii, the
-       relations in the trust hierarchy.
-
-       Examples:
-       * Added ldns-verify-zone, that can verify the internal DNSSEC records
-       of a signed BIND-style zone file
-
-       * ldns-keygen now takes an -a argument specifying the algorithm,
-       instead of -R or -D. -a list show a list of supported algorithms
-
-       * ldns-keygen now defaults to the exponent RSA_F4 instead of RSA_3
-       for RSA key generation
-
-       * ldns-signzone now has support for HSMs
-       * ldns-signzone uses the new ldns_dnssec_ structures and functions
-       which improves its speed, and output; RRSIGS are now placed
-       directly after their RRset, NSEC(3) records directly after the
-       name they handle
-
-       Contrib:
-       * new contrib/ dir with user contributions
-       * added compilation script for solaris (thanks to Jakob Schlyter)
-       
-28 Nov 2007 1.2.2:
-       * Added support for HMAC-MD5 keys in generator
-       * Added a new example tool (written by Ondrej Sury): ldns-compare-zones
-       * ldns-keygen now checks key sizes for rfc conformancy
-       * ldns-signzone outputs SSL error if present
-       * Fixed manpages (thanks to Ondrej Sury)
-       * Fixed Makefile for -j <x>
-       * Fixed a $ORIGIN error when reading zones
-       * Fixed another off-by-one error
-
-03 Oct 2007 1.2.1:
-       * Fixed an offset error in rr comparison
-       * Fixed ldns-read-zone exit code
-       * Added check for availability of SHA256 hashing algorithm
-       * Fixed ldns-key2ds -2 argument
-       * Fixed $ORIGIN bug in .key files
-       * Output algorithms as an integer instead of their mnemonic
-       * Fixed a memory leak in dnssec code when SHA256 is not available
-       * Updated fedora .spec file
-
-11 Apr 2007 1.2.0:
-       * canonicalization of rdata in DNSSEC functions now adheres to the
-          rr type list in rfc3597, not rfc4035, which will be updated
-         (see http://www.ops.ietf.org/lists/namedroppers/namedroppers.2007/msg00183.html)
-       * ldns-walk now support dnames with maximum label length
-       * ldnsd now takes an extra argument containing the address to listen on
-       * signing no longer signs every rrset with KSK's, but only the DNSKEY rrset
-       * ported to Solaris 10
-       * added ldns_send_buffer() function
-       * added ldns-testpkts fake packet server
-       * added ldns-notify to send NOTIFY packets
-       * ldns-dpa can now accurately calculate the number of matches per
-         second
-       * libtool is now used for compilation too (still gcc, but not directly)
-       * Bugfixes:
-               - TSIG signing buffer size
-               - resolv.conf reading (comments)
-               - dname comparison off by one error
-               - typo in keyfetchers output file name fixed (a . too much)
-               - fixed zone file parser when comments contain ( or )
-               - fixed LOC RR type
-               - fixed CERT RR type
-
-       Drill:
-       * drill prints error on failed axfr.
-       * drill now accepts mangled packets with -f
-       * old -c option (use tcp) changed to -t
-       * -c option to specify alternative resolv.conf file added
-       * feedback of signature chase improved
-       * chaser now stops at root when no trusted keys are found
-         instead of looping forever trying to find the DS for .
-       * Fixed bugs:
-               - wildcard on multiple labels signature verification
-               - error in -f packet writing for malformed packets
-               - made KSK check more resilient
-
-7 Jul 2006: 1.1.0: ldns-team
-       * Added tutorials and an introduction to the documentation
-       * Added include/ and lib/ dirs so that you can compile against ldns
-         without installing ldns on your system
-       * Makefile updates
-       * Starting usage of assert throughout the library to catch illegal calls
-       * Solaris 9 testing was carried out. Ldns now compiles on that
-         platform; some gnuism were identified and fixed.
-       * The ldns_zone structure was stress tested. The current setup
-        (ie. just a list of rrs) can scale to zone file in order of
-         megabytes. Sorting such zone is still difficult.
-       * Reading multiline b64 encoded rdata works.
-       * OpenSSL was made optional, configure --without-ssl.
-         Ofcourse all dnssec/tsig related functions are disabled
-       * Building of examples and drill now happens with the same
-         defines as the building of ldns itself.
-       * Preliminary sha-256 support was added. Currently is your
-         OpenSSL supports it, it is supported in the DS creation.
-       * ldns_resolver_search was implemented
-       * Fixed a lot of bugs
-
-       Drill:
-       * -r was killed in favor of -o <header bit mnemonic> which 
-         allows for a header bits setting (and maybe more in the
-         future)
-       * DNSSEC is never automaticaly set, even when you query
-         for DNSKEY/RRSIG or DS.
-       * Implement a crude RTT check, it now distinguishes between
-         reachable and unreachable.
-        * A form of secure tracing was added
-        * Secure Chasing has been improved
-       * -x does a reverse lookup for the given IP address
-       
-       Examples:
-       * ldns-dpa was added to the examples - this is the Dns Packet
-         Analyzer tool.
-       * ldnsd - as very, very simple nameserver impl.
-       * ldns-zsplit - split zones for parrallel signing
-       * ldns-zcat - cat split zones back together
-        * ldns-keyfetcher - Fetches DNSKEY records with a few (non-strong, 
-         non-DNSSEC) anti-spoofing techniques.
-       * ldns-walk - 'Walks' a DNSSEC signed zone
-       * Added an all-static target to the makefile so you can use examples
-         without installing the library
-       * When building in the source tree or in a direct subdirectory of
-         the build dir, configure does not need --with-ldns=../ anymore
-
-       Code:
-       * All networking code was moved to net.c
-       * rdata.c: added asserts to the rdf set/get functions
-       * const keyword was added to pointer arguments that 
-         aren't changed
-
-       API:
-       Changed:
-       * renamed ldns/dns.h to ldns/ldns.h
-       * ldns_rr_new_frm_str() is extented with an extra variable which
-         in common use may be NULL. This trickles through to:
-          o ldns_rr_new_frm_fp
-         o ldns_rr_new_frm_fp_l
-         Which also get an extra variable
-         Also the function has been changed to return a status message.
-         The compiled RR is returned in the first argument.
-       * ldns_zone_new_frm_fp_l()  and ldns_zone_new_frm_fp() are
-          changed to return a status msg.
-       * ldns_key_new_frm_fp is changed to return ldns_status and
-         the actual key list in the first argument
-       * ldns_rdata_new_frm_fp[_l]() are changed to return a status.
-         the rdf is return in the first argument
-        * ldns_resolver_new_frm_fp: same treatment: return status and 
-         the new resolver in the first argument
-       * ldns_pkt_query_new_frm_str(): same: return status and the
-         packet in the first arg
-       * tsig.h: internal used functions are now static:
-         ldns_digest_name and ldns_tsig_mac_new
-       * ldns_key_rr2ds has an extra argument to specify the hash to
-         use.
-       * ldns_pkt_rcode() is renamed to ldns_pkt_get_rcode, ldns_pkt_rcode
-         is now the rcode type, like ldns_pkt_opcode
-       New:
-       * ldns_resolver_searchlist_count: return the searchlist counter
-       * ldns_zone_sort: Sort a zone
-       * ldns_bgsend(): background send, returns a socket.
-       * ldns_pkt_empty(): check is a packet is empty
-       * ldns_rr_list_pop_rr_list(): pop multiple rr's from another rr_list
-       * ldns_rr_list_push_rr_list(): push multiple rr's to an rr_list
-        * ldns_rr_list_compare(): compare 2 ldns_rr_lists
-       * ldns_pkt_push_rr_list: rr_list equiv for rr
-       * ldns_pkt_safe_push_rr_list: rr_list equiv for rr
-       Removed:
-       * ldns_resolver_bgsend(): was not used in 1.0.0 and is not used now
-       * ldns_udp_server_connect(): was faulty and isn't really part of
-         the core ldns idea any how.
-       * ldns_rr_list_insert_rr(): obsoleted, because not used.
-       * char *_when was removed from the ldns_pkt structure
-
-18 Oct 2005: 1.0.0: ldns-team
-       * Commited a patch from Håkan Olsson
-       * Added UPDATE support (Jakob Schlyter and Håkan Olsson)
-       * License change: ldns is now BSD licensed
-       * ldns now depends on SSL
-       * Networking code cleanup, added (some) server udp/tcp support
-       * A zone type is introduced. Currently this is a list
-         of RRs, so it will not scale well.
-       * [beta] Zonefile parsing was added
-       * [tools] Drill was added to ldns - see drill/
-       * [tools] experimental signer was added
-       * [building] better check for ssl
-       * [building] major revision of build system
-       * [building] added rpm .spec in packaging/ (thanks to Paul Wouters)
-       * [building] A lot of cleanup in the build scripts (thanks to Jakob Schlyter
-       and Paul Wouters)
-
-28 Jul 2005: 0.70: ldns-team
-       * [func] ldns_pkt_get_section now returns copies from the rrlists
-         in the packet. This can be freed by the user program
-       * [code] added ldns_ prefixes to function from util.h
-       * [inst] removed documentation from default make install
-       * Usual fixes in documentation and code
-
-20 Jun 2005: 0.66: ldns-team
-       Rel. Focus: drill-pre2 uses some functions which are
-       not in 0.65
-       * dnssec_cd bit function was added
-       * Zone infrastructure was added
-       * Usual fixes in documentation and code
-
-13 Jun 2005: 0.65: ldns-team
-       * Repository is online at: 
-         http://www.nlnetlabs.nl/ldns/svn/
-       * Apply reference copying throuhgout ldns, except in 2 
-         places in the ldns_resolver structure (._domain and
-        ._nameservers)
-       * Usual array of bugfixes
-       * Documentation added
-       * keygen.c added as an example for DNSSEC programming
-
-23 May 2005: 0.60: ldns-team
-       * Removed config.h from the header installed files
-         (you're not supposed to include that in a libary)
-       * Further tweaking
-         - DNSSEC signing/verification works
-         - Assorted bug fixes and tweaks (memory management) 
-
-May 2005: 0.50: ldns-team
-       * First usable release
-       * Basic DNS functionality works
-       * DNSSEC validation works
diff --git a/contrib/ldns/README.snapshots b/contrib/ldns/README.snapshots
deleted file mode 100644 (file)
index 891fcca..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-ldns - snapshot releases
-
-Snapshot releases are not official released. They can be released to
-interested parties for development.
-
-Snapshots can be recognized from the date in the the tar file name.
-
-They should not be used for packaging in distributions.
diff --git a/contrib/ldns/README.svn b/contrib/ldns/README.svn
deleted file mode 100644 (file)
index 10f7cb4..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-
-# The ldns subversion repository can found at:
-# www.nlnetlabs.nl/ldns/svn/
-
-# small list of commands to build all on a linux system
-# libtoolize is needed for most other targets
-
-# on Solaris, and other systems that may not have
-# the default 'automake' and 'aclocal' script aliases,
-# the correct versions may need to be set. On those
-# systems, the 'autoreconf' line should be changed to:
-# AUTOMAKE=automake-1.10 ACLOCAL=aclocal-1.10 autoreconf
-# (and these systems probably need gmake instead of make)
-
-# older versions of libtoolize do not support --install
-# so you might need to remove that (with newer versions
-# it is needed)
-libtoolize -c --install
-autoreconf --install
-./configure
-make
-make doc  # needs doxygen for the html pages
-(cd examples && autoreconf && ./configure && make)
-(cd drill && autoreconf && ./configure && make)
-(cd pcat && autoreconf && ./configure && make)
-(cd examples/nsd-test && autoreconf && ./configure && make)
index 5a6b0ba..fc6c17e 100644 (file)
@@ -140,7 +140,8 @@ ldns_buffer_free(ldns_buffer *buffer)
                return;
        }
 
-       LDNS_FREE(buffer->_data);
+       if (!buffer->_fixed)
+               LDNS_FREE(buffer->_data);
 
        LDNS_FREE(buffer);
 }
diff --git a/contrib/ldns/compat/calloc.c b/contrib/ldns/compat/calloc.c
new file mode 100644 (file)
index 0000000..c86b956
--- /dev/null
@@ -0,0 +1,24 @@
+/* Just a replacement, if the original malloc is not
+   GNU-compliant. See autoconf documentation. */
+
+#if HAVE_CONFIG_H
+#include <ldns/config.h>
+#endif
+
+void *calloc();
+
+#if !HAVE_BZERO && HAVE_MEMSET
+# define bzero(buf, bytes)     ((void) memset (buf, 0, bytes))
+#endif
+
+void *
+calloc(size_t num, size_t size)
+{
+       void *new = malloc(num * size);
+       if (!new) {
+               return NULL;
+       }
+       bzero(new, num * size);
+       return new;
+}
+
index 57509c7..52197d0 100644 (file)
@@ -135,7 +135,9 @@ inet_ntop6(const u_char *src, char *dst, size_t size)
        for (i = 0; i < IN6ADDRSZ; i++)
                words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
        best.base = -1;
+       best.len = 0;
        cur.base = -1;
+       cur.len = 0;
        for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
                if (words[i] == 0) {
                        if (cur.base == -1)
diff --git a/contrib/ldns/compat/localtime_r.c b/contrib/ldns/compat/localtime_r.c
new file mode 100644 (file)
index 0000000..017c6e4
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef HAVE_CONFIG_H
+#include <ldns/config.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+struct tm *localtime_r(const time_t *timep, struct tm *result)
+{
+       /* no thread safety. */
+       *result = *localtime(timep);
+       return result;
+}
diff --git a/contrib/ldns/dane.c b/contrib/ldns/dane.c
new file mode 100644 (file)
index 0000000..793005d
--- /dev/null
@@ -0,0 +1,742 @@
+/*
+ * Verify or create TLS authentication with DANE (RFC6698)
+ *
+ * (c) NLnetLabs 2012
+ *
+ * See the file LICENSE for the license.
+ *
+ */
+
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+#include <ldns/dane.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#ifdef HAVE_SSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+#endif
+
+ldns_status
+ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name,
+               uint16_t port, ldns_dane_transport transport)
+{
+       char buf[LDNS_MAX_DOMAINLEN];
+       size_t s;
+
+       assert(tlsa_owner != NULL);
+       assert(name != NULL);
+       assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME);
+
+       s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port);
+       buf[0] = (char)(s - 1);
+
+       switch(transport) {
+       case LDNS_DANE_TRANSPORT_TCP:
+               s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp");
+               break;
+       
+       case LDNS_DANE_TRANSPORT_UDP:
+               s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp");
+               break;
+
+       case LDNS_DANE_TRANSPORT_SCTP:
+               s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp");
+               break;
+       
+       default:
+               return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT;
+       }
+       if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) {
+               return LDNS_STATUS_DOMAINNAME_OVERFLOW;
+       }
+       memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name));
+       *tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
+                       s + ldns_rdf_size(name), buf);
+       if (*tlsa_owner == NULL) {
+               return LDNS_STATUS_MEM_ERR;
+       }
+       return LDNS_STATUS_OK;
+}
+
+
+#ifdef HAVE_SSL
+ldns_status
+ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
+               ldns_tlsa_selector      selector,
+               ldns_tlsa_matching_type matching_type)
+{
+       unsigned char* buf = NULL;
+       size_t len;
+
+       X509_PUBKEY* xpubkey;
+       EVP_PKEY* epubkey;
+
+       unsigned char* digest;
+
+       assert(rdf != NULL);
+       assert(cert != NULL);
+
+       switch(selector) {
+       case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE:
+
+               len = (size_t)i2d_X509(cert, &buf);
+               break;
+
+       case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO:
+
+#ifndef S_SPLINT_S
+               xpubkey = X509_get_X509_PUBKEY(cert);
+#endif
+               if (! xpubkey) {
+                       return LDNS_STATUS_SSL_ERR;
+               }
+               epubkey = X509_PUBKEY_get(xpubkey);
+               if (! epubkey) {
+                       return LDNS_STATUS_SSL_ERR;
+               }
+               len = (size_t)i2d_PUBKEY(epubkey, &buf);
+               break;
+       
+       default:
+               return LDNS_STATUS_DANE_UNKNOWN_SELECTOR;
+       }
+
+       switch(matching_type) {
+       case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED:
+
+               *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf);
+               
+               return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
+               break;
+       
+       case LDNS_TLSA_MATCHING_TYPE_SHA256:
+
+               digest = LDNS_XMALLOC(unsigned char, SHA256_DIGEST_LENGTH);
+               if (digest == NULL) {
+                       LDNS_FREE(buf);
+                       return LDNS_STATUS_MEM_ERR;
+               }
+               (void) ldns_sha256(buf, (unsigned int)len, digest);
+               *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH,
+                               digest);
+               LDNS_FREE(buf);
+
+               return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
+               break;
+
+       case LDNS_TLSA_MATCHING_TYPE_SHA512:
+
+               digest = LDNS_XMALLOC(unsigned char, SHA512_DIGEST_LENGTH);
+               if (digest == NULL) {
+                       LDNS_FREE(buf);
+                       return LDNS_STATUS_MEM_ERR;
+               }
+               (void) ldns_sha512(buf, (unsigned int)len, digest);
+               *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA512_DIGEST_LENGTH,
+                               digest);
+               LDNS_FREE(buf);
+
+               return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
+               break;
+       
+       default:
+               LDNS_FREE(buf);
+               return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE;
+       }
+}
+
+
+/* Ordinary PKIX validation of cert (with extra_certs to help)
+ * against the CA's in store
+ */
+static ldns_status
+ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs,
+               X509_STORE* store)
+{
+       X509_STORE_CTX* vrfy_ctx;
+       ldns_status s;
+
+       if (! store) {
+               return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+       }
+       vrfy_ctx = X509_STORE_CTX_new();
+       if (! vrfy_ctx) {
+
+               return LDNS_STATUS_SSL_ERR;
+
+       } else if (X509_STORE_CTX_init(vrfy_ctx, store,
+                               cert, extra_certs) != 1) {
+               s = LDNS_STATUS_SSL_ERR;
+
+       } else if (X509_verify_cert(vrfy_ctx) == 1) {
+
+               s = LDNS_STATUS_OK;
+
+       } else {
+               s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+       }
+       X509_STORE_CTX_free(vrfy_ctx);
+       return s;
+}
+
+
+/* Orinary PKIX validation of cert (with extra_certs to help)
+ * against the CA's in store, but also return the validation chain.
+ */
+static ldns_status
+ldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert,
+               STACK_OF(X509)* extra_certs, X509_STORE* store)
+{
+       ldns_status s;
+       X509_STORE* empty_store = NULL;
+       X509_STORE_CTX* vrfy_ctx;
+
+       assert(chain != NULL);
+
+       if (! store) {
+               store = empty_store = X509_STORE_new();
+       }
+       s = LDNS_STATUS_SSL_ERR;
+       vrfy_ctx = X509_STORE_CTX_new();
+       if (! vrfy_ctx) {
+
+               goto exit_free_empty_store;
+
+       } else if (X509_STORE_CTX_init(vrfy_ctx, store,
+                                       cert, extra_certs) != 1) {
+               goto exit_free_vrfy_ctx;
+
+       } else if (X509_verify_cert(vrfy_ctx) == 1) {
+
+               s = LDNS_STATUS_OK;
+
+       } else {
+               s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+       }
+       *chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
+       if (! *chain) {
+               s = LDNS_STATUS_SSL_ERR;
+       }
+
+exit_free_vrfy_ctx:
+       X509_STORE_CTX_free(vrfy_ctx);
+
+exit_free_empty_store:
+       if (empty_store) {
+               X509_STORE_free(empty_store);
+       }
+       return s;
+}
+
+
+/* Return the validation chain that can be build out of cert, with extra_certs.
+ */
+static ldns_status
+ldns_dane_pkix_get_chain(STACK_OF(X509)** chain,
+               X509* cert, STACK_OF(X509)* extra_certs)
+{
+       ldns_status s;
+       X509_STORE* empty_store = NULL;
+       X509_STORE_CTX* vrfy_ctx;
+
+       assert(chain != NULL);
+
+       empty_store = X509_STORE_new();
+       s = LDNS_STATUS_SSL_ERR;
+       vrfy_ctx = X509_STORE_CTX_new();
+       if (! vrfy_ctx) {
+
+               goto exit_free_empty_store;
+
+       } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
+                                       cert, extra_certs) != 1) {
+               goto exit_free_vrfy_ctx;
+       }
+       (void) X509_verify_cert(vrfy_ctx);
+       *chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
+       if (! *chain) {
+               s = LDNS_STATUS_SSL_ERR;
+       } else {
+               s = LDNS_STATUS_OK;
+       }
+exit_free_vrfy_ctx:
+       X509_STORE_CTX_free(vrfy_ctx);
+
+exit_free_empty_store:
+       X509_STORE_free(empty_store);
+       return s;
+}
+
+
+/* Pop n+1 certs and return the last popped.
+ */
+static ldns_status
+ldns_dane_get_nth_cert_from_validation_chain(
+               X509** cert, STACK_OF(X509)* chain, int n, bool ca)
+{
+       if (n >= sk_X509_num(chain) || n < 0) {
+               return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE;
+       }
+       *cert = sk_X509_pop(chain);
+       while (n-- > 0) {
+               X509_free(*cert);
+               *cert = sk_X509_pop(chain);
+       }
+       if (ca && ! X509_check_ca(*cert)) {
+               return LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
+       }
+       return LDNS_STATUS_OK;
+}
+
+
+/* Create validation chain with cert and extra_certs and returns the last
+ * self-signed (if present).
+ */
+static ldns_status
+ldns_dane_pkix_get_last_self_signed(X509** out_cert,
+               X509* cert, STACK_OF(X509)* extra_certs)
+{
+       ldns_status s;
+       X509_STORE* empty_store = NULL;
+       X509_STORE_CTX* vrfy_ctx;
+
+       assert(out_cert != NULL);
+
+       empty_store = X509_STORE_new();
+       s = LDNS_STATUS_SSL_ERR;
+       vrfy_ctx = X509_STORE_CTX_new();
+       if (! vrfy_ctx) {
+               goto exit_free_empty_store;
+
+       } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
+                                       cert, extra_certs) != 1) {
+               goto exit_free_vrfy_ctx;
+
+       }
+       (void) X509_verify_cert(vrfy_ctx);
+       if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
+           vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){
+
+               *out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx);
+               s = LDNS_STATUS_OK;
+       } else {
+               s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR;
+       }
+exit_free_vrfy_ctx:
+       X509_STORE_CTX_free(vrfy_ctx);
+
+exit_free_empty_store:
+       X509_STORE_free(empty_store);
+       return s;
+}
+
+
+ldns_status
+ldns_dane_select_certificate(X509** selected_cert,
+               X509* cert, STACK_OF(X509)* extra_certs,
+               X509_STORE* pkix_validation_store,
+               ldns_tlsa_certificate_usage cert_usage, int offset)
+{
+       ldns_status s;
+       STACK_OF(X509)* pkix_validation_chain = NULL;
+
+       assert(selected_cert != NULL);
+       assert(cert != NULL);
+
+       /* With PKIX validation explicitely turned off (pkix_validation_store
+        *  == NULL), treat the "CA constraint" and "Service certificate
+        * constraint" the same as "Trust anchor assertion" and "Domain issued
+        * certificate" respectively.
+        */
+       if (pkix_validation_store == NULL) {
+               switch (cert_usage) {
+
+               case LDNS_TLSA_USAGE_CA_CONSTRAINT:
+
+                       cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION;
+                       break;
+
+               case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
+
+                       cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE;
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       /* Now what to do with each Certificate usage...
+        */
+       switch (cert_usage) {
+
+       case LDNS_TLSA_USAGE_CA_CONSTRAINT:
+
+               s = ldns_dane_pkix_validate_and_get_chain(
+                               &pkix_validation_chain,
+                               cert, extra_certs,
+                               pkix_validation_store);
+               if (! pkix_validation_chain) {
+                       return s;
+               }
+               if (s == LDNS_STATUS_OK) {
+                       if (offset == -1) {
+                               offset = 0;
+                       }
+                       s = ldns_dane_get_nth_cert_from_validation_chain(
+                                       selected_cert, pkix_validation_chain,
+                                       offset, true);
+               }
+               sk_X509_pop_free(pkix_validation_chain, X509_free);
+               return s;
+               break;
+
+
+       case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
+
+               *selected_cert = cert;
+               return ldns_dane_pkix_validate(cert, extra_certs,
+                               pkix_validation_store);
+               break;
+
+
+       case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
+
+               if (offset == -1) {
+                       s = ldns_dane_pkix_get_last_self_signed(
+                                       selected_cert, cert, extra_certs);
+                       return s;
+               } else {
+                       s = ldns_dane_pkix_get_chain(
+                                       &pkix_validation_chain,
+                                       cert, extra_certs);
+                       if (s == LDNS_STATUS_OK) {
+                               s =
+                               ldns_dane_get_nth_cert_from_validation_chain(
+                                       selected_cert, pkix_validation_chain,
+                                       offset, false);
+                       } else if (! pkix_validation_chain) {
+                               return s;
+                       }
+                       sk_X509_pop_free(pkix_validation_chain, X509_free);
+                       return s;
+               }
+               break;
+
+
+       case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
+
+               *selected_cert = cert;
+               return LDNS_STATUS_OK;
+               break;
+       
+       default:
+               return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
+               break;
+       }
+}
+
+
+ldns_status
+ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
+               ldns_tlsa_certificate_usage certificate_usage,
+               ldns_tlsa_selector          selector,
+               ldns_tlsa_matching_type     matching_type,
+               X509* cert)
+{
+       ldns_rdf* rdf;
+       ldns_status s;
+
+       assert(tlsa != NULL);
+       assert(cert != NULL);
+
+       /* create rr */
+       *tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA);
+       if (*tlsa == NULL) {
+               return LDNS_STATUS_MEM_ERR;
+       }
+
+       rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
+                       (uint8_t)certificate_usage);
+       if (rdf == NULL) {
+               goto memerror;
+       }
+       (void) ldns_rr_set_rdf(*tlsa, rdf, 0);
+
+       rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector);
+       if (rdf == NULL) {
+               goto memerror;
+       }
+       (void) ldns_rr_set_rdf(*tlsa, rdf, 1);
+
+       rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type);
+       if (rdf == NULL) {
+               goto memerror;
+       }
+       (void) ldns_rr_set_rdf(*tlsa, rdf, 2);
+
+       s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type);
+       if (s == LDNS_STATUS_OK) {
+               (void) ldns_rr_set_rdf(*tlsa, rdf, 3);
+               return LDNS_STATUS_OK;
+       }
+       ldns_rr_free(*tlsa);
+       *tlsa = NULL;
+       return s;
+
+memerror:
+       ldns_rr_free(*tlsa);
+       *tlsa = NULL;
+       return LDNS_STATUS_MEM_ERR;
+}
+
+
+/* Return tlsas that actually are TLSA resource records with known values
+ * for the Certificate usage, Selector and Matching type rdata fields.
+ */
+static ldns_rr_list*
+ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas)
+{
+       size_t i;
+       ldns_rr_list* r = ldns_rr_list_new();
+       ldns_rr* tlsa_rr;
+
+       if (! r) {
+               return NULL;
+       }
+       for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
+               tlsa_rr = ldns_rr_list_rr(tlsas, i);
+               if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA &&
+                   ldns_rr_rd_count(tlsa_rr) == 4 &&
+                   ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 &&
+                   ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 &&
+                   ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) {
+
+                       if (! ldns_rr_list_push_rr(r, tlsa_rr)) {
+                               ldns_rr_list_free(r);
+                               return NULL;
+                       }
+               }
+       }
+       return r;
+}
+
+
+/* Return whether cert/selector/matching_type matches data.
+ */
+static ldns_status
+ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector,
+               ldns_tlsa_matching_type matching_type, ldns_rdf* data)
+{
+       ldns_status s;
+       ldns_rdf* match_data;
+
+       s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type);
+       if (s == LDNS_STATUS_OK) {
+               if (ldns_rdf_compare(data, match_data) != 0) {
+                       s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
+               }
+               ldns_rdf_free(match_data);
+       }
+       return s;
+}
+
+
+/* Return whether any certificate from the chain with selector/matching_type
+ * matches data.
+ * ca should be true if the certificate has to be a CA certificate too.
+ */
+static ldns_status
+ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain,
+               ldns_tlsa_selector      selector,
+               ldns_tlsa_matching_type matching_type,
+               ldns_rdf* data, bool ca)
+{
+       ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
+       size_t n, i;
+       X509* cert;
+
+       n = (size_t)sk_X509_num(chain);
+       for (i = 0; i < n; i++) {
+               cert = sk_X509_pop(chain);
+               if (! cert) {
+                       s = LDNS_STATUS_SSL_ERR;
+                       break;
+               }
+               s = ldns_dane_match_cert_with_data(cert,
+                               selector, matching_type, data);
+               if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) {
+                       s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
+               }
+               X509_free(cert);
+               if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) {
+                       break;
+               }
+               /* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
+                * try to match the next certificate
+                */
+       }
+       return s;
+}
+
+
+ldns_status
+ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
+               X509* cert, STACK_OF(X509)* extra_certs,
+               X509_STORE* pkix_validation_store)
+{
+       ldns_status s;
+
+       STACK_OF(X509)* pkix_validation_chain = NULL;
+
+       ldns_tlsa_certificate_usage cert_usage;
+       ldns_tlsa_selector          selector;
+       ldns_tlsa_matching_type     matching_type;
+       ldns_rdf*                   data;
+
+       if (! tlsa_rr) {
+               /* No TLSA, so regular PKIX validation
+                */
+               return ldns_dane_pkix_validate(cert, extra_certs,
+                               pkix_validation_store);
+       }
+       cert_usage    = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0));
+       selector      = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1));
+       matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2));
+       data          =                      ldns_rr_rdf(tlsa_rr, 3) ;
+
+       switch (cert_usage) {
+       case LDNS_TLSA_USAGE_CA_CONSTRAINT:
+               s = ldns_dane_pkix_validate_and_get_chain(
+                               &pkix_validation_chain, 
+                               cert, extra_certs,
+                               pkix_validation_store);
+               if (! pkix_validation_chain) {
+                       return s;
+               }
+               if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
+                       /*
+                        * NO PKIX validation. We still try to match *any*
+                        * certificate from the chain, so we return
+                        * TLSA errors over PKIX errors.
+                        *
+                        * i.e. When the TLSA matches no certificate, we return
+                        * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE
+                        */
+                       s = ldns_dane_match_any_cert_with_data(
+                                       pkix_validation_chain,
+                                       selector, matching_type, data, true);
+
+                       if (s == LDNS_STATUS_OK) {
+                               /* A TLSA record did match a cert from the
+                                * chain, thus the error is failed PKIX
+                                * validation.
+                                */
+                               s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+                       }
+
+               } else if (s == LDNS_STATUS_OK) { 
+                       /* PKIX validated, does the TLSA match too? */
+
+                       s = ldns_dane_match_any_cert_with_data(
+                                       pkix_validation_chain,
+                                       selector, matching_type, data, true);
+               }
+               sk_X509_pop_free(pkix_validation_chain, X509_free);
+               return s;
+               break;
+
+       case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
+               s = ldns_dane_match_cert_with_data(cert,
+                               selector, matching_type, data);
+
+               if (s == LDNS_STATUS_OK) {
+                       return ldns_dane_pkix_validate(cert, extra_certs,
+                                       pkix_validation_store);
+               }
+               return s;
+               break;
+
+       case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
+               s = ldns_dane_pkix_get_chain(&pkix_validation_chain,
+                               cert, extra_certs);
+
+               if (s == LDNS_STATUS_OK) {
+                       s = ldns_dane_match_any_cert_with_data(
+                                       pkix_validation_chain,
+                                       selector, matching_type, data, false);
+
+               } else if (! pkix_validation_chain) {
+                       return s;
+               }
+               sk_X509_pop_free(pkix_validation_chain, X509_free);
+               return s;
+               break;
+
+       case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
+               return ldns_dane_match_cert_with_data(cert,
+                               selector, matching_type, data);
+               break;
+
+       default:
+               break;
+       }
+       return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
+}
+
+
+ldns_status
+ldns_dane_verify(ldns_rr_list* tlsas,
+               X509* cert, STACK_OF(X509)* extra_certs,
+               X509_STORE* pkix_validation_store)
+{
+       size_t i;
+       ldns_rr* tlsa_rr;
+       ldns_status s = LDNS_STATUS_OK, ps;
+
+       assert(cert != NULL);
+
+       if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) {
+               tlsas = ldns_dane_filter_unusable_records(tlsas);
+               if (! tlsas) {
+                       return LDNS_STATUS_MEM_ERR;
+               }
+       }
+       if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) {
+               /* No TLSA's, so regular PKIX validation
+                */
+               return ldns_dane_pkix_validate(cert, extra_certs,
+                               pkix_validation_store);
+       } else {
+               for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
+                       tlsa_rr = ldns_rr_list_rr(tlsas, i);
+                       ps = s;
+                       s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs,
+                                       pkix_validation_store);
+
+                       if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH &&
+                           s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
+
+                               /* which would be LDNS_STATUS_OK (match)
+                                * or some fatal error preventing use from
+                                * trying the next TLSA record.
+                                */
+                               break;
+                       }
+                       s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE
+                                               * over   TLSA_DID_NOT_MATCH
+                                               */
+               }
+               ldns_rr_list_free(tlsas);
+       }
+       return s;
+}
+#endif /* HAVE_SSL */
index 0e63ef2..55aba5d 100644 (file)
 #include <arpa/inet.h>
 #endif
 
+/* Returns whether the last label in the name is a root label (a empty label).
+ * Note that it is not enough to just test the last character to be 0,
+ * because it may be part of the last label itself.
+ */
+static bool
+ldns_dname_last_label_is_root_label(const ldns_rdf* dname)
+{
+       size_t src_pos;
+       size_t len = 0;
+
+       for (src_pos = 0; src_pos < ldns_rdf_size(dname); src_pos += len + 1) {
+               len = ldns_rdf_data(dname)[src_pos];
+       }
+       assert(src_pos == ldns_rdf_size(dname));
+
+       return src_pos > 0 && len == 0;
+}
+
 ldns_rdf *
 ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2)
 {
@@ -47,7 +65,7 @@ ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2)
         * rd, by reducing the size with 1
         */
        left_size = ldns_rdf_size(rd1);
-       if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) {
+       if (ldns_dname_last_label_is_root_label(rd1)) {
                left_size--;
        }
 
@@ -84,12 +102,9 @@ ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2)
         * rd, by reducing the size with 1
         */
        left_size = ldns_rdf_size(rd1);
-       if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) {
+       if (ldns_dname_last_label_is_root_label(rd1)) {
                left_size--;
        }
-        if(left_size == 0) {
-                return LDNS_STATUS_OK;
-        }
 
        size = left_size + ldns_rdf_size(rd2);
        newd = LDNS_XREALLOC(ldns_rdf_data(rd1), uint8_t, size);
@@ -105,36 +120,39 @@ ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2)
        return LDNS_STATUS_OK;
 }
 
-ldns_rdf *
-ldns_dname_reverse(const ldns_rdf *d)
+ldns_rdf*
+ldns_dname_reverse(const ldns_rdf *dname)
 {
-       ldns_rdf *new;
-       ldns_rdf *tmp;
-       ldns_rdf *d_tmp;
-       ldns_status status;
-
-       d_tmp = ldns_rdf_clone(d);
-
-       new = ldns_dname_new_frm_str(".");
-        if(!new)
-                return NULL;
-
-       while(ldns_dname_label_count(d_tmp) > 0) {
-               tmp = ldns_dname_label(d_tmp, 0);
-               status = ldns_dname_cat(tmp, new);
-                if(status != LDNS_STATUS_OK) {
-                        ldns_rdf_deep_free(new);
-                       ldns_rdf_deep_free(d_tmp);
-                        return NULL;
-                }
-               ldns_rdf_deep_free(new);
-               new = tmp;
-               tmp = ldns_dname_left_chop(d_tmp);
-               ldns_rdf_deep_free(d_tmp);
-               d_tmp = tmp;
+       size_t rd_size;
+       uint8_t* buf;
+       ldns_rdf* new;
+       size_t src_pos;
+       size_t len ;
+
+       assert(ldns_rdf_get_type(dname) == LDNS_RDF_TYPE_DNAME);
+       
+       rd_size = ldns_rdf_size(dname);
+       buf = LDNS_XMALLOC(uint8_t, rd_size);
+       if (! buf) {
+               return NULL;
+       }
+       new = ldns_rdf_new(LDNS_RDF_TYPE_DNAME, rd_size, buf);
+       if (! new) {
+               LDNS_FREE(buf);
+               return NULL;
+       }
+       
+       /* If dname ends in a root label, the reverse should too.
+        */
+       if (ldns_dname_last_label_is_root_label(dname)) {
+               buf[rd_size - 1] = 0;
+               rd_size -= 1;
+       }
+       for (src_pos = 0; src_pos < rd_size; src_pos += len + 1) {
+               len = ldns_rdf_data(dname)[src_pos];
+               memcpy(&buf[rd_size - src_pos - len - 1],
+                               &ldns_rdf_data(dname)[src_pos], len + 1);
        }
-       ldns_rdf_deep_free(d_tmp);
-
        return new;
 }
 
@@ -522,6 +540,18 @@ ldns_dname_str_absolute(const char *dname_str)
         return 0;
 }
 
+bool
+ldns_dname_absolute(const ldns_rdf *rdf)
+{
+       char *str = ldns_rdf2str(rdf);
+       if (str) {
+               bool r = ldns_dname_str_absolute(str);
+               LDNS_FREE(str);
+               return r;
+       }
+       return false;
+}
+
 ldns_rdf *
 ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos)
 {
@@ -530,6 +560,7 @@ ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos)
        uint16_t len;
        ldns_rdf *tmpnew;
        size_t s;
+       uint8_t *data;
 
        if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_DNAME) {
                return NULL;
@@ -543,19 +574,19 @@ ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos)
        while ((len > 0) && src_pos < s) {
                if (labelcnt == labelpos) {
                        /* found our label */
-                       tmpnew = LDNS_MALLOC(ldns_rdf);
-                       if (!tmpnew) {
+                       data = LDNS_XMALLOC(uint8_t, len + 2);
+                       if (!data) {
                                return NULL;
                        }
-                       tmpnew->_type = LDNS_RDF_TYPE_DNAME;
-                       tmpnew->_data = LDNS_XMALLOC(uint8_t, len + 2);
-                       if (!tmpnew->_data) {
-                               LDNS_FREE(tmpnew);
+                       memcpy(data, ldns_rdf_data(rdf) + src_pos, len + 1);
+                       data[len + 2 - 1] = 0;
+
+                       tmpnew = ldns_rdf_new( LDNS_RDF_TYPE_DNAME
+                                            , len + 2, data);
+                       if (!tmpnew) {
+                               LDNS_FREE(data);
                                return NULL;
                        }
-                       memset(tmpnew->_data, 0, len + 2);
-                       memcpy(tmpnew->_data, ldns_rdf_data(rdf) + src_pos, len + 1);
-                       tmpnew->_size = len + 2;
                        return tmpnew;
                }
                src_pos++;
index b36e3f3..684d171 100644 (file)
@@ -105,7 +105,6 @@ ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname,
        uint8_t *salt;
 
        ldns_rdf *sname, *hashed_sname, *tmp;
-       ldns_rr *ce;
        bool flag;
 
        bool exact_match_found;
@@ -117,7 +116,6 @@ ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname,
        size_t nsec_i;
        ldns_rr *nsec;
        ldns_rdf *result = NULL;
-       qtype = qtype;
 
        if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
                return NULL;
@@ -131,7 +129,6 @@ ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname,
 
        sname = ldns_rdf_clone(qname);
 
-       ce = NULL;
        flag = false;
 
        zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
@@ -535,17 +532,18 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
                ldns_rr_free(ds);
                return NULL;
 #endif
-#ifdef USE_ECDSA
-               /* Make similar ``not implemented'' construct as above when 
-                  draft-hoffman-dnssec-ecdsa-04 becomes a standard
-                */
        case LDNS_SHA384:
+#ifdef USE_ECDSA
                digest = LDNS_XMALLOC(uint8_t, SHA384_DIGEST_LENGTH);
                if (!digest) {
                        ldns_rr_free(ds);
                        return NULL;
                }
                 break;
+#else
+               /* not implemented */
+               ldns_rr_free(ds);
+               return NULL;
 #endif
        }
 
@@ -638,8 +636,8 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
                ldns_rr_push_rdf(ds, tmp);
 #endif
                break;
-#ifdef USE_ECDSA
        case LDNS_SHA384:
+#ifdef USE_ECDSA
                (void) SHA384((unsigned char *) ldns_buffer_begin(data_buf),
                                 (unsigned int) ldns_buffer_position(data_buf),
                                 (unsigned char *) digest);
@@ -647,8 +645,8 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
                                            SHA384_DIGEST_LENGTH,
                                            digest);
                ldns_rr_push_rdf(ds, tmp);
-               break;
 #endif
+               break;
        }
 
        LDNS_FREE(digest);
@@ -745,7 +743,6 @@ ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
                memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1);
                cur_data_size += cur_window_max + 3;
        }
-
        bitmap_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC,
                                                                cur_data_size,
                                                                data);
@@ -841,8 +838,6 @@ ldns_dnssec_create_nsec3(ldns_dnssec_name *from,
        ldns_status status;
        int on_delegation_point;
 
-       flags = flags;
-
        if (!from) {
                return NULL;
        }
@@ -1158,12 +1153,15 @@ ldns_create_nsec3(ldns_rdf *cur_owner,
                                                                 salt_length,
                                                                 salt);
        status = ldns_dname_cat(hashed_owner, cur_zone);
-        if(status != LDNS_STATUS_OK)
+        if(status != LDNS_STATUS_OK) {
+               ldns_rdf_deep_free(hashed_owner);
                 return NULL;
-
+       }
        nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3);
-        if(!nsec)
+        if(!nsec) {
+               ldns_rdf_deep_free(hashed_owner);
                 return NULL;
+       }
        ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3);
        ldns_rr_set_owner(nsec, hashed_owner);
 
@@ -1420,9 +1418,11 @@ ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name)
 
 #ifdef HAVE_SSL
 /* sig may be null - if so look in the packet */
+
 ldns_status
-ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o,
-                        ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys)
+ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 
+               ldns_rr_list *k, ldns_rr_list *s, 
+               time_t check_time, ldns_rr_list *good_keys)
 {
        ldns_rr_list *rrset;
        ldns_rr_list *sigs;
@@ -1445,8 +1445,9 @@ ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o,
                sigs = s;
        } else {
                /* otherwise get them from the packet */
-               sigs = ldns_pkt_rr_list_by_name_and_type(p, o, LDNS_RR_TYPE_RRSIG,
-                                                                         LDNS_SECTION_ANY_NOQUESTION);
+               sigs = ldns_pkt_rr_list_by_name_and_type(p, o,
+                               LDNS_RR_TYPE_RRSIG,
+                               LDNS_SECTION_ANY_NOQUESTION);
                if (!sigs) {
                        /* no sigs */
                        return LDNS_STATUS_ERR;
@@ -1459,25 +1460,34 @@ ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o,
         */
        t_netorder = htons(t); /* rdf are in network order! */
        /* a type identifier is a 16-bit number, so the size is 2 bytes */
-       rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE,
-                                        2,
-                                        &t_netorder);
-       sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
+       rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2, &t_netorder);
 
-       rrset = ldns_pkt_rr_list_by_name_and_type(p,
-                                                                         o,
-                                                                         t,
-                                                                         LDNS_SECTION_ANY_NOQUESTION);
-
-       if (!rrset) {
+       sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
+       ldns_rdf_free(rdf_t);
+       if (! sigs_covered) {
+               if (! s) {
+                       ldns_rr_list_deep_free(sigs);
+               }
                return LDNS_STATUS_ERR;
        }
+       ldns_rr_list_deep_free(sigs_covered);
 
-       if (!sigs_covered) {
+       rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t,
+                       LDNS_SECTION_ANY_NOQUESTION);
+       if (!rrset) {
+               if (! s) {
+                       ldns_rr_list_deep_free(sigs);
+               }
                return LDNS_STATUS_ERR;
        }
+       return ldns_verify_time(rrset, sigs, k, check_time, good_keys);
+}
 
-       return ldns_verify(rrset, sigs, k, good_keys);
+ldns_status
+ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 
+               ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys)
+{
+       return ldns_pkt_verify_time(p, t, o, k, s, ldns_time(NULL), good_keys);
 }
 #endif /* HAVE_SSL */
 
@@ -1561,34 +1571,34 @@ ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted)
 }
 
 int
-ldns_dnssec_default_add_to_signatures(ldns_rr *sig, void *n)
+ldns_dnssec_default_add_to_signatures( ATTR_UNUSED(ldns_rr *sig)
+                                    , ATTR_UNUSED(void *n)
+                                    )
 {
-       sig = sig;
-       n = n;
        return LDNS_SIGNATURE_LEAVE_ADD_NEW;
 }
 
 int
-ldns_dnssec_default_leave_signatures(ldns_rr *sig, void *n)
+ldns_dnssec_default_leave_signatures( ATTR_UNUSED(ldns_rr *sig)
+                                   , ATTR_UNUSED(void *n)
+                                   )
 {
-       sig = sig;
-       n = n;
        return LDNS_SIGNATURE_LEAVE_NO_ADD;
 }
 
 int
-ldns_dnssec_default_delete_signatures(ldns_rr *sig, void *n)
+ldns_dnssec_default_delete_signatures( ATTR_UNUSED(ldns_rr *sig)
+                                    , ATTR_UNUSED(void *n)
+                                    )
 {
-       sig = sig;
-       n = n;
        return LDNS_SIGNATURE_REMOVE_NO_ADD;
 }
 
 int
-ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n)
+ldns_dnssec_default_replace_signatures( ATTR_UNUSED(ldns_rr *sig)
+                                     , ATTR_UNUSED(void *n)
+                                     )
 {
-       sig = sig;
-       n = n;
        return LDNS_SIGNATURE_REMOVE_ADD_NEW;
 }
 
index 8e65d22..f2f9d9d 100644 (file)
@@ -28,6 +28,7 @@ ldns_create_empty_rrsig(ldns_rr_list *rrset,
        time_t now;
        ldns_rr *current_sig;
        uint8_t label_count;
+       ldns_rdf *signame;
 
        label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset,
                                                           0)));
@@ -57,9 +58,11 @@ ldns_create_empty_rrsig(ldns_rr_list *rrset,
                   ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
                                         orig_ttl));
        /* the signers name */
+       signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key));
+       ldns_dname2canonical(signame);
        (void)ldns_rr_rrsig_set_signame(
                        current_sig,
-                       ldns_rdf_clone(ldns_key_pubkey_owner(current_key)));
+                       signame);
        /* label count - get it from the first rr in the rr_list */
        (void)ldns_rr_rrsig_set_labels(
                        current_sig,
@@ -257,6 +260,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
                                ldns_buffer_free(sign_buf);
                                /* ERROR */
                                ldns_rr_list_deep_free(rrset_clone);
+                               ldns_rr_free(current_sig);
+                               ldns_rr_list_deep_free(signatures);
                                return NULL;
                        }
 
@@ -265,6 +270,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
                            != LDNS_STATUS_OK) {
                                ldns_buffer_free(sign_buf);
                                ldns_rr_list_deep_free(rrset_clone);
+                               ldns_rr_free(current_sig);
+                               ldns_rr_list_deep_free(signatures);
                                return NULL;
                        }
 
@@ -273,6 +280,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
                        if (!b64rdf) {
                                /* signing went wrong */
                                ldns_rr_list_deep_free(rrset_clone);
+                               ldns_rr_free(current_sig);
+                               ldns_rr_list_deep_free(signatures);
                                return NULL;
                        }
 
@@ -478,10 +487,7 @@ ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
                                   (unsigned char*)ldns_buffer_begin(b64sig),
                                   &siglen, key);
        if (result != 1) {
-               return NULL;
-       }
-
-       if (result != 1) {
+               ldns_buffer_free(b64sig);
                return NULL;
        }
 
@@ -856,16 +862,14 @@ ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone,
                                   ldns_rbtree_next(current_name_node));
        }
        if (result != LDNS_STATUS_OK) {
+               ldns_rr_list_free(nsec3_list);
                return result;
        }
 
        ldns_rr_list_sort_nsec3(nsec3_list);
        result = ldns_dnssec_chain_nsec3_list(nsec3_list);
-       if (result != LDNS_STATUS_OK) {
-               return result;
-       }
-
        ldns_rr_list_free(nsec3_list);
+
        return result;
 }
 
@@ -885,10 +889,11 @@ ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
 #endif /* HAVE_SSL */
 
 ldns_dnssec_rrs *
-ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures,
-                                               ldns_key_list *key_list,
-                                               int (*func)(ldns_rr *, void *),
-                                               void *arg)
+ldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures
+                            , ATTR_UNUSED(ldns_key_list *key_list)
+                            , int (*func)(ldns_rr *, void *)
+                            , void *arg
+                            )
 {
        ldns_dnssec_rrs *base_rrs = signatures;
        ldns_dnssec_rrs *cur_rr = base_rrs;
@@ -898,8 +903,6 @@ ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures,
        uint16_t keytag;
        size_t i;
 
-       key_list = key_list;
-
        if (!cur_rr) {
                switch(func(NULL, arg)) {
                case LDNS_SIGNATURE_LEAVE_ADD_NEW:
@@ -1021,12 +1024,13 @@ ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list)
 }
 
 ldns_status
-ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone,
-                               ldns_rr_list *new_rrs,
-                               ldns_key_list *key_list,
-                               int (*func)(ldns_rr *, void*),
-                               void *arg,
-                              int flags)
+ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone
+                                 , ldns_rr_list *new_rrs
+                                 , ldns_key_list *key_list
+                                 , int (*func)(ldns_rr *, void*)
+                                 , void *arg
+                                 , int flags
+                                 )
 {
        ldns_status result = LDNS_STATUS_OK;
 
@@ -1044,12 +1048,11 @@ ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone,
        int on_delegation_point = 0; /* handle partially occluded names */
 
        ldns_rr_list *pubkey_list = ldns_rr_list_new();
-       zone = zone;
-       new_rrs = new_rrs;
-       key_list = key_list;
        for (i = 0; i<ldns_key_list_key_count(key_list); i++) {
-               ldns_rr_list_push_rr(pubkey_list,
-                                                ldns_key2rr(ldns_key_list_key(key_list, i)));
+               ldns_rr_list_push_rr( pubkey_list
+                                   , ldns_key2rr(ldns_key_list_key(
+                                                       key_list, i))
+                                   );
        }
        /* TODO: callback to see is list should be signed */
        /* TODO: remove 'old' signatures from signature list */
@@ -1110,9 +1113,11 @@ ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone,
                                                        cur_rrset->signatures = ldns_dnssec_rrs_new();
                                                        cur_rrset->signatures->rr =
                                                                ldns_rr_list_rr(siglist, i);
+                                               }
+                                               if (new_rrs) {
                                                        ldns_rr_list_push_rr(new_rrs,
-                                                                                        ldns_rr_list_rr(siglist,
-                                                                                                                 i));
+                                                                                                ldns_rr_list_rr(siglist,
+                                                                                                                         i));
                                                }
                                        }
                                        ldns_rr_list_free(siglist);
@@ -1144,8 +1149,10 @@ ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone,
                                        cur_name->nsec_signatures = ldns_dnssec_rrs_new();
                                        cur_name->nsec_signatures->rr =
                                                ldns_rr_list_rr(siglist, i);
+                               }
+                               if (new_rrs) {
                                        ldns_rr_list_push_rr(new_rrs,
-                                                                        ldns_rr_list_rr(siglist, i));
+                                                                ldns_rr_list_rr(siglist, i));
                                }
                        }
 
@@ -1276,8 +1283,9 @@ ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone,
                                                                         salt_length,
                                                                         salt);
                                /* always set bit 7 of the flags to zero, according to
-                                * rfc5155 section 11 */
-                               ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 7, 0);
+                                * rfc5155 section 11. The bits are counted from right to left,
+                                * so bit 7 in rfc5155 is bit 0 in ldns */
+                               ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0);
                                result = ldns_dnssec_zone_add_rr(zone, nsec3param);
                                if (result != LDNS_STATUS_OK) {
                                        return result;
index 4e51df7..d435eed 100644 (file)
@@ -285,9 +285,11 @@ ldns_dnssec_build_data_chain(ldns_resolver *res,
        ldns_rr_class c = 0;
 
        bool other_rrset = false;
-       
+
        ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new();
 
+       assert(pkt != NULL);
+
        if (!ldns_dnssec_pkt_has_rrsigs(pkt)) {
                /* hmm. no dnssec data in the packet. go up to try and deny
                 * DS? */
@@ -402,15 +404,16 @@ ldns_dnssec_build_data_chain(ldns_resolver *res,
        if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
                key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7);
        }
-
        if (!key_name) {
+               if (signatures) {
+                       ldns_rr_list_deep_free(signatures);
+               }
                return ldns_dnssec_build_data_chain_nokeyname(res,
                                                              qflags,
                                                              orig_rr,
                                                              rrset,
                                                              new_chain);
        }
-
        if (type != LDNS_RR_TYPE_DNSKEY) {
                ldns_dnssec_build_data_chain_dnskey(res,
                                                    qflags,
@@ -419,7 +422,7 @@ ldns_dnssec_build_data_chain(ldns_resolver *res,
                                                    new_chain,
                                                    key_name,
                                                    c
-                                                   );
+                                                  );
        } else {
                ldns_dnssec_build_data_chain_other(res,
                                                   qflags,
@@ -427,13 +430,11 @@ ldns_dnssec_build_data_chain(ldns_resolver *res,
                                                   key_name,
                                                   c,
                                                   dss
-                                                   
-                                                   );
+                                                 );
        }
        if (signatures) {
                ldns_rr_list_deep_free(signatures);
        }
-
        return new_chain;
 }
 
@@ -509,7 +510,7 @@ ldns_dnssec_trust_tree_print_sm_fmt(FILE *out,
        
        if (!sibmap) {
                treedepth = ldns_dnssec_trust_tree_depth(tree);
-               sibmap = malloc(treedepth);
+               sibmap = LDNS_XMALLOC(uint8_t, treedepth);
                 if(!sibmap)
                         return; /* mem err */
                memset(sibmap, 0, treedepth);
@@ -623,7 +624,7 @@ ldns_dnssec_trust_tree_print_sm_fmt(FILE *out,
        }
        
        if (mapset) {
-               free(sibmap);
+               LDNS_FREE(sibmap);
        }
 }
 
@@ -688,7 +689,11 @@ ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
 
 /* if rr is null, take the first from the rrset */
 ldns_dnssec_trust_tree *
-ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
+ldns_dnssec_derive_trust_tree_time(
+               ldns_dnssec_data_chain *data_chain, 
+               ldns_rr *rr, 
+               time_t check_time
+               )
 {
        ldns_rr_list *cur_rrset;
        ldns_rr_list *cur_sigs;
@@ -752,28 +757,31 @@ ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
                                        }
                                        /* option 1 */
                                        if (data_chain->parent) {
-                                               ldns_dnssec_derive_trust_tree_normal_rrset(
+                                               ldns_dnssec_derive_trust_tree_normal_rrset_time(
                                                    new_tree,
                                                    data_chain,
-                                                   cur_sig_rr);
+                                                   cur_sig_rr,
+                                                   check_time);
                                        }
 
                                        /* option 2 */
-                                       ldns_dnssec_derive_trust_tree_dnskey_rrset(
+                                       ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
                                            new_tree,
                                            data_chain,
                                            cur_rr,
-                                           cur_sig_rr);
+                                           cur_sig_rr,
+                                           check_time);
                                }
                                        
-                               ldns_dnssec_derive_trust_tree_ds_rrset(new_tree,
-                                                                                           data_chain,
-                                                                                           cur_rr);
+                               ldns_dnssec_derive_trust_tree_ds_rrset_time(
+                                               new_tree, data_chain, 
+                                               cur_rr, check_time);
                        } else {
                                /* no signatures? maybe it's nsec data */
                                        
                                /* just add every rr from parent as new parent */
-                               ldns_dnssec_derive_trust_tree_no_sig(new_tree, data_chain);
+                               ldns_dnssec_derive_trust_tree_no_sig_time(
+                                       new_tree, data_chain, check_time);
                        }
                }
        }
@@ -781,10 +789,18 @@ ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
        return new_tree;
 }
 
+ldns_dnssec_trust_tree *
+ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
+{
+       return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL));
+}
+
 void
-ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
-                                           ldns_dnssec_data_chain *data_chain,
-                                           ldns_rr *cur_sig_rr)
+ldns_dnssec_derive_trust_tree_normal_rrset_time(
+               ldns_dnssec_trust_tree *new_tree, 
+               ldns_dnssec_data_chain *data_chain, 
+               ldns_rr *cur_sig_rr,
+               time_t check_time)
 {
        size_t i, j;
        ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset); 
@@ -811,10 +827,7 @@ ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
                                                /* might contain different names! 
                                                   sort and split */
                                                ldns_rr_list_sort(cur_rrset);
-                                               if (tmp_rrset && tmp_rrset != cur_rrset) {
-                                                       ldns_rr_list_deep_free(tmp_rrset);
-                                                       tmp_rrset = NULL;
-                                               }
+                                               assert(tmp_rrset == cur_rrset);
                                                tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset);
                                                
                                                /* with nsecs, this might be the wrong one */
@@ -829,9 +842,17 @@ ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
                                                                ldns_rr_list_pop_rrset(cur_rrset);
                                                }
                                        }
-                                       cur_status = ldns_verify_rrsig(tmp_rrset,
-                                                                                        cur_sig_rr,
-                                                                                        cur_parent_rr);
+                                       cur_status = ldns_verify_rrsig_time(
+                                                       tmp_rrset, 
+                                                       cur_sig_rr, 
+                                                       cur_parent_rr,
+                                                       check_time);
+                                       if (tmp_rrset && tmp_rrset != cur_rrset
+                                                       ) {
+                                               ldns_rr_list_deep_free(
+                                                               tmp_rrset);
+                                               tmp_rrset = NULL;
+                                       }
                                        /* avoid dupes */
                                        for (i = 0; i < new_tree->parent_count; i++) {
                                                if (cur_parent_rr == new_tree->parents[i]->rr) {
@@ -840,8 +861,10 @@ ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
                                        }
 
                                        cur_parent_tree =
-                                               ldns_dnssec_derive_trust_tree(data_chain->parent,
-                                                                             cur_parent_rr);
+                                               ldns_dnssec_derive_trust_tree_time(
+                                                               data_chain->parent,
+                                                               cur_parent_rr,
+                                                               check_time);
                                        (void)ldns_dnssec_trust_tree_add_parent(new_tree,
                                                   cur_parent_tree,
                                                   cur_sig_rr,
@@ -851,17 +874,25 @@ ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
                }
        }
  done:
-       if (tmp_rrset && tmp_rrset != cur_rrset) {
-               ldns_rr_list_deep_free(tmp_rrset);
-       }
        ldns_rr_list_deep_free(cur_rrset);
 }
 
 void
-ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
+ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
                                            ldns_dnssec_data_chain *data_chain,
-                                           ldns_rr *cur_rr,
                                            ldns_rr *cur_sig_rr)
+{
+       ldns_dnssec_derive_trust_tree_normal_rrset_time(
+                       new_tree, data_chain, cur_sig_rr, ldns_time(NULL));
+}
+
+void
+ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
+               ldns_dnssec_trust_tree *new_tree, 
+               ldns_dnssec_data_chain *data_chain, 
+               ldns_rr *cur_rr, 
+               ldns_rr *cur_sig_rr,
+               time_t check_time)
 {
        size_t j;
        ldns_rr_list *cur_rrset = data_chain->rrset;
@@ -881,9 +912,9 @@ ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
                                cur_parent_tree = ldns_dnssec_trust_tree_new();
                                cur_parent_tree->rr = cur_parent_rr;
                                cur_parent_tree->rrset = cur_rrset;
-                               cur_status = ldns_verify_rrsig(cur_rrset,
-                                                              cur_sig_rr,
-                                                              cur_parent_rr);
+                               cur_status = ldns_verify_rrsig_time(
+                                               cur_rrset, cur_sig_rr, 
+                                               cur_parent_rr, check_time);
                                (void) ldns_dnssec_trust_tree_add_parent(new_tree,
                                            cur_parent_tree, cur_sig_rr, cur_status);
                        }
@@ -892,9 +923,21 @@ ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
 }
 
 void
-ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
-                                       ldns_dnssec_data_chain *data_chain,
-                                       ldns_rr *cur_rr)
+ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
+                                           ldns_dnssec_data_chain *data_chain,
+                                           ldns_rr *cur_rr,
+                                           ldns_rr *cur_sig_rr)
+{
+       ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
+                       new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL));
+}
+
+void
+ldns_dnssec_derive_trust_tree_ds_rrset_time(
+               ldns_dnssec_trust_tree *new_tree,
+               ldns_dnssec_data_chain *data_chain, 
+               ldns_rr *cur_rr,
+               time_t check_time)
 {
        size_t j, h;
        ldns_rr_list *cur_rrset = data_chain->rrset;
@@ -915,8 +958,10 @@ ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
                                        cur_rr = ldns_rr_list_rr(cur_rrset, h);
                                        if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) {
                                                cur_parent_tree =
-                                                       ldns_dnssec_derive_trust_tree(
-                                                           data_chain->parent, cur_parent_rr);
+                                                       ldns_dnssec_derive_trust_tree_time(
+                                                           data_chain->parent, 
+                                                           cur_parent_rr,
+                                                           check_time);
                                                (void) ldns_dnssec_trust_tree_add_parent(
                                                            new_tree,
                                                            cur_parent_tree,
@@ -932,8 +977,19 @@ ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
 }
 
 void
-ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
-                                     ldns_dnssec_data_chain *data_chain)
+ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
+                                       ldns_dnssec_data_chain *data_chain,
+                                       ldns_rr *cur_rr)
+{
+       ldns_dnssec_derive_trust_tree_ds_rrset_time(
+                       new_tree, data_chain, cur_rr, ldns_time(NULL));
+}
+
+void
+ldns_dnssec_derive_trust_tree_no_sig_time(
+               ldns_dnssec_trust_tree *new_tree, 
+               ldns_dnssec_data_chain *data_chain,
+               time_t check_time)
 {
        size_t i;
        ldns_rr_list *cur_rrset;
@@ -955,7 +1011,7 @@ ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
                                                   data_chain->packet_qtype,
                                                   data_chain->packet_nodata);
                        } else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
-                                        LDNS_RR_TYPE_NSEC3) {
+                                        LDNS_RR_TYPE_NSEC) {
                                result = ldns_dnssec_verify_denial(
                                                new_tree->rr,
                                                   cur_rrset,
@@ -970,14 +1026,24 @@ ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
                for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) {
                        cur_parent_rr = ldns_rr_list_rr(cur_rrset, i);
                        cur_parent_tree = 
-                               ldns_dnssec_derive_trust_tree(data_chain->parent,
-                                                                               cur_parent_rr);
+                               ldns_dnssec_derive_trust_tree_time(
+                                               data_chain->parent, 
+                                               cur_parent_rr,
+                                               check_time);
                        (void) ldns_dnssec_trust_tree_add_parent(new_tree,
                                    cur_parent_tree, NULL, result);
                }
        }
 }
 
+void
+ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
+                                     ldns_dnssec_data_chain *data_chain)
+{
+       ldns_dnssec_derive_trust_tree_no_sig_time(
+                       new_tree, data_chain, ldns_time(NULL));
+}
+
 /*
  * returns OK if there is a path from tree to key with only OK
  * the (first) error in between otherwise
@@ -1012,7 +1078,8 @@ ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree,
                                        if (tree->parent_status[i] != LDNS_STATUS_OK) {
                                                result = tree->parent_status[i];
                                        } else {
-                                               if (ldns_rr_get_type(tree->rr)
+                                               if (tree->rr &&
+                                                   ldns_rr_get_type(tree->rr)
                                                    == LDNS_RR_TYPE_NSEC &&
                                                    parent_result == LDNS_STATUS_OK
                                                    ) {
@@ -1032,8 +1099,13 @@ ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree,
 }
 
 ldns_status
-ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, 
-                 ldns_rr_list *good_keys)
+ldns_verify_time(
+               ldns_rr_list *rrset,
+               ldns_rr_list *rrsig, 
+               const ldns_rr_list *keys, 
+               time_t check_time,
+               ldns_rr_list *good_keys
+               )
 {
        uint16_t i;
        ldns_status verify_result = LDNS_STATUS_ERR;
@@ -1054,8 +1126,9 @@ ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys,
                verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
        } else {
                for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
-                       ldns_status s = ldns_verify_rrsig_keylist(rrset, 
-                               ldns_rr_list_rr(rrsig, i), keys, good_keys);
+                       ldns_status s = ldns_verify_rrsig_keylist_time(
+                                       rrset, ldns_rr_list_rr(rrsig, i), 
+                                       keys, check_time, good_keys);
                        /* try a little to get more descriptive error */
                        if(s == LDNS_STATUS_OK) {
                                verify_result = LDNS_STATUS_OK;
@@ -1069,6 +1142,13 @@ ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys,
        return verify_result;
 }
 
+ldns_status
+ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, 
+                 ldns_rr_list *good_keys)
+{
+       return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys);
+}
+
 ldns_status
 ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig,
        const ldns_rr_list *keys, ldns_rr_list *good_keys)
@@ -1110,9 +1190,10 @@ ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig,
 }
 
 ldns_rr_list *
-ldns_fetch_valid_domain_keys(const ldns_resolver *res,
+ldns_fetch_valid_domain_keys_time(const ldns_resolver *res,
                              const ldns_rdf *domain,
                              const ldns_rr_list *keys,
+                            time_t check_time,
                              ldns_status *status)
 {
        ldns_rr_list * trusted_keys = NULL;
@@ -1123,33 +1204,36 @@ ldns_fetch_valid_domain_keys(const ldns_resolver *res,
 
        if (res && domain && keys) {
 
-               if ((trusted_keys = ldns_validate_domain_dnskey(res,
-                                         domain,
-                                         keys))) {
+               if ((trusted_keys = ldns_validate_domain_dnskey_time(res,
+                                         domain, keys, check_time))) {
                        *status = LDNS_STATUS_OK;
                } else {
                        /* No trusted keys in this domain, we'll have to find some in the parent domain */
                        *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
 
                        parent_domain = ldns_dname_left_chop(domain);
-                       while (ldns_rdf_size(parent_domain) > 0) {
-                               /* Fail if we are at the root */
+                       while (parent_domain && /* Fail if we are at the root*/
+                                       ldns_rdf_size(parent_domain) > 0) {
        
                                if ((parent_keys = 
-                                       ldns_fetch_valid_domain_keys(res,
+                                       ldns_fetch_valid_domain_keys_time(res,
                                             parent_domain,
                                             keys,
+                                            check_time,
                                             status))) {
                                        /* Check DS records */
                                        if ((ds_keys =
-                                               ldns_validate_domain_ds(res,
+                                               ldns_validate_domain_ds_time(res,
                                                     domain,
-                                                    parent_keys))) {
+                                                    parent_keys,
+                                                    check_time))) {
                                                trusted_keys =
-                                                       ldns_fetch_valid_domain_keys(res,
-                                                            domain,
-                                                            ds_keys,
-                                                            status);
+                                               ldns_fetch_valid_domain_keys_time(
+                                                               res, 
+                                                               domain, 
+                                                               ds_keys, 
+                                                               check_time,
+                                                               status);
                                                ldns_rr_list_deep_free(ds_keys);
                                        } else {
                                                /* No valid DS at the parent -- fail */
@@ -1165,16 +1249,31 @@ ldns_fetch_valid_domain_keys(const ldns_resolver *res,
                                        ldns_rdf_deep_free(prev_parent_domain);
                                }
                        }
-                       ldns_rdf_deep_free(parent_domain);
+                       if (parent_domain) {
+                               ldns_rdf_deep_free(parent_domain);
+                       }
                }
        }
        return trusted_keys;
 }
 
 ldns_rr_list *
-ldns_validate_domain_dnskey(const ldns_resolver * res,
-                                          const ldns_rdf * domain,
-                                          const ldns_rr_list * keys)
+ldns_fetch_valid_domain_keys(const ldns_resolver *res,
+                             const ldns_rdf *domain,
+                             const ldns_rr_list *keys,
+                             ldns_status *status)
+{
+       return ldns_fetch_valid_domain_keys_time(
+                       res, domain, keys, ldns_time(NULL), status);
+}
+
+ldns_rr_list *
+ldns_validate_domain_dnskey_time(
+               const ldns_resolver * res,
+               const ldns_rdf * domain,
+               const ldns_rr_list * keys,
+               time_t check_time
+               )
 {
        ldns_pkt * keypkt;
        ldns_rr * cur_key;
@@ -1215,9 +1314,11 @@ ldns_validate_domain_dnskey(const ldns_resolver * res,
                                                if (ldns_rdf2native_int16(
                                                           ldns_rr_rrsig_keytag(cur_sig))
                                                    == ldns_calc_keytag(cur_key)) {
-                                                       if (ldns_verify_rrsig(domain_keys,
-                                                                                          cur_sig,
-                                                                                          cur_key)
+                                                       if (ldns_verify_rrsig_time(
+                                                                       domain_keys,
+                                                                       cur_sig,
+                                                                       cur_key,
+                                                                       check_time)
                                                            == LDNS_STATUS_OK) {
                 
                                                                /* Push the whole rrset 
@@ -1261,9 +1362,20 @@ ldns_validate_domain_dnskey(const ldns_resolver * res,
 }
 
 ldns_rr_list *
-ldns_validate_domain_ds(const ldns_resolver *res,
-                                   const ldns_rdf * domain,
-                                   const ldns_rr_list * keys)
+ldns_validate_domain_dnskey(const ldns_resolver * res,
+                                          const ldns_rdf * domain,
+                                          const ldns_rr_list * keys)
+{
+       return ldns_validate_domain_dnskey_time(
+                       res, domain, keys, ldns_time(NULL));
+}
+
+ldns_rr_list *
+ldns_validate_domain_ds_time(
+               const ldns_resolver *res, 
+               const ldns_rdf * domain,
+               const ldns_rr_list * keys,
+               time_t check_time)
 {
        ldns_pkt * dspkt;
        uint16_t key_i;
@@ -1283,7 +1395,8 @@ ldns_validate_domain_ds(const ldns_resolver *res,
                                                                  LDNS_SECTION_ANSWER);
 
                /* Validate sigs */
-               if (ldns_verify(rrset, sigs, keys, NULL) == LDNS_STATUS_OK) {
+               if (ldns_verify_time(rrset, sigs, keys, check_time, NULL)
+                               == LDNS_STATUS_OK) {
                        trusted_keys = ldns_rr_list_new();
                        for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) {
                                ldns_rr_list_push_rr(trusted_keys,
@@ -1305,11 +1418,22 @@ ldns_validate_domain_ds(const ldns_resolver *res,
        return trusted_keys;
 }
 
+ldns_rr_list *
+ldns_validate_domain_ds(const ldns_resolver *res,
+                                   const ldns_rdf * domain,
+                                   const ldns_rr_list * keys)
+{
+       return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL));
+}
+
 ldns_status
-ldns_verify_trusted(ldns_resolver *res,
-                               ldns_rr_list *rrset,
-                               ldns_rr_list * rrsigs,
-                               ldns_rr_list * validating_keys)
+ldns_verify_trusted_time(
+               ldns_resolver *res, 
+               ldns_rr_list *rrset, 
+               ldns_rr_list * rrsigs, 
+               time_t check_time,
+               ldns_rr_list * validating_keys
+               )
 {
        uint16_t sig_i; uint16_t key_i;
        ldns_rr * cur_sig; ldns_rr * cur_key;
@@ -1333,20 +1457,22 @@ ldns_verify_trusted(ldns_resolver *res,
 
                cur_sig = ldns_rr_list_rr(rrsigs, sig_i);
                /* Get a valid signer key and validate the sig */
-               if ((trusted_keys = ldns_fetch_valid_domain_keys(
-                                                   res,
-                                                   ldns_rr_rrsig_signame(cur_sig),
-                                                   ldns_resolver_dnssec_anchors(res),
-                                                   &result))) {
+               if ((trusted_keys = ldns_fetch_valid_domain_keys_time(
+                                       res, 
+                                       ldns_rr_rrsig_signame(cur_sig), 
+                                       ldns_resolver_dnssec_anchors(res), 
+                                       check_time,
+                                       &result))) {
 
                        for (key_i = 0;
                                key_i < ldns_rr_list_rr_count(trusted_keys);
                                key_i++) {
                                cur_key = ldns_rr_list_rr(trusted_keys, key_i);
 
-                               if ((result = ldns_verify_rrsig(rrset,
-                                                                                 cur_sig,
-                                                                                 cur_key))
+                               if ((result = ldns_verify_rrsig_time(rrset,
+                                                               cur_sig, 
+                                                               cur_key,
+                                                               check_time))
                                    == LDNS_STATUS_OK) {
                                        if (validating_keys) {
                                                ldns_rr_list_push_rr(validating_keys,
@@ -1363,6 +1489,18 @@ ldns_verify_trusted(ldns_resolver *res,
        return result;
 }
 
+ldns_status
+ldns_verify_trusted(
+               ldns_resolver *res,
+               ldns_rr_list *rrset, 
+               ldns_rr_list * rrsigs, 
+               ldns_rr_list * validating_keys)
+{
+       return ldns_verify_trusted_time(
+                       res, rrset, rrsigs, ldns_time(NULL), validating_keys);
+}
+
+
 ldns_status
 ldns_dnssec_verify_denial(ldns_rr *rr,
                           ldns_rr_list *nsecs,
@@ -1385,12 +1523,11 @@ ldns_dnssec_verify_denial(ldns_rr *rr,
        rr_name = ldns_rr_owner(rr);
        chopped_dname = ldns_dname_left_chop(rr_name);
        result = ldns_dname_cat(wildcard_name, chopped_dname);
+       ldns_rdf_deep_free(chopped_dname);
        if (result != LDNS_STATUS_OK) {
                return result;
        }
        
-       ldns_rdf_deep_free(chopped_dname);
-       
        for  (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
                cur_nsec = ldns_rr_list_rr(nsecs, i);
                if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) {
@@ -1442,15 +1579,15 @@ ldns_dnssec_verify_denial(ldns_rr *rr,
        return LDNS_STATUS_OK;
 }
 
-#ifdef HAVE_SSL
 ldns_status
-ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr,
-                                                 ldns_rr_list *nsecs,
-                                                 ldns_rr_list *rrsigs,
-                                                 ldns_pkt_rcode packet_rcode,
-                                                 ldns_rr_type packet_qtype,
-                                                 bool packet_nodata,
-                                                 ldns_rr **match)
+ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr
+                                    , ldns_rr_list *nsecs
+                                    , ATTR_UNUSED(ldns_rr_list *rrsigs)
+                                    , ldns_pkt_rcode packet_rcode
+                                    , ldns_rr_type packet_qtype
+                                    , bool packet_nodata
+                                    , ldns_rr **match
+                                    )
 {
        ldns_rdf *closest_encloser;
        ldns_rdf *wildcard;
@@ -1458,11 +1595,12 @@ ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr,
        bool wildcard_covered = false;
        ldns_rdf *zone_name;
        ldns_rdf *hashed_name;
+       /* self assignment to suppress uninitialized warning */
+       ldns_rdf *next_closer = next_closer;
+       ldns_rdf *hashed_next_closer;
        size_t i;
        ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
 
-       rrsigs = rrsigs;
-
        if (match) {
                *match = NULL;
        }
@@ -1476,7 +1614,7 @@ ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr,
                                                   ldns_rr_get_type(rr),
                                                   nsecs);
                 if(!closest_encloser) {
-                        result = LDNS_STATUS_NSEC3_ERR;
+                        result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
                         goto done;
                 }
 
@@ -1500,16 +1638,14 @@ ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr,
                        ldns_rdf_deep_free(hashed_wildcard_name);
                }
 
-               ldns_rdf_deep_free(closest_encloser);
-               ldns_rdf_deep_free(wildcard);
-
-               if (!wildcard_covered) {
+               if (! wildcard_covered) {
                        result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
-               } else if (closest_encloser && wildcard_covered) {
-                       result = LDNS_STATUS_OK;
                } else {
-                       result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
+                       result = LDNS_STATUS_OK;
                }
+               ldns_rdf_deep_free(closest_encloser);
+               ldns_rdf_deep_free(wildcard);
+
        } else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) {
                /* section 8.5 */
                hashed_name = ldns_nsec3_hash_name_frm_nsec3(
@@ -1523,7 +1659,7 @@ ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr,
                                if (!ldns_nsec_bitmap_covers_type(
                                            ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
                                            packet_qtype)
-                                   && 
+                                   &&
                                    !ldns_nsec_bitmap_covers_type(
                                            ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
                                            LDNS_RR_TYPE_CNAME)) {
@@ -1536,6 +1672,46 @@ ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr,
                        }
                }
                result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
+               /* wildcard no data? section 8.7 */
+               closest_encloser = ldns_dnssec_nsec3_closest_encloser(
+                                  ldns_rr_owner(rr),
+                                  ldns_rr_get_type(rr),
+                                  nsecs);
+               if(!closest_encloser) {
+                       result = LDNS_STATUS_NSEC3_ERR;
+                       goto done;
+               }
+               wildcard = ldns_dname_new_frm_str("*");
+               (void) ldns_dname_cat(wildcard, closest_encloser);
+               for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
+                       hashed_wildcard_name =
+                               ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
+                                        wildcard);
+                       (void) ldns_dname_cat(hashed_wildcard_name, zone_name);
+
+                       if (ldns_dname_compare(hashed_wildcard_name,
+                                ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
+                           == 0) {
+                               if (!ldns_nsec_bitmap_covers_type(
+                                           ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
+                                           packet_qtype)
+                                   &&
+                                   !ldns_nsec_bitmap_covers_type(
+                                           ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
+                                           LDNS_RR_TYPE_CNAME)) {
+                                       result = LDNS_STATUS_OK;
+                                       if (match) {
+                                               *match = ldns_rr_list_rr(nsecs, i);
+                                       }
+                               }
+                       }
+                       ldns_rdf_deep_free(hashed_wildcard_name);
+                       if (result == LDNS_STATUS_OK) {
+                               break;
+                       }
+               }
+               ldns_rdf_deep_free(closest_encloser);
+               ldns_rdf_deep_free(wildcard);
        } else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) {
                /* section 8.6 */
                /* note: up to XXX this is the same as for 8.5 */
@@ -1567,6 +1743,61 @@ ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr,
 
                /* XXX see note above */
                result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
+
+               closest_encloser = ldns_dnssec_nsec3_closest_encloser(
+                                  ldns_rr_owner(rr),
+                                  ldns_rr_get_type(rr),
+                                  nsecs);
+               if(!closest_encloser) {
+                       result = LDNS_STATUS_NSEC3_ERR;
+                       goto done;
+               }
+               /* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/
+
+               if (ldns_dname_label_count(closest_encloser) + 1
+                   >= ldns_dname_label_count(ldns_rr_owner(rr))) {
+                       
+                       /* Query name *is* the "next closer". */
+                       hashed_next_closer = hashed_name;
+               } else {
+
+                       /* "next closer" has less labels than the query name.
+                        * Create the name and hash it.
+                        */
+                       next_closer = ldns_dname_clone_from(
+                                       ldns_rr_owner(rr),
+                                       ldns_dname_label_count(ldns_rr_owner(rr))
+                                       - (ldns_dname_label_count(closest_encloser) + 1)
+                                       );
+                       hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3(
+                                       ldns_rr_list_rr(nsecs, 0),
+                                       next_closer
+                                       );
+                       (void) ldns_dname_cat(hashed_next_closer, zone_name);
+               }
+               /* Find the NSEC3 that covers the "next closer" */
+               for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
+                       if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
+                                                 hashed_next_closer) && 
+                               ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) {
+
+                               result = LDNS_STATUS_OK;
+                               if (match) {
+                                       *match = ldns_rr_list_rr(nsecs, i);
+                               }
+                               break;
+                       }
+               }
+               if (ldns_dname_label_count(closest_encloser) + 1
+                   < ldns_dname_label_count(ldns_rr_owner(rr))) {
+
+                       /* "next closer" has less labels than the query name.
+                        * Dispose of the temporary variables that held that name.
+                        */
+                       ldns_rdf_deep_free(hashed_next_closer);
+                       ldns_rdf_deep_free(next_closer);
+               }
+               ldns_rdf_deep_free(closest_encloser);
        }
 
  done:
@@ -1588,9 +1819,6 @@ ldns_dnssec_verify_denial_nsec3(ldns_rr *rr,
               );
 }
 
-
-#endif /* HAVE_SSL */
-
 #ifdef USE_GOST
 EVP_PKEY*
 ldns_gost2pkey_raw(unsigned char* key, size_t keylen)
@@ -1920,7 +2148,7 @@ ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig)
  * @return status code LDNS_STATUS_OK if all is fine.
  */
 static ldns_status
-ldns_rrsig_check_timestamps(ldns_rr* rrsig, int32_t now)
+ldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now)
 {
        int32_t inception, expiration;
        
@@ -1934,11 +2162,11 @@ ldns_rrsig_check_timestamps(ldns_rr* rrsig, int32_t now)
                /* bad sig, expiration before inception?? Tsssg */
                return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION;
        }
-       if (now - inception < 0) {
+       if (((int32_t) now) - inception < 0) {
                /* bad sig, inception date has not yet come to pass */
                return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
        }
-       if (expiration - now < 0) {
+       if (expiration - ((int32_t) now) < 0) {
                /* bad sig, expiration date has passed */
                return LDNS_STATUS_CRYPTO_SIG_EXPIRED;
        }
@@ -2068,10 +2296,12 @@ ldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf,
  * - verify the rrset+sig, with the b64 data and the b64 key data
  */
 ldns_status
-ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
-                                        ldns_rr *rrsig,
-                                        const ldns_rr_list *keys, 
-                                        ldns_rr_list *good_keys)
+ldns_verify_rrsig_keylist_time(
+               ldns_rr_list *rrset,
+               ldns_rr *rrsig,
+               const ldns_rr_list *keys, 
+               time_t check_time,
+               ldns_rr_list *good_keys)
 {
        ldns_status result;
        ldns_rr_list *valid = ldns_rr_list_new();
@@ -2085,7 +2315,7 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
        }
 
        /* check timestamps last; its OK except time */
-       result = ldns_rrsig_check_timestamps(rrsig, (int32_t)time(NULL));
+       result = ldns_rrsig_check_timestamps(rrsig, check_time);
        if(result != LDNS_STATUS_OK) {
                ldns_rr_list_free(valid); 
                return result;
@@ -2096,6 +2326,25 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
        return LDNS_STATUS_OK;
 }
 
+/* 
+ * to verify:
+ * - create the wire fmt of the b64 key rdata
+ * - create the wire fmt of the sorted rrset
+ * - create the wire fmt of the b64 sig rdata
+ * - create the wire fmt of the sig without the b64 rdata
+ * - cat the sig data (without b64 rdata) to the rrset
+ * - verify the rrset+sig, with the b64 data and the b64 key data
+ */
+ldns_status
+ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
+                                        ldns_rr *rrsig,
+                                        const ldns_rr_list *keys, 
+                                        ldns_rr_list *good_keys)
+{
+       return ldns_verify_rrsig_keylist_time(
+                       rrset, rrsig, keys, ldns_time(NULL), good_keys);
+}
+
 ldns_status
 ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset,
                                         ldns_rr *rrsig,
@@ -2181,7 +2430,11 @@ ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset,
 }
 
 ldns_status
-ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
+ldns_verify_rrsig_time(
+               ldns_rr_list *rrset, 
+               ldns_rr *rrsig, 
+               ldns_rr *key, 
+               time_t check_time)
 {
        ldns_buffer *rawsig_buf;
        ldns_buffer *verify_buf;
@@ -2214,12 +2467,18 @@ ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
 
        /* check timestamp last, apart from time its OK */
        if(result == LDNS_STATUS_OK)
-               result = ldns_rrsig_check_timestamps(rrsig, 
-                       (int32_t)time(NULL));
+               result = ldns_rrsig_check_timestamps(rrsig, check_time);
 
        return result;
 }
 
+ldns_status
+ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
+{
+       return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL));
+}
+
+
 ldns_status
 ldns_verify_rrsig_evp(ldns_buffer *sig,
                                  ldns_buffer *rrset,
index 89bdf8d..df71a23 100644 (file)
@@ -621,18 +621,174 @@ ldns_dnssec_zone_new()
        return zone;
 }
 
+static bool
+rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
+{
+       return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
+               && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
+}
+
+/* When the zone is first read into an list and then inserted into an
+ * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
+ * to each other. Because ldns-verify-zone (the only program that uses this
+ * function) uses the rbtree mostly for sequentual walking, this results
+ * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
+ */
+#define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
+
+ldns_status
+ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
+               uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
+{
+       ldns_rr* cur_rr;
+       size_t i;
+
+       ldns_rdf *my_origin = NULL;
+       ldns_rdf *my_prev = NULL;
+
+       ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
+       /* when reading NSEC3s, there is a chance that we encounter nsecs
+          for empty nonterminals, whose nonterminals we cannot derive yet
+          because the needed information is to be read later. in that case
+          we keep a list of those nsec3's and retry to add them later */
+       ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
+       ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
+
+       ldns_status status = LDNS_STATUS_MEM_ERR;
+
+#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
+       ldns_zone* zone = NULL;
+       if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
+                       != LDNS_STATUS_OK) goto error;
+#else
+       uint32_t  my_ttl = ttl;
+#endif
+
+       if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
+
+       if (origin) {
+               if (!(my_origin = ldns_rdf_clone(origin))) goto error;
+               if (!(my_prev   = ldns_rdf_clone(origin))) goto error;
+       }
+
+#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
+       if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
+                       != LDNS_STATUS_OK) goto error;
+
+       for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
+               cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
+               status = LDNS_STATUS_OK;
+#else
+       while (!feof(fp)) {
+               status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
+                               &my_prev, line_nr);
+
+#endif
+               switch (status) {
+               case LDNS_STATUS_OK:
+
+                       status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
+                       if (status ==
+                               LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
+
+                               if (rr_is_rrsig_covering(cur_rr,
+                                                       LDNS_RR_TYPE_NSEC3)){
+                                       ldns_rr_list_push_rr(todo_nsec3_rrsigs,
+                                                       cur_rr);
+                               } else {
+                                       ldns_rr_list_push_rr(todo_nsec3s,
+                                                       cur_rr);
+                               }
+                       } else if (status != LDNS_STATUS_OK)
+                               goto error;
+
+                       break;
+
+
+               case LDNS_STATUS_SYNTAX_EMPTY:  /* empty line was seen */
+               case LDNS_STATUS_SYNTAX_TTL:    /* the ttl was set*/
+               case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
+                       status = LDNS_STATUS_OK;
+                       break;
+
+               case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
+                       status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
+                       break;
+
+               default:
+                       goto error;
+               }
+       }
+
+       if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
+               (void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
+               for (i = 0; status == LDNS_STATUS_OK && 
+                               i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
+                       cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
+                       status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
+               }
+               for (i = 0; status == LDNS_STATUS_OK &&
+                               i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
+                               i++){
+                       cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
+                       status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
+               }
+       } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
+               for (i = 0; status == LDNS_STATUS_OK &&
+                               i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
+                               i++){
+                       cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
+                       status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
+               }
+       }
+
+       if (z) {
+               *z = newzone;
+               newzone = NULL;
+       } else {
+               ldns_dnssec_zone_free(newzone);
+       }
+
+error:
+#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
+       if (zone) {
+               ldns_zone_free(zone);
+       }
+#endif
+       ldns_rr_list_free(todo_nsec3_rrsigs);
+       ldns_rr_list_free(todo_nsec3s);
+
+       if (my_origin) {
+               ldns_rdf_deep_free(my_origin);
+       }
+       if (my_prev) {
+               ldns_rdf_deep_free(my_prev);
+       }
+       if (newzone) {
+               ldns_dnssec_zone_free(newzone);
+       }
+       return status;
+}
+
+ldns_status
+ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
+               uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
+{
+       return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
+}
+
 void
 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
        (void) arg;
        ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
-       free(node);
+       LDNS_FREE(node);
 }
 
 void
 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
        (void) arg;
        ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
-       free(node);
+       LDNS_FREE(node);
 }
 
 void
@@ -644,7 +800,7 @@ ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
                        ldns_traverse_postorder(zone->names,
                                                    ldns_dnssec_name_node_free,
                                                    NULL);
-                       free(zone->names);
+                       LDNS_FREE(zone->names);
                }
                LDNS_FREE(zone);
        }
@@ -659,7 +815,7 @@ ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
                        ldns_traverse_postorder(zone->names,
                                                    ldns_dnssec_name_node_deep_free,
                                                    NULL);
-                       free(zone->names);
+                       LDNS_FREE(zone->names);
                }
                LDNS_FREE(zone);
        }
@@ -671,7 +827,6 @@ ldns_dname_compare_v(const void *a, const void *b) {
        return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
 }
 
-#ifdef HAVE_SSL
 ldns_rbnode_t *
 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone,
                                      ldns_rr *rr) {
@@ -761,7 +916,6 @@ ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
 
        return result;
 }
-#endif /* HAVE_SSL */
 
 void
 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
@@ -858,7 +1012,9 @@ ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
                if (next_node == LDNS_RBTREE_NULL) {
                        next_node = ldns_rbtree_first(zone->names);
                }
-
+               if (! cur_node->data || ! next_node->data) {
+                       return LDNS_STATUS_ERR;
+               }
                cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
                next_name = ((ldns_dnssec_name *)next_node->data)->name;
                cur_label_count = ldns_dname_label_count(cur_name);
@@ -919,3 +1075,24 @@ ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
        }
        return LDNS_STATUS_OK;
 }
+
+bool
+ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
+{
+       ldns_rr* nsec3;
+       ldns_rbnode_t* node;
+
+       if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
+               node = ldns_rbtree_first(zone->names);
+               while (node != LDNS_RBTREE_NULL) {
+                       nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
+                       if (nsec3 &&ldns_rr_get_type(nsec3) 
+                                       == LDNS_RR_TYPE_NSEC3 &&
+                                       ldns_nsec3_optout(nsec3)) {
+                               return true;
+                       }
+                       node = ldns_rbtree_next(node);
+               }
+       }
+       return false;
+}
index a1dfd44..0a37ff3 100644 (file)
@@ -30,7 +30,6 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
        ldns_rr_list *new_nss_aaaa;
        ldns_rr_list *final_answer;
        ldns_rr_list *new_nss;
-       ldns_rr_list *hostnames;
        ldns_rr_list *ns_addr;
        uint16_t loop_count;
        ldns_rdf *pop; 
@@ -46,7 +45,15 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
        p = ldns_pkt_new();
        res = ldns_resolver_new();
 
-       if (!p || !res) {
+       if (!p) {
+               if (res) {
+                       ldns_resolver_free(res);
+               }
+                error("Memory allocation failed");
+                return NULL;
+       }
+       if (!res) {
+               ldns_pkt_free(p);
                 error("Memory allocation failed");
                 return NULL;
         }
@@ -74,6 +81,8 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
        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);
+               ldns_resolver_free(res);
+               ldns_pkt_free(p);
                return NULL;
        }
 
@@ -119,7 +128,7 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
                drill_pkt_print_footer(stdout, local_res, p);
                
                /* remove the old nameserver from the resolver */
-               while((pop = ldns_resolver_pop_nameserver(res))) { /* do it */ }
+               while(ldns_resolver_pop_nameserver(res)) { /* do it */ }
 
                /* also check for new_nss emptyness */
 
@@ -195,9 +204,6 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
                return NULL;
        }
 
-       hostnames = ldns_get_rr_list_name_by_addr(local_res, 
-                       ldns_pkt_answerfrom(p), 0, 0);
-
        new_nss = ldns_pkt_authority(p);
        final_answer = ldns_pkt_answer(p);
 
@@ -229,14 +235,13 @@ do_chase(ldns_resolver *res,
            ldns_rr_list *trusted_keys,
            ldns_pkt *pkt_o,
            uint16_t qflags,
-           ldns_rr_list *prev_key_list,
+           ldns_rr_list * ATTR_UNUSED(prev_key_list),
            int verbosity)
 {
        ldns_rr_list *rrset = NULL;
        ldns_status result;
        ldns_rr *orig_rr = NULL;
        
-       bool cname_followed = false;
 /*
        ldns_rr_list *sigs;
        ldns_rr *cur_sig;
@@ -290,7 +295,6 @@ do_chase(ldns_resolver *res,
                /* answer might be a cname, chase that first, then chase
                   cname target? (TODO) */
                if (!rrset) {
-                       cname_followed = true;
                        rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
                                        name,
                                        LDNS_RR_TYPE_CNAME,
index 030aa3b..b8074be 100644 (file)
@@ -22,12 +22,10 @@ get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c)
        p = ldns_pkt_new();
        found = NULL;
 
-       if (ldns_resolver_send(&p, res, zname, t, c, 0) != LDNS_STATUS_OK) {
-               /* oops */
-               return NULL;
-       } else {
+       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;
 }
 
@@ -36,6 +34,7 @@ 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;
@@ -46,8 +45,7 @@ drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
        new_nss = ldns_pkt_rr_list_by_type(p,
                        LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
        ldns_rr_list_print(fd, new_nss);
-
-       /* new_nss can be empty.... */
+       ldns_rr_list_deep_free(new_nss);
 
        fprintf(fd, ";; Received %d bytes from %s#%d(",
                        (int) ldns_pkt_size(p),
@@ -59,7 +57,11 @@ drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
                                ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
                ldns_rr_list_deep_free(hostnames);
        } else {
-               fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
+               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));
 }
@@ -68,6 +70,7 @@ void
 drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
 {
        ldns_rr_list *hostnames;
+       char *answerfrom_str;
 
        if (verbosity < 5) {
                return;
@@ -85,7 +88,11 @@ drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
                                ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
                ldns_rr_list_deep_free(hostnames);
        } else {
-               fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
+               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));
 }
@@ -98,7 +105,6 @@ 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 *rr = NULL;
        ldns_rr_list *sigs = NULL;
        size_t i;
 
@@ -111,36 +117,52 @@ get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t,
 
        pt = ldns_pkt_reply_type(p);
        if (name) {
-               rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_ANSWER);
-               if (!rr) {
-                       rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_AUTHORITY);
+               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);
+                       }
                }
-               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);
+               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 */
-               rr = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_AUTHORITY);
-               sigs = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG,
-                               LDNS_SECTION_AUTHORITY);
+               /* 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 (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(ldns_rr_list_rr(sigs, i))) ==
-                           t) {
-                               ldns_rr_list_push_rr(*sig, ldns_rr_clone(ldns_rr_list_rr(sigs, i)));   
+                       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 (rrlist) {
-               *rrlist = rr;
-       }
 
        if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) {
                return pt;
@@ -153,6 +175,7 @@ get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t,
 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;
@@ -216,12 +239,28 @@ ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_lis
                 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) return LDNS_STATUS_MEM_ERR;
-                if(!q) return LDNS_STATUS_MEM_ERR;
+
+                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)) return LDNS_STATUS_MEM_ERR;
+                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); */
@@ -234,6 +273,14 @@ ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_lis
                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 */
@@ -245,17 +292,15 @@ ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s
        uint8_t salt_length;
        uint8_t *salt;
        
-       ldns_rdf *sname, *hashed_sname;
+       ldns_rdf *sname = NULL, *hashed_sname = NULL;
        
        size_t nsec_i;
        ldns_rr *nsec;
        ldns_rr *result = NULL;
        
-       ldns_status status;
-       
        const ldns_rr_descriptor *descriptor;
        
-       ldns_rdf *zone_name;
+       ldns_rdf *zone_name = NULL;
        
        if (verbosity >= 4) {
                printf(";; finding exact match for ");
@@ -281,16 +326,28 @@ ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s
        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));
-       status = ldns_dname_cat(hashed_sname, zone_name);
+       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);
@@ -337,15 +394,13 @@ ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *n
        uint8_t salt_length;
        uint8_t *salt;
 
-       ldns_rdf *sname, *hashed_sname, *tmp;
-       ldns_rr *ce;
+       ldns_rdf *sname = NULL, *hashed_sname = NULL, *tmp;
        bool flag;
        
        bool exact_match_found;
        bool in_range_found;
        
-       ldns_status status;
-       ldns_rdf *zone_name;
+       ldns_rdf *zone_name = NULL;
        
        size_t nsec_i;
        ldns_rr *nsec;
@@ -366,13 +421,21 @@ ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *n
        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;
+       }
 
-       ce = NULL;
        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) {
@@ -385,8 +448,13 @@ ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *n
                        printf(" hashes to: ");
                }
                hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
+               if (hashed_sname == NULL) {
+                       goto done;
+               }
 
-               status = ldns_dname_cat(hashed_sname, zone_name);
+               if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK){
+                       goto done;
+               }
 
                if (verbosity >= 3) {
                        ldns_rdf_print(stdout, hashed_sname);
@@ -431,9 +499,12 @@ ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *n
                tmp = sname;
                sname = ldns_dname_left_chop(sname);
                ldns_rdf_deep_free(tmp);
+               if (sname == NULL) {
+                       goto done;
+               }
        }
 
-       done:
+done:
        LDNS_FREE(salt);
        ldns_rdf_deep_free(zone_name);
        ldns_rdf_deep_free(sname);
@@ -447,68 +518,3 @@ ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *n
        /* todo checks from end of 6.2. here or in caller? */
        return result;
 }
-
-
-/* special case were there was a wildcard expansion match, the exact match must be disproven */
-ldns_status
-ldns_verify_denial_wildcard(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs)
-{
-       ldns_rdf *nsec3_ce = NULL;
-       ldns_rr *nsec3_ex = NULL;
-       ldns_rdf *wildcard_name = NULL;
-       ldns_rdf *nsec3_wc_ce = NULL;
-       ldns_rr *nsec3_wc_ex = NULL;
-       ldns_rdf *chopped_dname = NULL;
-       ldns_rr_list *nsecs;
-       ldns_status result = LDNS_STATUS_ERR;
-
-       nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION);
-       if (nsecs) {
-               wildcard_name = ldns_dname_new_frm_str("*");
-               chopped_dname = ldns_dname_left_chop(name);
-               result = ldns_dname_cat(wildcard_name, chopped_dname);
-               ldns_rdf_deep_free(chopped_dname);
-
-               nsec3_ex = ldns_nsec3_exact_match(name, type, nsecs);
-               nsec3_ce = ldns_nsec3_closest_encloser(name, type, nsecs);
-               nsec3_wc_ce = ldns_nsec3_closest_encloser(wildcard_name, type, nsecs);                          
-               nsec3_wc_ex = ldns_nsec3_exact_match(wildcard_name, type, nsecs);
-               
-               if (nsec3_ex) {
-                       if (verbosity >= 3) {
-                               printf(";; Error, exact match for for name found, but should not exist (draft -07 section 8.8)\n");
-                       }
-                       result = LDNS_STATUS_NSEC3_ERR;
-               } else if (!nsec3_ce) {
-                       if (verbosity >= 3) {
-                               printf(";; Error, closest encloser for exact match missing in wildcard response (draft -07 section 8.8)\n");
-                       }
-                       result = LDNS_STATUS_NSEC3_ERR;
-/*
-               } else if (!nsec3_wc_ex) {
-                       printf(";; Error, no wildcard nsec3 match: ");
-                       ldns_rdf_print(stdout, wildcard_name);
-                       printf(" (draft -07 section 8.8)\n");
-                       result = LDNS_STATUS_NSEC3_ERR;
-*/
-/*             } else if (!nsec */
-               } else {
-                       if (verbosity >= 3) {
-                               printf(";; wilcard expansion proven\n");
-                       }
-                       result = LDNS_STATUS_OK;
-               }
-       } else {
-               if (verbosity >= 3) {
-                       printf(";; Error: no NSEC or NSEC3 records in answer\n");
-               }
-               result = LDNS_STATUS_CRYPTO_NO_RRSIG;
-       }
-       
-       if (nsecs && nsec_rrs && nsec_rr_sigs) {
-               (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, 0)), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs);
-       }
-       return result;
-}
-
-
diff --git a/contrib/ldns/drill/drill.1 b/contrib/ldns/drill/drill.1
deleted file mode 100644 (file)
index 24cfd6d..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-.\" @(#)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 to designed to get all sorts of information out of the
-DNS. It is specificly 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 to 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 automaticly enabled.
-
-.TP
-\fB\-T
-Trace \fIname\fR from the root down. When using this option the @server and
-the type arguments are 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\-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.
-
-.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 loopup. 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.
-
-
-.SH AUTHOR
-Jelte Jansen and Miek Gieben. Both of NLnet Labs.
-
-.SH REPORTING BUGS
-Report bugs to <ldns-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.
index abd0ff6..574c8b9 100644 (file)
@@ -47,19 +47,25 @@ usage(FILE *stream, const char *progname)
        fprintf(stream, "\t-6\t\tstay on ip6\n");
        fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n");
        fprintf(stream, "\t-b <bufsize>\tuse <bufsize> as the buffer size (defaults to 512 b)\n");
-       fprintf(stream, "\t-c <file>\t\tuse file for rescursive nameserver configuration (/etc/resolv.conf)\n");
-       fprintf(stream, "\t-k <file>\tspecify a file that contains a trusted DNSSEC key (DNSKEY|DS) [**]\n");
-       fprintf(stream, "\t\t\tused to verify any signatures in the current answer\n");
-       fprintf(stream, "\t-o <mnemonic>\tset flags to: [QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n");
+       fprintf(stream, "\t-c <file>\tuse file for rescursive nameserver configuration"
+                       "\n\t\t\t(/etc/resolv.conf)\n");
+       fprintf(stream, "\t-k <file>\tspecify a file that contains a trusted DNSSEC key [**]\n");
+       fprintf(stream, "\t\t\tUsed to verify any signatures in the current answer.\n");
+       fprintf(stream, "\t\t\tWhen DNSSEC enabled tracing (-TD) or signature\n"
+                       "\t\t\tchasing (-S) and no key files are given, keys are read\n"
+                       "\t\t\tfrom: %s\n",
+                       LDNS_TRUST_ANCHOR_FILE);
+       fprintf(stream, "\t-o <mnemonic>\tset flags to:"
+                       "\n\t\t\t[QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n");
        fprintf(stream, "\t\t\tlowercase: unset bit, uppercase: set bit\n");
        fprintf(stream, "\t-p <port>\tuse <port> as remote port number\n");
        fprintf(stream, "\t-s\t\tshow the DS RR for each key in a packet\n");
        fprintf(stream, "\t-u\t\tsend the query with udp (the default)\n");
        fprintf(stream, "\t-x\t\tdo a reverse lookup\n");
        fprintf(stream, "\twhen doing a secure trace:\n");
-       fprintf(stream, "\t-r <file>\t\tuse file as root servers hint file\n");
+       fprintf(stream, "\t-r <file>\tuse file as root servers hint file\n");
        fprintf(stream, "\t-t\t\tsend the query with tcp (connected)\n");
-       fprintf(stream, "\t-d <domain>\t\tuse domain as the start point for the trace\n");
+       fprintf(stream, "\t-d <domain>\tuse domain as the start point for the trace\n");
     fprintf(stream, "\t-y <name:key[:algo]>\tspecify named base64 tsig key, and optional an\n\t\t\talgorithm (defaults to hmac-md5.sig-alg.reg.int)\n");
        fprintf(stream, "\t-z\t\tdon't randomize the nameservers before use\n");
        fprintf(stream, "\n  [*] = enables/implies DNSSEC\n");
@@ -97,7 +103,7 @@ main(int argc, char *argv[])
         ldns_pkt       *pkt;
         ldns_pkt       *qpkt;
         char           *serv;
-        char           *name;
+        const char     *name;
         char           *name2;
        char            *progname;
        char            *query_file = NULL;
@@ -221,6 +227,10 @@ main(int argc, char *argv[])
                                break;
 #endif /* HAVE_SSL */
                        case 'V':
+                               if (strtok(optarg, "0123456789") != NULL) {
+                                       fprintf(stderr, "-V expects an number as an argument.\n");
+                                       exit(EXIT_FAILURE);
+                               }
                                verbosity = atoi(optarg);
                                break;
                        case 'Q':
@@ -268,7 +278,8 @@ main(int argc, char *argv[])
                                qusevc = true;
                                break;
                        case 'k':
-                               status = read_key_file(optarg, key_list);
+                               status = read_key_file(optarg,
+                                               key_list, false);
                                if (status != LDNS_STATUS_OK) {
                                        error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status));
                                }
@@ -393,6 +404,15 @@ main(int argc, char *argv[])
        argc -= optind;
        argv += optind;
 
+       if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) &&
+                       ldns_rr_list_rr_count(key_list) == 0) {
+
+               (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true);
+       }
+       if (ldns_rr_list_rr_count(key_list) > 0) {
+               printf(";; Number of trusted keys: %d\n",
+                               (int) ldns_rr_list_rr_count(key_list));
+       }
        /* do a secure trace when requested */
        if (PURPOSE == DRILL_TRACE && qdnssec) {
 #ifdef HAVE_SSL
diff --git a/contrib/ldns/drill/drill.h b/contrib/ldns/drill/drill.h
new file mode 100644 (file)
index 0000000..0746fe7
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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_REVERSE  6
+#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 bool qds;
+extern int verbosity;
+
+ldns_pkt *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 verbosity);
+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_ */
index 596be9d..db0433e 100644 (file)
 #include <errno.h>
 
 static int
-read_line(FILE *input, char *line)
+read_line(FILE *input, char *line, size_t len)
 {
        int i;
        
        char c;
-       for (i = 0; i < LDNS_MAX_PACKETLEN; i++) {
-               c = getc(input);
+       for (i = 0; i < (int)len-1; i++) {
+               c = (char)getc(input);
                if (c == EOF) {
                        return -1;
                } else if (c != '\n') {
@@ -35,32 +35,37 @@ read_line(FILE *input, char *line)
 
 /* key_list must be initialized with ldns_rr_list_new() */
 ldns_status
-read_key_file(const char *filename, ldns_rr_list *key_list)
+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_PACKETLEN];
+       char line[LDNS_MAX_LINELEN];
        ldns_status status;
        FILE *input_file;
        ldns_rr *rr;
 
        input_file = fopen(filename, "r");
        if (!input_file) {
-               fprintf(stderr, "Error opening %s: %s\n",
-                       filename, strerror(errno));
+               if (! silently) {
+                       fprintf(stderr, "Error opening %s: %s\n",
+                               filename, strerror(errno));
+               }
                return LDNS_STATUS_ERR;
        }
        while (line_len >= 0) {
-               line_len = read_line(input_file, line);
+               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) {
-                               fprintf(stderr,
-                                               "Error parsing DNSKEY RR in line %d: %s\n",
-                                               line_nr,
-                                               ldns_get_errorstr_by_id(status));
+                               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);
@@ -70,7 +75,7 @@ read_key_file(const char *filename, ldns_rr_list *key_list)
                        }
                }
        }
-       printf(";; Number of trusted keys: %d\n", key_count);
+       fclose(input_file);
        if (key_count > 0) {
                return LDNS_STATUS_OK;
        } else {
@@ -132,6 +137,7 @@ print_ds_of_keys(ldns_pkt *p)
                        ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA256);
                        local_print_ds(stdout, "; sha256: ", ds);
                }
+               ldns_rr_list_deep_free(keys);
        }
 }
 
@@ -240,7 +246,7 @@ print_dnskey_abbr(FILE *fp, ldns_rr *key)
 }
 
 void
-print_rr_list_abbr(FILE *fp, ldns_rr_list *rrlist, char *usr) 
+print_rr_list_abbr(FILE *fp, ldns_rr_list *rrlist, const char *usr) 
 {
        size_t i;
        ldns_rr_type tp;
index db3a574..42b3f32 100644 (file)
 #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
@@ -39,7 +46,7 @@ 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, char *usr);
+void print_rr_list_abbr(FILE *fp, ldns_rr_list *sig, const char *usr);
 
 /**
  * Alloc some memory, with error checking
index c08b040..c6e7e58 100644 (file)
@@ -129,11 +129,8 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
 {
        ldns_resolver *res;
        ldns_pkt *p, *local_p;
-       ldns_rr_list *new_nss_a;
-       ldns_rr_list *new_nss_aaaa;
        ldns_rr_list *new_nss;
        ldns_rr_list *ns_addr;
-       uint16_t loop_count;
        ldns_rdf *pop;
        ldns_rdf **labels = NULL;
        ldns_status status, st;
@@ -142,7 +139,6 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
        size_t k;
        size_t l;
        uint8_t labels_count;
-       ldns_pkt_type pt;
 
        /* dnssec */
        ldns_rr_list *key_list;
@@ -173,14 +169,10 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
 
        descriptor = ldns_rr_descript(t);
 
-       loop_count = 0;
-       new_nss_a = NULL;
-       new_nss_aaaa = NULL;
        new_nss = NULL;
        ns_addr = NULL;
        key_list = NULL;
        ds_list = NULL;
-       pt = LDNS_PACKET_UNKNOWN;
 
        p = NULL;
        local_p = NULL;
@@ -239,7 +231,8 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
        if (status != LDNS_STATUS_OK) {
                printf("ERRRRR: %s\n", ldns_get_errorstr_by_id(status));
                ldns_rr_list_print(stdout, global_dns_root);
-               return status;
+               result = status;
+               goto done;
        }
        labels_count = ldns_dname_label_count(name);
        if (start_name) {
@@ -400,7 +393,6 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
                                        printf(";; There is an empty non-terminal here, continue\n");
                                        continue;
                                }
-                               goto done;
                        }
 
                        if (ldns_resolver_nameserver_count(res) == 0) {
@@ -419,7 +411,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
                   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);
-               pt = get_key(p, labels[i], &key_list, &key_sig_list);
+               (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();
@@ -490,14 +482,14 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
                /* check the DS records for the next child domain */
                if (i > 1) {
                        p = get_dnssec_pkt(res, labels[i-1], LDNS_RR_TYPE_DS);
-                       pt = get_ds(p, labels[i-1], &ds_list, &ds_sig_list);
+                       (void) get_ds(p, labels[i-1], &ds_list, &ds_sig_list);
                        if (!ds_list) {
                                ldns_pkt_free(p);
                                if (ds_sig_list) {
                                        ldns_rr_list_deep_free(ds_sig_list);
                                }
                                p = get_dnssec_pkt(res, name, LDNS_RR_TYPE_DNSKEY);
-                               pt = get_ds(p, NULL, &ds_list, &ds_sig_list); 
+                               (void) get_ds(p, NULL, &ds_list, &ds_sig_list); 
                        }
                        if (ds_sig_list) {
                                if (ds_list) {
@@ -560,7 +552,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
                                        ldns_pkt_free(p);
                                        ldns_rr_list_deep_free(ds_sig_list);
                                        p = get_dnssec_pkt(res, labels[i-1], LDNS_RR_TYPE_DS);
-                                       pt = get_ds(p, labels[i-1], &ds_list, &ds_sig_list);
+                                       (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);
 
@@ -616,7 +608,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
                } else {
                        /* if this is the last label, just verify the data and stop */
                        p = get_dnssec_pkt(res, labels[i], t);
-                       pt = get_dnssec_rr(p, labels[i], t, &dataset, &key_sig_list);
+                       (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) {
 
@@ -721,8 +713,6 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
                        ldns_pkt_free(p);
                }
 
-               new_nss_aaaa = NULL;
-               new_nss_a = NULL;
                new_nss = NULL;
                ns_addr = NULL;
                ldns_rr_list_deep_free(key_list);
index 3a9cb58..653145f 100644 (file)
@@ -122,11 +122,6 @@ packetbuffromfile(char *filename, uint8_t *wire)
                                hexbuf[hexbufpos] = (uint8_t) c;
                                hexbufpos++;
                                break;
-                       default:
-                               warning("unknown state while reading %s", filename);
-                               xfree(hexbuf);
-                               return 0;
-                               break;
                }
                c = fgetc(fp);
        }
@@ -178,20 +173,7 @@ read_hex_buffer(char *filename)
        size_t wiresize;
        ldns_buffer *result_buffer = NULL;
        
-       FILE *fp = NULL;
-       
-       if (strncmp(filename, "-", 2) != 0) {
-               fp = fopen(filename, "r");
-       } else {
-               fp = stdin;
-       }
-       
-       if (fp == NULL) {
-               perror("");
-               warning("Unable to open %s", filename);
-               return NULL;
-       }
-       
+
        wire = xmalloc(LDNS_MAX_PACKETLEN);
        
        wiresize = packetbuffromfile(filename, wire);
@@ -199,8 +181,8 @@ read_hex_buffer(char *filename)
        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;
 }
 
@@ -236,7 +218,7 @@ read_hex_pkt(char *filename)
 void
 dump_hex(const ldns_pkt *pkt, const char *filename)
 {
-       uint8_t *wire;
+       uint8_t *wire = NULL;
        size_t size, i;
        FILE *fp;
        ldns_status status;
@@ -252,6 +234,7 @@ dump_hex(const ldns_pkt *pkt, const char *filename)
        
        if (status != LDNS_STATUS_OK) {
                error("Unable to convert packet: error code %u", status);
+               LDNS_FREE(wire);
                return;
        }
        
@@ -273,4 +256,5 @@ dump_hex(const ldns_pkt *pkt, const char *filename)
        }
        fprintf(fp, "\n");
        fclose(fp);
+       LDNS_FREE(wire);
 }
diff --git a/contrib/ldns/duration.c b/contrib/ldns/duration.c
new file mode 100644 (file)
index 0000000..6d0a388
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * $Id: duration.c 4518 2011-02-24 15:39:09Z matthijs $
+ *
+ * Copyright (c) 2009 NLNet Labs. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ *
+ * This file is copied from the OpenDNSSEC source repository
+ * and only slightly adapted to make it fit.
+ */
+
+/**
+ *
+ * Durations.
+ */
+
+#include <ldns/config.h>
+#include <ldns/duration.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+
+/**
+ * Create a new 'instant' duration.
+ *
+ */
+ldns_duration_type*
+ldns_duration_create(void)
+{
+    ldns_duration_type* duration;
+
+    duration = malloc(sizeof(ldns_duration_type));
+    if (!duration) {
+        return NULL;
+    }
+    duration->years = 0;
+    duration->months = 0;
+    duration->weeks = 0;
+    duration->days = 0;
+    duration->hours = 0;
+    duration->minutes = 0;
+    duration->seconds = 0;
+    return duration;
+}
+
+
+/**
+ * Compare durations.
+ *
+ */
+int
+ldns_duration_compare(ldns_duration_type* d1, ldns_duration_type* d2)
+{
+    if (!d1 && !d2) {
+        return 0;
+    }
+    if (!d1 || !d2) {
+        return d1?-1:1;
+    }
+
+    if (d1->years != d2->years) {
+        return (int) (d1->years - d2->years);
+    }
+    if (d1->months != d2->months) {
+        return (int) (d1->months - d2->months);
+    }
+    if (d1->weeks != d2->weeks) {
+        return (int) (d1->weeks - d2->weeks);
+    }
+    if (d1->days != d2->days) {
+        return (int) (d1->days - d2->days);
+    }
+    if (d1->hours != d2->hours) {
+        return (int) (d1->hours - d2->hours);
+    }
+    if (d1->minutes != d2->minutes) {
+        return (int) (d1->minutes - d2->minutes);
+    }
+    if (d1->seconds != d2->seconds) {
+        return (int) (d1->seconds - d2->seconds);
+    }
+
+    return 0;
+}
+
+
+/**
+ * Create a duration from string.
+ *
+ */
+ldns_duration_type*
+ldns_duration_create_from_string(const char* str)
+{
+    ldns_duration_type* duration = ldns_duration_create();
+    char* P, *X, *T, *W;
+    int not_weeks = 0;
+
+    if (!duration) {
+        return NULL;
+    }
+    if (!str) {
+        return duration;
+    }
+
+    P = strchr(str, 'P');
+    if (!P) {
+       ldns_duration_cleanup(duration);
+        return NULL;
+    }
+
+    T = strchr(str, 'T');
+    X = strchr(str, 'Y');
+    if (X) {
+        duration->years = (time_t) atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    X = strchr(str, 'M');
+    if (X && (!T || (size_t) (X-P) < (size_t) (T-P))) {
+        duration->months = (time_t) atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    X = strchr(str, 'D');
+    if (X) {
+        duration->days = (time_t) atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    if (T) {
+        str = T;
+        not_weeks = 1;
+    }
+    X = strchr(str, 'H');
+    if (X && T) {
+        duration->hours = (time_t) atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    X = strrchr(str, 'M');
+    if (X && T && (size_t) (X-P) > (size_t) (T-P)) {
+        duration->minutes = (time_t) atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    X = strchr(str, 'S');
+    if (X && T) {
+        duration->seconds = (time_t) atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+
+    W = strchr(str, 'W');
+    if (W) {
+        if (not_weeks) {
+            ldns_duration_cleanup(duration);
+            return NULL;
+        } else {
+            duration->weeks = (time_t) atoi(str+1);
+            str = W;
+        }
+    }
+    return duration;
+}
+
+
+/**
+ * Get the number of digits in a number.
+ *
+ */
+static size_t
+digits_in_number(time_t duration)
+{
+    uint32_t period = (uint32_t) duration;
+    size_t count = 0;
+
+    while (period > 0) {
+        count++;
+        period /= 10;
+    }
+    return count;
+}
+
+
+/**
+ * Convert a duration to a string.
+ *
+ */
+char*
+ldns_duration2string(ldns_duration_type* duration)
+{
+    char* str = NULL, *num = NULL;
+    size_t count = 2;
+    int T = 0;
+
+    if (!duration) {
+        return NULL;
+    }
+
+    if (duration->years > 0) {
+        count = count + 1 + digits_in_number(duration->years);
+    }
+    if (duration->months > 0) {
+        count = count + 1 + digits_in_number(duration->months);
+    }
+    if (duration->weeks > 0) {
+        count = count + 1 + digits_in_number(duration->weeks);
+    }
+    if (duration->days > 0) {
+        count = count + 1 + digits_in_number(duration->days);
+    }
+    if (duration->hours > 0) {
+        count = count + 1 + digits_in_number(duration->hours);
+        T = 1;
+    }
+    if (duration->minutes > 0) {
+        count = count + 1 + digits_in_number(duration->minutes);
+        T = 1;
+    }
+    if (duration->seconds > 0) {
+        count = count + 1 + digits_in_number(duration->seconds);
+        T = 1;
+    }
+    if (T) {
+        count++;
+    }
+
+    str = (char*) calloc(count, sizeof(char));
+    str[0] = 'P';
+    str[1] = '\0';
+
+    if (duration->years > 0) {
+        count = digits_in_number(duration->years);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uY", (unsigned int) duration->years);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->months > 0) {
+        count = digits_in_number(duration->months);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uM", (unsigned int) duration->months);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->weeks > 0) {
+        count = digits_in_number(duration->weeks);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uW", (unsigned int) duration->weeks);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->days > 0) {
+        count = digits_in_number(duration->days);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uD", (unsigned int) duration->days);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (T) {
+        str = strncat(str, "T", 1);
+    }
+    if (duration->hours > 0) {
+        count = digits_in_number(duration->hours);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uH", (unsigned int) duration->hours);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->minutes > 0) {
+        count = digits_in_number(duration->minutes);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uM", (unsigned int) duration->minutes);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->seconds > 0) {
+        count = digits_in_number(duration->seconds);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uS", (unsigned int) duration->seconds);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    return str;
+}
+
+
+/**
+ * Convert a duration to a time.
+ *
+ */
+time_t
+ldns_duration2time(ldns_duration_type* duration)
+{
+    time_t period = 0;
+
+    if (duration) {
+        period += (duration->seconds);
+        period += (duration->minutes)*60;
+        period += (duration->hours)*3600;
+        period += (duration->days)*86400;
+        period += (duration->weeks)*86400*7;
+        period += (duration->months)*86400*31;
+        period += (duration->years)*86400*365;
+
+        /* [TODO] calculate correct number of days in this month/year */
+       /*
+        if (duration->months || duration->years) {
+        }
+       */
+    }
+    return period;
+}
+
+
+/**
+ * Clean up duration.
+ *
+ */
+void
+ldns_duration_cleanup(ldns_duration_type* duration)
+{
+    if (!duration) {
+        return;
+    }
+    free(duration);
+    return;
+}
index a619502..2fc63e9 100644 (file)
@@ -29,6 +29,7 @@ ldns_lookup_table ldns_error_str[] = {
         { LDNS_STATUS_INVALID_IP4, "Conversion error, ip4 addr expected" },
         { LDNS_STATUS_INVALID_IP6, "Conversion error, ip6 addr expected" },
         { LDNS_STATUS_INVALID_STR, "Conversion error, string expected" },
+       { LDNS_STATUS_INVALID_B32_EXT, "Conversion error, b32 ext encoding expected" },
         { LDNS_STATUS_INVALID_B64, "Conversion error, b64 encoding expected" },
         { LDNS_STATUS_INVALID_HEX, "Conversion error, hex encoding expected" },
         { LDNS_STATUS_INVALID_TIME, "Conversion error, time encoding expected" },
@@ -90,6 +91,39 @@ ldns_lookup_table ldns_error_str[] = {
        { LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND, "original of NSEC3 hashed name could not be found" },
        { LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG, "The RRSIG has to few rdata fields" },
        { LDNS_STATUS_MISSING_RDATA_FIELDS_KEY, "The DNSKEY has to few rdata fields" },
+       { LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN, 
+               "DNSSEC signature will expire too soon" },
+       { LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN,
+               "DNSSEC signature not incepted long enough" },
+       { LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE,
+               "Unknown TLSA Certificate Usage" },
+       { LDNS_STATUS_DANE_UNKNOWN_SELECTOR, "Unknown TLSA Selector" },
+       { LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE,
+               "Unknown TLSA Matching Type" },
+       { LDNS_STATUS_DANE_UNKNOWN_PROTOCOL,
+               "Unknown protocol. Only IPv4 and IPv6 are understood" },
+       { LDNS_STATUS_DANE_UNKNOWN_TRANSPORT,
+               "Unknown transport. Should be one of {tcp, udp, sctp}" },
+       { LDNS_STATUS_DANE_MISSING_EXTRA_CERTS,  /* Trust anchor assertion */
+               "More than one certificate should be provided" },
+       { LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED, /* Trust anchor assertion */
+               "Non of the extra certificates is used to sign the first" },
+       { LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE,   /* Trust anchor assertion */
+               "The offset was out of range" },
+       { LDNS_STATUS_DANE_INSECURE,             /* Unused by library */
+               "The queried resource records were insecure" },
+       { LDNS_STATUS_DANE_BOGUS,             /* Unused by library */
+               "The queried resource records were bogus" },
+       { LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
+               "The TLSA record(s) "
+               "did not match with the server certificate (chain)" },
+       { LDNS_STATUS_DANE_NON_CA_CERTIFICATE,
+               "The certificate was not a CA certificate" },
+       { LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE,
+               "Could not PKIX validate" },
+       { LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR,
+               "The validation path "
+               "did not end in a self-signed certificate" },
        { 0, NULL }
 };
 
index c9eb173..990fb6a 100644 (file)
@@ -126,6 +126,7 @@ ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class
        
        /* add the RD flags, because we want an answer */
        pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD);
+       ldns_rdf_deep_free(name);
        if (pkt) {
                /* extract the data we need */
                names = ldns_pkt_rr_list_by_type(pkt, 
index eff1216..521e246 100644 (file)
@@ -123,6 +123,7 @@ const ldns_output_format  *ldns_output_format_onlykeyids
                        = &ldns_output_format_onlykeyids_record;
 const ldns_output_format  *ldns_output_format_default
                        = &ldns_output_format_onlykeyids_record;
+
 const ldns_output_format   ldns_output_format_bubblebabble_record = { 
        LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL
 };
@@ -195,7 +196,7 @@ ldns_pkt_opcode2str(ldns_pkt_opcode opcode)
 
        str = NULL;
        if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) {
-               str = ldns_buffer2str(buf);
+               str = ldns_buffer_export2str(buf);
        }
 
        ldns_buffer_free(buf);
@@ -215,7 +216,7 @@ ldns_pkt_rcode2str(ldns_pkt_rcode rcode)
 
        str = NULL;
        if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) {
-               str = ldns_buffer2str(buf);
+               str = ldns_buffer_export2str(buf);
        }
 
        ldns_buffer_free(buf);
@@ -236,7 +237,7 @@ ldns_pkt_algorithm2str(ldns_algorithm algorithm)
        str = NULL;
        if (ldns_algorithm2buffer_str(buf, algorithm)
            == LDNS_STATUS_OK) {
-               str = ldns_buffer2str(buf);
+               str = ldns_buffer_export2str(buf);
        }
 
        ldns_buffer_free(buf);
@@ -257,7 +258,7 @@ ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm)
        str = NULL;
        if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm)
            == LDNS_STATUS_OK) {
-               str = ldns_buffer2str(buf);
+               str = ldns_buffer_export2str(buf);
        }
 
        ldns_buffer_free(buf);
@@ -567,7 +568,7 @@ ldns_rr_type2str(const ldns_rr_type type)
 
        str = NULL;
        if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) {
-               str = ldns_buffer2str(buf);
+               str = ldns_buffer_export2str(buf);
        }
 
        ldns_buffer_free(buf);
@@ -603,7 +604,7 @@ ldns_rr_class2str(const ldns_rr_class klass)
 
        str = NULL;
        if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) {
-               str = ldns_buffer2str(buf);
+               str = ldns_buffer_export2str(buf);
        }
        ldns_buffer_free(buf);
        return str;
@@ -1149,8 +1150,9 @@ ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
                        break;
                }
        } else {
+               /** This will write mangled RRs */
                ldns_buffer_printf(buffer, "(null) ");
-               res = ldns_buffer_status(buffer);
+               res = LDNS_STATUS_ERR;
        }
        return res;
 }
@@ -1230,7 +1232,33 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output,
 
        for (i = 0; i < ldns_rr_rd_count(rr); i++) {
                /* ldns_rdf2buffer_str handles NULL input fine! */
-               status = ldns_rdf2buffer_str(output, ldns_rr_rdf(rr, i));
+               if ((fmt->flags & LDNS_FMT_ZEROIZE_RRSIGS) &&
+                               (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) &&
+                               ((/* inception  */ i == 4 &&
+                                 ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) == 
+                                                       LDNS_RDF_TYPE_TIME) ||
+                                 (/* expiration */ i == 5 &&
+                                  ldns_rdf_get_type(ldns_rr_rdf(rr, 5)) ==
+                                                       LDNS_RDF_TYPE_TIME) ||
+                                 (/* signature  */ i == 8 &&
+                                  ldns_rdf_get_type(ldns_rr_rdf(rr, 8)) ==
+                                                       LDNS_RDF_TYPE_B64))) {
+
+                       ldns_buffer_printf(output, "(null)");
+                       status = ldns_buffer_status(output);
+               } else if ((fmt->flags & LDNS_FMT_PAD_SOA_SERIAL) &&
+                               (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) &&
+                               /* serial */ i == 2 &&
+                               ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) ==
+                                                       LDNS_RDF_TYPE_INT32) {
+                       ldns_buffer_printf(output, "%10lu",
+                               (unsigned long) ldns_read_uint32(
+                                       ldns_rdf_data(ldns_rr_rdf(rr, 2))));
+                       status = ldns_buffer_status(output);
+               } else {
+                       status = ldns_rdf2buffer_str(output,
+                                       ldns_rr_rdf(rr, i));
+               }
                if(status != LDNS_STATUS_OK)
                        return status;
                if (i < ldns_rr_rd_count(rr) - 1) {
@@ -1633,12 +1661,12 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
 {
        ldns_status status = LDNS_STATUS_OK;
        unsigned char  *bignum;
-#ifndef S_SPLINT_S
-       uint16_t i;
-#endif
-
 #ifdef HAVE_SSL
+#  ifndef S_SPLINT_S
+       uint16_t i;
+#  endif
        /* not used when ssl is not defined */
+       /*@unused@*/
        ldns_rdf *b64_bignum = NULL;
 
        RSA *rsa;
@@ -1716,6 +1744,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                }
                                b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                       ldns_rdf_deep_free(b64_bignum);
                                        goto error;
                                }
                                ldns_rdf_deep_free(b64_bignum);
@@ -1727,6 +1756,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                }
                                b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                       ldns_rdf_deep_free(b64_bignum);
                                        goto error;
                                }
                                ldns_rdf_deep_free(b64_bignum);
@@ -1740,6 +1770,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1756,6 +1787,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1772,6 +1804,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1788,6 +1821,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1804,6 +1838,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1820,6 +1855,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1853,6 +1889,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1869,6 +1906,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1885,6 +1923,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1901,6 +1940,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1917,6 +1957,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
@@ -1938,12 +1979,13 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                        NULL
 #endif
                                );
-
-#endif
+#else
+                               goto error;
+#endif /* GOST */
                                break;
-#ifdef USE_ECDSA
                        case LDNS_SIGN_ECDSAP256SHA256:
                        case LDNS_SIGN_ECDSAP384SHA384:
+#ifdef USE_ECDSA
                                 ldns_buffer_printf(output, "Private-key-format: v1.2\n");
                                ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
                                 status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
@@ -1959,6 +2001,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                         }
                                         b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                         if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                               ldns_rdf_deep_free(b64_bignum);
                                                 goto error;
                                         }
                                         ldns_rdf_deep_free(b64_bignum);
@@ -1968,8 +2011,10 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                         EC_KEY_free(ec);
                                 }
 #endif /* splint */
+#else
+                               goto error;
+#endif /* ECDSA */
                                 break;
-#endif
                        case LDNS_SIGN_HMACMD5:
                                /* there's not much of a format defined for TSIG */
                                /* It's just a binary blob, Same for all algorithms */
@@ -1990,9 +2035,6 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                }
 #endif /* HAVE_SSL */
        } else {
-#ifdef HAVE_SSL
-               LDNS_FREE(b64_bignum);
-#endif
                LDNS_FREE(bignum);
                return ldns_buffer_status(output);
        }
@@ -2009,12 +2051,11 @@ error:
 }
 
 /*
- * Zero terminate the buffer and fix it to the size of the string.
+ * Zero terminate the buffer and copy data.
  */
 char *
 ldns_buffer2str(ldns_buffer *buffer)
 {
-       char *tmp_str;
        char *str;
 
        /* check if buffer ends with \0, if not, and
@@ -2029,16 +2070,30 @@ ldns_buffer2str(ldns_buffer *buffer)
                }
        }
 
-       tmp_str = ldns_buffer_export(buffer);
-       str = LDNS_XMALLOC(char, strlen(tmp_str) + 1);
+       str = strdup((const char *)ldns_buffer_begin(buffer));
         if(!str) {
                 return NULL;
         }
-       memcpy(str, tmp_str, strlen(tmp_str) + 1);
-
        return str;
 }
 
+/*
+ * Zero terminate the buffer and export data.
+ */
+char *
+ldns_buffer_export2str(ldns_buffer *buffer)
+{
+       /* Append '\0' as string terminator */
+       if (! ldns_buffer_reserve(buffer, 1)) {
+               return NULL;
+       }
+       ldns_buffer_write_u8(buffer, 0);
+
+       /* reallocate memory to the size of the string and export */
+       ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer));
+       return ldns_buffer_export(buffer);
+}
+
 char *
 ldns_rdf2str(const ldns_rdf *rdf)
 {
@@ -2050,7 +2105,7 @@ ldns_rdf2str(const ldns_rdf *rdf)
        }
        if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) {
                /* export and return string, destroy rest */
-               result = ldns_buffer2str(tmp_buffer);
+               result = ldns_buffer_export2str(tmp_buffer);
        }
        ldns_buffer_free(tmp_buffer);
        return result;
@@ -2068,7 +2123,7 @@ ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr)
        if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr)
                        == LDNS_STATUS_OK) {
                /* export and return string, destroy rest */
-               result = ldns_buffer2str(tmp_buffer);
+               result = ldns_buffer_export2str(tmp_buffer);
        }
        ldns_buffer_free(tmp_buffer);
        return result;
@@ -2092,7 +2147,7 @@ ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt)
        if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt)
                        == LDNS_STATUS_OK) {
                /* export and return string, destroy rest */
-               result = ldns_buffer2str(tmp_buffer);
+               result = ldns_buffer_export2str(tmp_buffer);
        }
 
        ldns_buffer_free(tmp_buffer);
@@ -2116,7 +2171,7 @@ ldns_key2str(const ldns_key *k)
        }
        if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) {
                /* export and return string, destroy rest */
-               result = ldns_buffer2str(tmp_buffer);
+               result = ldns_buffer_export2str(tmp_buffer);
        }
        ldns_buffer_free(tmp_buffer);
        return result;
@@ -2146,7 +2201,7 @@ ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list)
        }
 
        /* export and return string, destroy rest */
-       result = ldns_buffer2str(tmp_buffer);
+       result = ldns_buffer_export2str(tmp_buffer);
        ldns_buffer_free(tmp_buffer);
        return result;
 }
@@ -2164,20 +2219,20 @@ ldns_rdf_print(FILE *output, const ldns_rdf *rdf)
        if (str) {
                fprintf(output, "%s", str);
        } else {
-               fprintf(output, "Unable to convert rdf to string\n");
+               fprintf(output, ";Unable to convert rdf to string\n");
        }
        LDNS_FREE(str);
 }
 
 void
-ldns_rr_print_fmt(FILE *output, 
+ldns_rr_print_fmt(FILE *output,
                const ldns_output_format *fmt, const ldns_rr *rr)
 {
        char *str = ldns_rr2str_fmt(fmt, rr);
        if (str) {
                fprintf(output, "%s", str);
        } else {
-               fprintf(output, "Unable to convert rr to string\n");
+               fprintf(output, ";Unable to convert rr to string\n");
        }
        LDNS_FREE(str);
 }
@@ -2196,7 +2251,7 @@ ldns_pkt_print_fmt(FILE *output,
        if (str) {
                fprintf(output, "%s", str);
        } else {
-               fprintf(output, "Unable to convert packet to string\n");
+               fprintf(output, ";Unable to convert packet to string\n");
        }
        LDNS_FREE(str);
 }
index ca28dba..de1e01e 100644 (file)
@@ -113,6 +113,7 @@ ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
        case LDNS_RR_TYPE_SRV:
        case LDNS_RR_TYPE_DNAME:
        case LDNS_RR_TYPE_A6:
+       case LDNS_RR_TYPE_RRSIG:
                pre_rfc3597 = true;
                break;
        default:
@@ -205,7 +206,7 @@ ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
        /* Convert all the rdfs, except the actual signature data
         * rdf number 8  - the last, hence: -1 */
        for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
-               (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
+               (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_rdf(rr, i));
        }
 
        return ldns_buffer_status(buffer);
@@ -340,7 +341,6 @@ ldns_status
 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
 {
        ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
-       uint8_t *result = NULL;
        ldns_status status;
        *result_size = 0;
        *dest = NULL;
@@ -349,21 +349,8 @@ ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
        status = ldns_rdf2buffer_wire(buffer, rdf);
        if (status == LDNS_STATUS_OK) {
                *result_size =  ldns_buffer_position(buffer);
-               result = (uint8_t *) ldns_buffer_export(buffer);
-       } else {
-               ldns_buffer_free(buffer);
-               return status;
-       }
-       
-       if (result) {
-               *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
-               if(!*dest) {
-                       ldns_buffer_free(buffer);
-                       return LDNS_STATUS_MEM_ERR;
-               }
-               memcpy(*dest, result, ldns_buffer_position(buffer));
+               *dest = (uint8_t *) ldns_buffer_export(buffer);
        }
-       
        ldns_buffer_free(buffer);
        return status;
 }
@@ -372,7 +359,6 @@ ldns_status
 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
 {
        ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
-       uint8_t *result = NULL;
        ldns_status status;
        *result_size = 0;
        *dest = NULL;
@@ -381,21 +367,8 @@ ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size
        status = ldns_rr2buffer_wire(buffer, rr, section);
        if (status == LDNS_STATUS_OK) {
                *result_size =  ldns_buffer_position(buffer);
-               result = (uint8_t *) ldns_buffer_export(buffer);
-       } else {
-               ldns_buffer_free(buffer);
-               return status;
-       }
-       
-       if (result) {
-               *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
-               if(!*dest) {
-                       ldns_buffer_free(buffer);
-                       return LDNS_STATUS_MEM_ERR;
-               }
-               memcpy(*dest, result, ldns_buffer_position(buffer));
+               *dest = (uint8_t *) ldns_buffer_export(buffer);
        }
-       
        ldns_buffer_free(buffer);
        return status;
 }
@@ -404,7 +377,6 @@ ldns_status
 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
 {
        ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
-       uint8_t *result = NULL;
        ldns_status status;
        *result_size = 0;
        *dest = NULL;
@@ -413,21 +385,8 @@ ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
        status = ldns_pkt2buffer_wire(buffer, packet);
        if (status == LDNS_STATUS_OK) {
                *result_size =  ldns_buffer_position(buffer);
-               result = (uint8_t *) ldns_buffer_export(buffer);
-       } else {
-               ldns_buffer_free(buffer);
-               return status;
+               *dest = (uint8_t *) ldns_buffer_export(buffer);
        }
-       
-       if (result) {
-               *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
-               if(!*dest) {
-                       ldns_buffer_free(buffer);
-                       return LDNS_STATUS_MEM_ERR;
-               }
-               memcpy(*dest, result, ldns_buffer_position(buffer));
-       }
-       
        ldns_buffer_free(buffer);
        return status;
 }
index 2d7f62a..de7c946 100644 (file)
@@ -314,7 +314,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
 
        /* the file is highly structured. Do this in sequence */
        /* RSA:
-        * Private-key-format: v1.2
+        * Private-key-format: v1.x.
         * Algorithm: 1 (RSA)
 
         */
@@ -326,7 +326,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                 LDNS_FREE(d);
                return LDNS_STATUS_SYNTAX_ERR;
        }
-       if (strncmp(d, "v1.2", strlen(d)) != 0) {
+       if (strncmp(d, "v1.", 3) != 0) {
                 ldns_key_free(k);
                 LDNS_FREE(d);
                return LDNS_STATUS_SYNTAX_VERSION_ERR;
@@ -388,14 +388,22 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                fprintf(stderr, "version of ldns, use --enable-gost\n");
 #endif
        }
-#ifdef USE_ECDSA
        if (strncmp(d, "13 ECDSAP256SHA256", 3) == 0) {
+#ifdef USE_ECDSA
                 alg = LDNS_SIGN_ECDSAP256SHA256;
+#else
+               fprintf(stderr, "Warning: ECDSA not compiled into this ");
+               fprintf(stderr, "version of ldns, use --enable-ecdsa\n");
+#endif
         }
        if (strncmp(d, "14 ECDSAP384SHA384", 3) == 0) {
+#ifdef USE_ECDSA
                 alg = LDNS_SIGN_ECDSAP384SHA384;
-        }
+#else
+               fprintf(stderr, "Warning: ECDSA not compiled into this ");
+               fprintf(stderr, "version of ldns, use --enable-ecdsa\n");
 #endif
+        }
        if (strncmp(d, "157 HMAC-MD5", 4) == 0) {
                alg = LDNS_SIGN_HMACMD5;
        }
@@ -423,8 +431,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                                ldns_key_free(k);
                                return LDNS_STATUS_ERR;
                        }
-                       ldns_key_set_rsa_key(k, rsa);
-                       RSA_free(rsa);
+                       ldns_key_assign_rsa_key(k, rsa);
 #endif /* HAVE_SSL */
                        break;
                case LDNS_SIGN_DSA:
@@ -436,8 +443,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                                ldns_key_free(k);
                                return LDNS_STATUS_ERR;
                        }
-                       ldns_key_set_dsa_key(k, dsa);
-                       DSA_free(dsa);
+                       ldns_key_assign_dsa_key(k, dsa);
 #endif /* HAVE_SSL */
                        break;
                case LDNS_SIGN_HMACMD5:
@@ -497,6 +503,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                *key = k;
                return LDNS_STATUS_OK;
        }
+       ldns_key_free(k);
        return LDNS_STATUS_ERR;
 }
 
@@ -651,15 +658,13 @@ ldns_key_new_frm_fp_dsa(FILE *f)
 }
 
 DSA *
-ldns_key_new_frm_fp_dsa_l(FILE *f, int *line_nr)
+ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
 {
        int i;
        char *d;
        DSA *dsa;
        uint8_t *buf;
 
-       line_nr = line_nr;
-
        d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
        buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN);
        dsa = DSA_new();
@@ -740,32 +745,26 @@ ldns_key_new_frm_fp_hmac(FILE *f, size_t *hmac_size)
 }
 
 unsigned char *
-ldns_key_new_frm_fp_hmac_l(FILE *f, int *line_nr, size_t *hmac_size)
+ldns_key_new_frm_fp_hmac_l( FILE *f
+                         , ATTR_UNUSED(int *line_nr)
+                         , size_t *hmac_size
+                         )
 {
-       size_t i;
-       char *d;
-       unsigned char *buf;
-
-       line_nr = line_nr;
-
-       d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
-       buf = LDNS_XMALLOC(unsigned char, LDNS_MAX_LINELEN);
-        if(!d || !buf) {
-                goto error;
-        }
+       size_t i, bufsz;
+       char d[LDNS_MAX_LINELEN];
+       unsigned char *buf = NULL;
 
        if (ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
                goto error;
        }
-       i = (size_t) ldns_b64_pton((const char*)d,
-                                  buf,
-                                  ldns_b64_ntop_calculate_size(strlen(d)));
+       bufsz = ldns_b64_ntop_calculate_size(strlen(d));
+       buf = LDNS_XMALLOC(unsigned char, bufsz);
+       i = (size_t) ldns_b64_pton((const char*)d, buf, bufsz);
 
        *hmac_size = i;
        return buf;
 
        error:
-       LDNS_FREE(d);
        LDNS_FREE(buf);
        *hmac_size = 0;
        return NULL;
@@ -843,6 +842,7 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
                                return NULL;
                        }
                        ldns_key_set_rsa_key(k, r);
+                       RSA_free(r);
 #endif /* HAVE_SSL */
                        break;
                case LDNS_SIGN_DSA:
@@ -858,6 +858,7 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
                                return NULL;
                        }
                        ldns_key_set_dsa_key(k, d);
+                       DSA_free(d);
 #endif /* HAVE_SSL */
                        break;
                case LDNS_SIGN_HMACMD5:
@@ -906,11 +907,14 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
                                 return NULL;
                         }
 #endif /* splint */
+#else
+                       ldns_key_free(k);
+                       return NULL;
 #endif /* HAVE_SSL and USE_GOST */
                         break;
-#ifdef USE_ECDSA
                 case LDNS_SIGN_ECDSAP256SHA256:
                 case LDNS_SIGN_ECDSAP384SHA384:
+#ifdef USE_ECDSA
                         if(alg == LDNS_SIGN_ECDSAP256SHA256)
                                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
                         else if(alg == LDNS_SIGN_ECDSAP384SHA384)
@@ -937,8 +941,11 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
                                 return NULL;
                        }
 #endif /* splint */
+#else
+                       ldns_key_free(k);
+                       return NULL;
+#endif /* ECDSA */
                        break;
-#endif
        }
        ldns_key_set_algorithm(k, alg);
        return k;
@@ -992,6 +999,22 @@ ldns_key_set_dsa_key(ldns_key *k, DSA *d)
        EVP_PKEY_set1_DSA(key, d);
        k->_key.key  = key;
 }
+
+void
+ldns_key_assign_rsa_key(ldns_key *k, RSA *r)
+{
+       EVP_PKEY *key = EVP_PKEY_new();
+       EVP_PKEY_assign_RSA(key, r);
+       k->_key.key = key;
+}
+
+void
+ldns_key_assign_dsa_key(ldns_key *k, DSA *d)
+{
+       EVP_PKEY *key = EVP_PKEY_new();
+       EVP_PKEY_assign_DSA(key, d);
+       k->_key.key  = key;
+}
 #endif /* splint */
 #endif /* HAVE_SSL */
 
@@ -1289,7 +1312,7 @@ ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size)
        }
        
        /* See RFC2536 */
-       *size = (uint16_t)BN_num_bytes(k->g);
+       *size = (uint16_t)BN_num_bytes(k->p);
        T = (*size - 64) / 8;
        memcpy(data, &T, 1);
 
@@ -1352,10 +1375,10 @@ ldns_key2rr(const ldns_key *k)
 #endif
        int internal_data = 0;
 
-       pubkey = ldns_rr_new();
        if (!k) {
                return NULL;
        }
+       pubkey = ldns_rr_new();
 
        switch (ldns_key_algorithm(k)) {
        case LDNS_SIGN_HMACMD5:
@@ -1466,11 +1489,14 @@ ldns_key2rr(const ldns_key *k)
                        }
 #endif /* splint */
                        internal_data = 1;
+#else
+                        ldns_rr_free(pubkey);
+                       return NULL;
 #endif /* HAVE_SSL and USE_GOST */
                        break;
-#ifdef USE_ECDSA
                 case LDNS_SIGN_ECDSAP256SHA256:
                 case LDNS_SIGN_ECDSAP384SHA384:
+#ifdef USE_ECDSA
                        ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
                                LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
                         bin = NULL;
@@ -1497,8 +1523,11 @@ ldns_key2rr(const ldns_key *k)
                          * to the pkey */
                         EC_KEY_free(ec);
                        internal_data = 1;
+#else
+                        ldns_rr_free(pubkey);
+                       return NULL;
+#endif /* ECDSA */
                         break;
-#endif
                case LDNS_SIGN_HMACMD5:
                case LDNS_SIGN_HMACSHA1:
                case LDNS_SIGN_HMACSHA256:
@@ -1533,6 +1562,7 @@ ldns_key_free(ldns_key *key)
 void
 ldns_key_deep_free(ldns_key *key)
 {
+       unsigned char* hmac;
        if (ldns_key_pubkey_owner(key)) {
                ldns_rdf_deep_free(ldns_key_pubkey_owner(key));
        }
@@ -1542,7 +1572,8 @@ ldns_key_deep_free(ldns_key *key)
        }
 #endif /* HAVE_SSL */
        if (ldns_key_hmac_key(key)) {
-               free(ldns_key_hmac_key(key));
+               hmac = ldns_key_hmac_key(key);
+               LDNS_FREE(hmac);
        }
        LDNS_FREE(key);
 }
@@ -1617,7 +1648,7 @@ ldns_key_get_file_base_name(ldns_key *key)
                           "+%03u+%05u",
                           ldns_key_algorithm(key),
                           ldns_key_keytag(key));
-       file_base_name = strdup(ldns_buffer_export(buffer));
+       file_base_name = ldns_buffer_export(buffer);
        ldns_buffer_free(buffer);
        return file_base_name;
 }
index 03df14c..3b64198 100644 (file)
@@ -630,8 +630,9 @@ void ldns_buffer_free(ldns_buffer *buffer);
 void *ldns_buffer_export(ldns_buffer *buffer);
 
 /**
- * Copy contents of the other buffer to this buffer. Silently truncated
- * if this buffer is too small.
+ * Copy contents of the from buffer to the result buffer and then flips 
+ * the result buffer. Data will be silently truncated if the result buffer is
+ * too small.
  * \param[out] *result resulting buffer which is copied to.
  * \param[in] *from what to copy to result.
  */
diff --git a/contrib/ldns/ldns/dane.h b/contrib/ldns/ldns/dane.h
new file mode 100644 (file)
index 0000000..c1c4e2d
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * dane.h -- defines for the DNS-Based Authentication of Named Entities (DANE)
+ *                           Transport Layer Security (TLS) Protocol: TLSA
+ *
+ * Copyright (c) 2012, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ */
+
+/**
+ * \file
+ *
+ * This module contains base functions for creating and verifying TLSA RR's
+ * with PKIX certificates, certificate chains and validation stores.
+ * (See RFC6394 and RFC6698).
+ * 
+ * Since those functions heavily rely op cryptographic operations,
+ * this module is dependent on openssl.
+ */
+
+#ifndef LDNS_DANE_H
+#define LDNS_DANE_H
+
+#include <ldns/common.h>
+#include <ldns/rdata.h>
+#include <ldns/rr.h>
+#if LDNS_BUILD_CONFIG_HAVE_SSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The different "Certificate usage" rdata field values for a TLSA RR.
+ */
+enum ldns_enum_tlsa_certificate_usage
+{
+       /** CA constraint */
+       LDNS_TLSA_USAGE_CA_CONSTRAINT                   = 0,
+       /** Sevice certificate constraint */
+       LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT  = 1,
+       /** Trust anchor assertion */
+       LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION          = 2,
+       /** Domain issued certificate */
+       LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE       = 3
+};
+typedef enum ldns_enum_tlsa_certificate_usage ldns_tlsa_certificate_usage;
+
+/**
+ * The different "Selector" rdata field values for a TLSA RR.
+ */
+enum ldns_enum_tlsa_selector
+{
+       /** 
+        * Full certificate: the Certificate binary structure
+        * as defined in [RFC5280]
+        */
+       LDNS_TLSA_SELECTOR_FULL_CERTIFICATE     = 0,
+
+       /** 
+        * SubjectPublicKeyInfo: DER-encoded binary structure
+        * as defined in [RFC5280]
+        */
+       LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO = 1
+};
+typedef enum ldns_enum_tlsa_selector ldns_tlsa_selector;
+
+/**
+ * The different "Matching type" rdata field values for a TLSA RR.
+ */
+enum ldns_enum_tlsa_matching_type
+{
+       /** Exact match on selected content */
+       LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED    = 0,
+       /** SHA-256 hash of selected content [RFC6234] */
+       LDNS_TLSA_MATCHING_TYPE_SHA256          = 1,
+       /** SHA-512 hash of selected content [RFC6234] */
+       LDNS_TLSA_MATCHING_TYPE_SHA512          = 2
+};
+typedef enum ldns_enum_tlsa_matching_type ldns_tlsa_matching_type;
+
+/**
+ * Known transports to use with TLSA owner names.
+ */
+enum ldns_enum_dane_transport
+{
+       /** TCP */
+       LDNS_DANE_TRANSPORT_TCP  = 0,
+       /** UDP */
+       LDNS_DANE_TRANSPORT_UDP  = 1,
+       /** SCTP */
+       LDNS_DANE_TRANSPORT_SCTP = 2
+};
+typedef enum ldns_enum_dane_transport ldns_dane_transport;
+
+
+/**
+ * Creates a dname consisting of the given name, prefixed by the service port
+ * and type of transport: _<EM>port</EM>._<EM>transport</EM>.<EM>name</EM>.
+ *
+ * \param[out] tlsa_owner The created dname.
+ * \param[in] name The dname that should be prefixed.
+ * \param[in] port The service port number for wich the name should be created.
+ * \param[in] transport The transport for wich the name should be created.
+ * \return LDNS_STATUS_OK on success or an error code otherwise.
+ */
+ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner,
+               const ldns_rdf* name, uint16_t port,
+               ldns_dane_transport transport);
+
+
+#if LDNS_BUILD_CONFIG_HAVE_SSL
+/**
+ * Creates a LDNS_RDF_TYPE_HEX type rdf based on the binary data choosen by
+ * the selector and encoded using matching_type.
+ *
+ * \param[out] rdf The created created rdf of type LDNS_RDF_TYPE_HEX.
+ * \param[in] cert The certificate from which the data is selected
+ * \param[in] selector The full certificate or the public key
+ * \param[in] matching_type The full data or the SHA256 or SHA512 hash
+ *            of the selected data
+ * \return LDNS_STATUS_OK on success or an error code otherwise.
+ */
+ldns_status ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
+               ldns_tlsa_selector      selector,
+               ldns_tlsa_matching_type matching_type);
+
+
+/**
+ * Selects the certificate from cert, extra_certs or the pkix_validation_store
+ * based on the value of cert_usage and index.
+ *
+ * \param[out] selected_cert The selected cert.
+ * \param[in] cert The certificate to validate (or not)
+ * \param[in] extra_certs Intermediate certificates that might be necessary
+ *            during validation. May be NULL, except when the certificate 
+ *            usage is "Trust Anchor Assertion" because the trust anchor has
+ *            to be provided.(otherwise choose a "Domain issued certificate!"
+ * \param[in] pkix_validation_store Used when the certificate usage is 
+ *            "CA constraint" or "Service Certificate Constraint" to 
+ *            validate the certificate and, in case of "CA constraint",
+ *            select the CA.
+ *            When pkix_validation_store is NULL, validation is explicitely
+ *            turned off and the behaviour is then the same as for "Trust
+ *            anchor assertion" and "Domain issued certificate" respectively.
+ * \param[in] cert_usage Which certificate to use and how to validate.
+ * \param[in] index Used to select the trust anchor when certificate usage
+ *            is "Trust Anchor Assertion". 0 is the last certificate in the
+ *            validation chain. 1 the one but last, etc. When index is -1,
+ *            the last certificate is used that MUST be self-signed.
+ *            This can help to make sure that the intended (self signed)
+ *            trust anchor is actually present in extra_certs (which is a
+ *            DANE requirement).
+ *
+ * \return LDNS_STATUS_OK on success or an error code otherwise.
+ */
+ldns_status ldns_dane_select_certificate(X509** selected_cert,
+               X509* cert, STACK_OF(X509)* extra_certs,
+               X509_STORE* pkix_validation_store,
+               ldns_tlsa_certificate_usage cert_usage, int index);
+
+/**
+ * Creates a TLSA resource record from the certificate.
+ * No PKIX validation is performed! The given certificate is used as data
+ * regardless the value of certificate_usage.
+ *
+ * \param[out] tlsa The created TLSA resource record.
+ * \param[in] certificate_usage The value for the Certificate Usage field
+ * \param[in] selector The value for the Selector field
+ * \param[in] matching_type The value for the Matching Type field
+ * \param[in] cert The certificate which data will be represented
+ *
+ * \return LDNS_STATUS_OK on success or an error code otherwise.
+ */
+ldns_status ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
+               ldns_tlsa_certificate_usage certificate_usage,
+               ldns_tlsa_selector          selector,
+               ldns_tlsa_matching_type     matching_type,
+               X509* cert);
+
+/**
+ * Verify if the given TLSA resource record matches the given certificate.
+ * Reporting on a TLSA rr mismatch (LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH)
+ * is preferred over PKIX failure  (LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE).
+ * So when PKIX validation is required by the TLSA Certificate usage,
+ * but the TLSA data does not match, LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH
+ * is returned whether the PKIX validated or not.
+ *
+ * \param[in] tlsa_rr The resource record that specifies what and how to
+ *            match the certificate. With tlsa_rr == NULL, regular PKIX
+ *            validation is performed.
+ * \param[in] cert The certificate to match (and validate)
+ * \param[in] extra_certs Intermediate certificates that might be necessary
+ *            creating the validation chain.
+ * \param[in] pkix_validation_store Used when the certificate usage is 
+ *            "CA constraint" or "Service Certificate Constraint" to 
+ *            validate the certificate.
+ *
+ * \return LDNS_STATUS_OK on success,
+ *         LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH on TLSA data mismatch,
+ *         LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when TLSA matched,
+ *         but the PKIX validation failed, or other ldns_status errors.
+ */
+ldns_status ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
+               X509* cert, STACK_OF(X509)* extra_certs,
+               X509_STORE* pkix_validation_store);
+
+/**
+ * Verify if any of the given TLSA resource records matches the given
+ * certificate.
+ *
+ * \param[in] tlsas The resource records that specify what and how to
+ *            match the certificate. One must match for this function
+ *            to succeed. With tlsas == NULL or the number of TLSA records
+ *            in tlsas == 0, regular PKIX validation is performed.
+ * \param[in] cert The certificate to match (and validate)
+ * \param[in] extra_certs Intermediate certificates that might be necessary
+ *            creating the validation chain.
+ * \param[in] pkix_validation_store Used when the certificate usage is 
+ *            "CA constraint" or "Service Certificate Constraint" to 
+ *            validate the certificate.
+ *
+ * \return LDNS_STATUS_OK on success,
+ *         LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when one of the TLSA's
+ *         matched but the PKIX validation failed,
+ *         LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH when none of the TLSA's matched,
+ *         or other ldns_status errors.
+ */
+ldns_status ldns_dane_verify(ldns_rr_list* tlsas,
+               X509* cert, STACK_OF(X509)* extra_certs,
+               X509_STORE* pkix_validation_store);
+#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LDNS_DANE_H */
+
index a91f075..16b4542 100644 (file)
@@ -111,6 +111,7 @@ ldns_rdf *ldns_dname_new_frm_str(const char *str);
  * Create a new dname rdf from a string
  * \param[in] s the size of the new dname
  * \param[in] *data pointer to the actual data
+ *
  * \return ldns_rdf*
  */
 ldns_rdf *ldns_dname_new(uint16_t s, void *data);
@@ -119,6 +120,7 @@ ldns_rdf *ldns_dname_new(uint16_t s, void *data);
  * Create a new dname rdf from data (the data is copied)
  * \param[in] size the size of the data
  * \param[in] *data pointer to the actual data
+ *
  * \return ldns_rdf*
  */
 ldns_rdf *ldns_dname_new_frm_data(uint16_t size, const void *data);
@@ -177,6 +179,13 @@ int ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, const ldns
  */
 bool ldns_dname_str_absolute(const char *dname_str);
 
+/**
+ * Checks whether the given dname is absolute (i.e. ends with a '.')
+ * \param[in] *dname a rdf representing the dname
+ * \return true or false
+ */
+bool ldns_dname_absolute(const ldns_rdf *dname);
+
 /**
  * look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME
  * try and retrieve a specific label. The labels are numbered
index 7863551..34f6371 100644 (file)
@@ -198,6 +198,7 @@ RSA *ldns_key_buf2rsa_raw(unsigned char* key, size_t len);
  *
  * \param[in] *key the key to convert
  * \param[in] h the hash to use LDNS_SHA1/LDNS_SHA256
+ *
  * \return ldns_rr* a new rr pointer to a DS
  */
 ldns_rr *ldns_key_rr2ds(const ldns_rr *key, ldns_hash h);
@@ -395,6 +396,21 @@ bool ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name);
  * 
  */
 ldns_status ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys);
+
+/**
+ * verify a packet 
+ * \param[in] p the packet
+ * \param[in] t the rr set type to check
+ * \param[in] o the rr set name to check
+ * \param[in] k list of keys
+ * \param[in] s list of sigs (may be null)
+ * \param[in] check_time the time for which the validation is performed
+ * \param[out] good_keys keys which validated the packet
+ * \return status 
+ * 
+ */
+ldns_status ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, time_t check_time, ldns_rr_list *good_keys);
+
 #endif
 
 /**
index 13b3fa3..b6bdeca 100644 (file)
@@ -209,7 +209,7 @@ ldns_status ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
                                                                         const ldns_status parent_status);
 
 /**
- * Generates a dnssec_trust_ttree for the given rr from the
+ * Generates a dnssec_trust_tree for the given rr from the
  * given data_chain
  *
  * This does not clone the actual data; Don't free the
@@ -223,6 +223,22 @@ ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree(
                             ldns_dnssec_data_chain *data_chain,
                                           ldns_rr *rr);
 
+/**
+ * Generates a dnssec_trust_tree for the given rr from the
+ * given data_chain
+ *
+ * This does not clone the actual data; Don't free the
+ * data_chain before you are done with this tree
+ *
+ * \param[in] *data_chain The chain to derive the trust tree from
+ * \param[in] *rr The RR this tree will be about
+ * \param[in] check_time the time for which the validation is performed
+ * \return ldns_dnssec_trust_tree *
+ */
+ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree_time(
+               ldns_dnssec_data_chain *data_chain, 
+               ldns_rr *rr, time_t check_time);
+
 /**
  * Sub function for derive_trust_tree that is used for a 'normal' rrset
  *
@@ -235,6 +251,20 @@ void ldns_dnssec_derive_trust_tree_normal_rrset(
            ldns_dnssec_data_chain *data_chain,
            ldns_rr *cur_sig_rr);
 
+/**
+ * Sub function for derive_trust_tree that is used for a 'normal' rrset
+ *
+ * \param[in] new_tree The trust tree that we are building
+ * \param[in] data_chain The data chain containing the data for the trust tree
+ * \param[in] cur_sig_rr The currently relevant signature
+ * \param[in] check_time the time for which the validation is performed
+ */
+void ldns_dnssec_derive_trust_tree_normal_rrset_time(
+         ldns_dnssec_trust_tree *new_tree,
+           ldns_dnssec_data_chain *data_chain,
+           ldns_rr *cur_sig_rr, time_t check_time);
+
+
 /**
  * Sub function for derive_trust_tree that is used for DNSKEY rrsets
  *
@@ -249,6 +279,38 @@ void ldns_dnssec_derive_trust_tree_dnskey_rrset(
            ldns_rr *cur_rr,
            ldns_rr *cur_sig_rr);
 
+/**
+ * Sub function for derive_trust_tree that is used for DNSKEY rrsets
+ *
+ * \param[in] new_tree The trust tree that we are building
+ * \param[in] data_chain The data chain containing the data for the trust tree
+ * \param[in] cur_rr The currently relevant DNSKEY RR
+ * \param[in] cur_sig_rr The currently relevant signature
+ * \param[in] check_time the time for which the validation is performed
+ */
+void ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
+         ldns_dnssec_trust_tree *new_tree,
+           ldns_dnssec_data_chain *data_chain,
+           ldns_rr *cur_rr, ldns_rr *cur_sig_rr,
+           time_t check_time);
+
+
+/**
+ * Sub function for derive_trust_tree that is used for DNSKEY rrsets
+ *
+ * \param[in] new_tree The trust tree that we are building
+ * \param[in] data_chain The data chain containing the data for the trust tree
+ * \param[in] cur_rr The currently relevant DNSKEY RR
+ * \param[in] cur_sig_rr The currently relevant signature
+ * \param[in] check_time the time for which the validation is performed
+ */
+void ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
+         ldns_dnssec_trust_tree *new_tree,
+           ldns_dnssec_data_chain *data_chain,
+           ldns_rr *cur_rr, ldns_rr *cur_sig_rr,
+           time_t check_time);
+
+
 /**
  * Sub function for derive_trust_tree that is used for DS rrsets
  *
@@ -261,6 +323,19 @@ void ldns_dnssec_derive_trust_tree_ds_rrset(
            ldns_dnssec_data_chain *data_chain,
            ldns_rr *cur_rr);
 
+/**
+ * Sub function for derive_trust_tree that is used for DS rrsets
+ *
+ * \param[in] new_tree The trust tree that we are building
+ * \param[in] data_chain The data chain containing the data for the trust tree
+ * \param[in] cur_rr The currently relevant DS RR
+ * \param[in] check_time the time for which the validation is performed
+ */
+void ldns_dnssec_derive_trust_tree_ds_rrset_time(
+         ldns_dnssec_trust_tree *new_tree,
+           ldns_dnssec_data_chain *data_chain,
+           ldns_rr *cur_rr, time_t check_time);
+
 /**
  * Sub function for derive_trust_tree that is used when there are no
  * signatures
@@ -272,12 +347,27 @@ void ldns_dnssec_derive_trust_tree_no_sig(
          ldns_dnssec_trust_tree *new_tree,
            ldns_dnssec_data_chain *data_chain);
 
+/**
+ * Sub function for derive_trust_tree that is used when there are no
+ * signatures
+ *
+ * \param[in] new_tree The trust tree that we are building
+ * \param[in] data_chain The data chain containing the data for the trust tree
+ * \param[in] check_time the time for which the validation is performed
+ */
+void ldns_dnssec_derive_trust_tree_no_sig_time(
+         ldns_dnssec_trust_tree *new_tree,
+           ldns_dnssec_data_chain *data_chain,
+           time_t check_time);
+
+
 /**
  * Returns OK if there is a trusted path in the tree to one of 
  * the DNSKEY or DS RRs in the given list
  *
  * \param *tree The trust tree so search
  * \param *keys A ldns_rr_list of DNSKEY and DS rrs to look for
+ *
  * \return LDNS_STATUS_OK if there is a trusted path to one of
  *                        the keys, or the *first* error encountered
  *                        if there were no paths
@@ -302,6 +392,25 @@ ldns_status ldns_verify(ldns_rr_list *rrset,
                                    const ldns_rr_list *keys,
                                    ldns_rr_list *good_keys);   
 
+/**
+ * Verifies a list of signatures for one rrset.
+ *
+ * \param[in] rrset the rrset to verify
+ * \param[in] rrsig a list of signatures to check
+ * \param[in] keys a list of keys to check with
+ * \param[in] check_time the time for which the validation is performed
+ * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
+ *                        from keys that validate one of the signatures
+ *                        are added to it
+ * \return status LDNS_STATUS_OK if there is at least one correct key
+ */
+ldns_status ldns_verify_time(ldns_rr_list *rrset,
+                                   ldns_rr_list *rrsig,
+                                   const ldns_rr_list *keys,
+                                   time_t check_time,
+                                   ldns_rr_list *good_keys);   
+
+
 /**
  * Verifies a list of signatures for one rrset, but disregard the time.
  * Inception and Expiration are not checked.
@@ -338,6 +447,26 @@ ldns_rr_list *ldns_fetch_valid_domain_keys(const ldns_resolver * res,
                                                                   const ldns_rr_list * keys,
                                                                   ldns_status *status);
 
+/**
+ * Tries to build an authentication chain from the given 
+ * keys down to the queried domain.
+ *
+ * If we find a valid trust path, return the valid keys for the domain.
+ * 
+ * \param[in] res the current resolver
+ * \param[in] domain the domain we want valid keys for
+ * \param[in] keys the current set of trusted keys
+ * \param[in] check_time the time for which the validation is performed
+ * \param[out] status pointer to the status variable where the result
+ *                    code will be stored
+ * \return the set of trusted keys for the domain, or NULL if no 
+ *         trust path could be built.
+ */
+ldns_rr_list *ldns_fetch_valid_domain_keys_time(const ldns_resolver * res,
+               const ldns_rdf * domain, const ldns_rr_list * keys,
+               time_t check_time, ldns_status *status);
+
+
 /**
  * Validates the DNSKEY RRset for the given domain using the provided 
  * trusted keys.
@@ -352,6 +481,22 @@ ldns_rr_list *ldns_validate_domain_dnskey (const ldns_resolver *res,
                                                                   const ldns_rdf *domain,
                                                                   const ldns_rr_list *keys);
 
+/**
+ * Validates the DNSKEY RRset for the given domain using the provided 
+ * trusted keys.
+ *
+ * \param[in] res the current resolver
+ * \param[in] domain the domain we want valid keys for
+ * \param[in] keys the current set of trusted keys
+ * \param[in] check_time the time for which the validation is performed
+ * \return the set of trusted keys for the domain, or NULL if the RRSET
+ *         could not be validated
+ */
+ldns_rr_list *ldns_validate_domain_dnskey_time(
+               const ldns_resolver *res, const ldns_rdf *domain, 
+               const ldns_rr_list *keys, time_t check_time);
+
+
 /**
  * Validates the DS RRset for the given domain using the provided trusted keys.
  *
@@ -365,6 +510,20 @@ ldns_rr_list *ldns_validate_domain_ds(const ldns_resolver *res,
                                                           domain,
                                                           const ldns_rr_list * keys);
 
+/**
+ * Validates the DS RRset for the given domain using the provided trusted keys.
+ *
+ * \param[in] res the current resolver
+ * \param[in] domain the domain we want valid keys for
+ * \param[in] keys the current set of trusted keys
+ * \param[in] check_time the time for which the validation is performed
+ * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated
+ */
+ldns_rr_list *ldns_validate_domain_ds_time(
+               const ldns_resolver *res, const ldns_rdf *domain, 
+               const ldns_rr_list * keys, time_t check_time);
+
+
 /**
  * Verifies a list of signatures for one RRset using a valid trust path.
  *
@@ -381,6 +540,24 @@ ldns_status ldns_verify_trusted(ldns_resolver *res,
                                                  ldns_rr_list *rrsigs,
                                                  ldns_rr_list *validating_keys);
 
+/**
+ * Verifies a list of signatures for one RRset using a valid trust path.
+ *
+ * \param[in] res the current resolver
+ * \param[in] rrset the rrset to verify
+ * \param[in] rrsigs a list of signatures to check
+ * \param[in] check_time the time for which the validation is performed
+ * \param[out] validating_keys  if this is a (initialized) list, the
+ *                              keys from keys that validate one of
+ *                              the signatures are added to it
+ * \return status LDNS_STATUS_OK if there is at least one correct key
+ */
+ldns_status ldns_verify_trusted_time(
+               ldns_resolver *res, ldns_rr_list *rrset, 
+               ldns_rr_list *rrsigs, time_t check_time,
+               ldns_rr_list *validating_keys);
+
+
 /**
  * denial is not just a river in egypt
  *
@@ -493,6 +670,24 @@ ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
                                                           const ldns_rr_list *keys,
                                                           ldns_rr_list *good_keys);
 
+/**
+ * Verifies an rrsig. All keys in the keyset are tried.
+ * \param[in] rrset the rrset to check
+ * \param[in] rrsig the signature of the rrset
+ * \param[in] keys the keys to try
+ * \param[in] check_time the time for which the validation is performed
+ * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
+ *                        from keys that validate one of the signatures
+ *                        are added to it
+ * \return a list of keys which validate the rrsig + rrset. Returns
+ * status LDNS_STATUS_OK if at least one key matched. Else an error.
+ */
+ldns_status ldns_verify_rrsig_keylist_time(
+               ldns_rr_list *rrset, ldns_rr *rrsig, 
+               const ldns_rr_list *keys, time_t check_time,
+               ldns_rr_list *good_keys);
+
+
 /**
  * Verifies an rrsig. All keys in the keyset are tried. Time is not checked.
  * \param[in] rrset the rrset to check
@@ -520,6 +715,20 @@ ldns_status ldns_verify_rrsig(ldns_rr_list *rrset,
                                                ldns_rr *rrsig,
                                                ldns_rr *key);
 
+
+/**
+ * verify an rrsig with 1 key
+ * \param[in] rrset the rrset
+ * \param[in] rrsig the rrsig to verify
+ * \param[in] key the key to use
+ * \param[in] check_time the time for which the validation is performed
+ * \return status message wether verification succeeded.
+ */
+ldns_status ldns_verify_rrsig_time(
+               ldns_rr_list *rrset, ldns_rr *rrsig, 
+               ldns_rr *key, time_t check_time);
+
+
 #if LDNS_BUILD_CONFIG_HAVE_SSL
 /**
  * verifies a buffer with signature data for a buffer with rrset data 
index e2dd402..70c81b0 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef LDNS_DNSSEC_ZONE_H
 #define LDNS_DNSSEC_ZONE_H
  
-#include <ldns/ldns.h>
 #include <ldns/rbtree.h>
 #include <ldns/host2str.h>
 
@@ -359,6 +358,33 @@ void ldns_dnssec_name_print_fmt(FILE *out,
  */
 ldns_dnssec_zone *ldns_dnssec_zone_new();
 
+/**
+ * Create a new dnssec zone from a file.
+ * \param[out] z the new zone
+ * \param[in] *fp the filepointer to use
+ * \param[in] *origin the zones' origin
+ * \param[in] c default class to use (IN)
+ * \param[in] ttl default ttl to use
+ *
+ * \return ldns_status mesg with an error or LDNS_STATUS_OK
+ */
+ldns_status ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp,
+               ldns_rdf* origin, uint32_t ttl, ldns_rr_class c);
+
+/**
+ * Create a new dnssec zone from a file, keep track of the line numbering
+ * \param[out] z the new zone
+ * \param[in] *fp the filepointer to use
+ * \param[in] *origin the zones' origin
+ * \param[in] ttl default ttl to use
+ * \param[in] c default class to use (IN)
+ * \param[out] line_nr used for error msg, to get to the line number
+ *
+ * \return ldns_status mesg with an error or LDNS_STATUS_OK
+ */
+ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp,
+               ldns_rdf* origin, uint32_t ttl, ldns_rr_class c, int* line_nr);
+
 /**
  * Frees the given zone structure, and its rbtree of dnssec_names
  * Individual ldns_rr RRs within those names are *not* freed
@@ -433,6 +459,15 @@ void ldns_dnssec_zone_print_fmt(FILE *out,
  */
 ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone);
 
+/**
+ * If a NSEC3PARAM is available in the apex, walks the zone and returns true
+ * on the first optout nsec3.
+ *
+ * \param[in] zone the zone to check for nsec3 optout records
+ * return true when the zone has at least one nsec3 optout record.
+ */
+bool ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/contrib/ldns/ldns/duration.h b/contrib/ldns/ldns/duration.h
new file mode 100644 (file)
index 0000000..f12edc4
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * $Id: duration.h 4341 2011-01-31 15:21:09Z matthijs $
+ *
+ * Copyright (c) 2009 NLNet Labs. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ *
+ * This file is copied from the OpenDNSSEC source repository
+ * and only slightly adapted to make it fit.
+ */
+
+/**
+ *
+ * Durations.
+ */
+
+#ifndef LDNS_DURATION_H
+#define LDNS_DURATION_H
+
+#include <stdint.h>
+#include <time.h>
+
+/**
+ * Duration.
+ *
+ */
+typedef struct ldns_duration_struct ldns_duration_type;
+struct ldns_duration_struct
+{
+    time_t years;
+    time_t months;
+    time_t weeks;
+    time_t days;
+    time_t hours;
+    time_t minutes;
+    time_t seconds;
+};
+
+/**
+ * Create a new 'instant' duration.
+ * \return ldns_duration_type* created duration
+ *
+ */
+ldns_duration_type* ldns_duration_create(void);
+
+/**
+ * Compare durations.
+ * \param[in] d1 one duration
+ * \param[in] d2 another duration
+ * \return int 0 if equal, -1 if d1 < d2, 1 if d2 < d1
+ *
+ */
+int ldns_duration_compare(ldns_duration_type* d1, ldns_duration_type* d2);
+
+/**
+ * Create a duration from string.
+ * \param[in] str string-format duration
+ * \return ldns_duration_type* created duration
+ *
+ */
+ldns_duration_type* ldns_duration_create_from_string(const char* str);
+
+/**
+ * Convert a duration to a string.
+ * \param[in] duration duration to be converted
+ * \return char* string-format duration
+ *
+ */
+char* ldns_duration2string(ldns_duration_type* duration);
+
+/**
+ * Convert a duration to a time.
+ * \param[in] duration duration to be converted
+ * \return time_t time-format duration
+ *
+ */
+time_t ldns_duration2time(ldns_duration_type* duration);
+
+/**
+ * Clean up duration.
+ * \param[in] duration duration to be cleaned up
+ *
+ */
+void ldns_duration_cleanup(ldns_duration_type* duration);
+
+#endif /* LDNS_DURATION_H */
index 99d4f0b..bac38ff 100644 (file)
@@ -100,7 +100,24 @@ enum ldns_enum_status {
        LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED,
        LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND,
        LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG,
-       LDNS_STATUS_MISSING_RDATA_FIELDS_KEY
+       LDNS_STATUS_MISSING_RDATA_FIELDS_KEY,
+       LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN,
+       LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN,
+       LDNS_STATUS_DANE_STATUS_MESSAGES,
+       LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE,
+       LDNS_STATUS_DANE_UNKNOWN_SELECTOR,
+       LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE,
+       LDNS_STATUS_DANE_UNKNOWN_PROTOCOL,
+       LDNS_STATUS_DANE_UNKNOWN_TRANSPORT,
+       LDNS_STATUS_DANE_MISSING_EXTRA_CERTS,
+       LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED,
+       LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE,
+       LDNS_STATUS_DANE_INSECURE,
+       LDNS_STATUS_DANE_BOGUS,
+       LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
+       LDNS_STATUS_DANE_NON_CA_CERTIFICATE,
+       LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE,
+       LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR
 };
 typedef enum ldns_enum_status ldns_status;
 
index f0a14a4..bbf9327 100644 (file)
@@ -64,6 +64,8 @@ extern "C" {
 #define LDNS_COMMENT_LAYOUT            0x0080
 /** Also comment KEY_ID with RRSIGS **/
 #define LDNS_COMMENT_RRSIGS            0x0100
+#define LDNS_FMT_ZEROIZE_RRSIGS                0x0200
+#define LDNS_FMT_PAD_SOA_SERIAL                0x0400
 
 /**
  * Output format specifier
@@ -601,14 +603,26 @@ char *ldns_rr_list2str_fmt(
                const ldns_output_format *fmt, const ldns_rr_list *rr_list);
 
 /**
- * Returns the data in the buffer as a null terminated char * string
- * Buffer data must be char * type, and must be freed by the caller
+ * Returns a copy of the data in the buffer as a null terminated
+ * char * string. The returned string must be freed by the caller.
+ * The buffer must be in write modus and may thus not have been flipped.
  *
  * \param[in] buffer buffer containing char * data
  * \return null terminated char * data, or NULL on error
  */
 char *ldns_buffer2str(ldns_buffer *buffer);
 
+/**
+ * Exports and returns the data in the buffer as a null terminated
+ * char * string. The returned string must be freed by the caller.
+ * The buffer must be in write modus and may thus not have been flipped.
+ * The buffer is fixed after this function returns.
+ *
+ * \param[in] buffer buffer containing char * data
+ * \return null terminated char * data, or NULL on error
+ */
+char *ldns_buffer_export2str(ldns_buffer *buffer);
+
 /**
  * Prints the data in the rdata field to the given file stream
  * (in presentation format)
index ae5d474..3e15623 100644 (file)
@@ -25,7 +25,6 @@
 #if LDNS_BUILD_CONFIG_HAVE_SSL
 #include <openssl/ssl.h>
 #endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
-#include <ldns/dnssec.h>
 #include <ldns/util.h>
 #include <errno.h>
 
@@ -54,12 +53,8 @@ enum ldns_enum_algorithm
         LDNS_RSASHA256          = 8,   /* RFC 5702 */
         LDNS_RSASHA512          = 10,  /* RFC 5702 */
         LDNS_ECC_GOST           = 12,  /* RFC 5933 */
-#if LDNS_BUILD_CONFIG_USE_ECDSA
-       /* this ifdef has to be removed once it is no longer experimental,
-        * to be able to use these values outside of the ldns library itself */
-        LDNS_ECDSAP256SHA256    = 13,  /* draft-hoffman-dnssec-ecdsa */
-        LDNS_ECDSAP384SHA384    = 14,  /* EXPERIMENTAL */
-#endif
+        LDNS_ECDSAP256SHA256    = 13,  /* RFC 6605 */
+        LDNS_ECDSAP384SHA384    = 14,  /* RFC 6605 */
         LDNS_INDIRECT           = 252,
         LDNS_PRIVATEDNS         = 253,
         LDNS_PRIVATEOID         = 254
@@ -73,12 +68,8 @@ enum ldns_enum_hash
 {
         LDNS_SHA1               = 1,  /* RFC 4034 */
      &n