From 435c04e03b718a88664a9c07a1addb324f21620e Mon Sep 17 00:00:00 2001 From: Jan Lentfer Date: Thu, 30 Dec 2010 01:30:02 +0100 Subject: [PATCH] Update to ldns-1.6.7 --- contrib/ldns/Changelog | 88 ++++++ contrib/ldns/README | 28 +- contrib/ldns/README.DELETED | 24 -- contrib/ldns/README.DRAGONFLY | 9 - contrib/ldns/buffer.c | 6 +- contrib/ldns/compat/b32_ntop.c | 21 +- contrib/ldns/compat/b32_pton.c | 2 - contrib/ldns/compat/b64_ntop.c | 2 - contrib/ldns/compat/b64_pton.c | 2 - contrib/ldns/compat/fake-rfc2553.h | 8 + contrib/ldns/compat/snprintf.c | 6 +- contrib/ldns/dname.c | 55 +++- contrib/ldns/dnssec.c | 114 +++++++- contrib/ldns/dnssec_sign.c | 179 ++++++++---- contrib/ldns/dnssec_verify.c | 124 ++++++-- contrib/ldns/dnssec_zone.c | 4 +- contrib/ldns/drill/dnssec.c | 17 +- contrib/ldns/drill/drill.1 | 2 +- contrib/ldns/drill/drill.c | 4 +- contrib/ldns/drill/securetrace.c | 53 ++-- contrib/ldns/error.c | 4 +- contrib/ldns/higher.c | 18 +- contrib/ldns/host2str.c | 130 ++++++--- contrib/ldns/host2wire.c | 21 +- contrib/ldns/keys.c | 245 ++++++++++++++-- contrib/ldns/ldns/buffer.h | 8 + contrib/ldns/ldns/common.h | 2 +- contrib/ldns/ldns/config.h.in | 443 ----------------------------- contrib/ldns/ldns/dname.h | 25 +- contrib/ldns/ldns/dnssec.h | 45 ++- contrib/ldns/ldns/dnssec_sign.h | 8 +- contrib/ldns/ldns/dnssec_verify.h | 18 +- contrib/ldns/ldns/dnssec_zone.h | 8 + contrib/ldns/ldns/error.h | 10 + contrib/ldns/ldns/higher.h | 8 + contrib/ldns/ldns/host2str.h | 66 ++++- contrib/ldns/ldns/host2wire.h | 8 + contrib/ldns/ldns/keys.h | 41 ++- contrib/ldns/ldns/ldns.h | 147 ---------- contrib/ldns/ldns/net.h.in | 200 ------------- contrib/ldns/ldns/packet.h | 10 +- contrib/ldns/ldns/parse.h | 8 + contrib/ldns/ldns/rbtree.h | 55 ++-- contrib/ldns/ldns/rdata.h | 8 + contrib/ldns/ldns/resolver.h | 80 ++++-- contrib/ldns/ldns/rr.h | 13 +- contrib/ldns/ldns/rr_functions.h | 8 + contrib/ldns/ldns/sha1.h | 9 + contrib/ldns/ldns/str2host.h | 8 + contrib/ldns/ldns/tsig.h | 28 +- contrib/ldns/ldns/update.h | 8 + contrib/ldns/ldns/util.h.in | 331 --------------------- contrib/ldns/ldns/wire2host.h | 8 + contrib/ldns/ldns/zone.h | 8 + contrib/ldns/net.c | 114 ++++++-- contrib/ldns/packet.c | 16 +- contrib/ldns/parse.c | 49 ++-- contrib/ldns/rbtree.c | 12 +- contrib/ldns/rdata.c | 20 +- contrib/ldns/resolver.c | 144 ++++++++-- contrib/ldns/rr.c | 87 +++--- contrib/ldns/rr_functions.c | 10 +- contrib/ldns/str2host.c | 126 ++++++-- contrib/ldns/tsig.c | 76 +++-- contrib/ldns/util.c | 24 +- contrib/ldns/wire2host.c | 9 +- contrib/ldns/zone.c | 16 +- 67 files changed, 1857 insertions(+), 1631 deletions(-) delete mode 100644 contrib/ldns/README.DELETED delete mode 100644 contrib/ldns/README.DRAGONFLY delete mode 100644 contrib/ldns/ldns/config.h.in delete mode 100644 contrib/ldns/ldns/ldns.h delete mode 100644 contrib/ldns/ldns/net.h.in delete mode 100644 contrib/ldns/ldns/util.h.in diff --git a/contrib/ldns/Changelog b/contrib/ldns/Changelog index 5ad466ab8e..e99956797b 100644 --- a/contrib/ldns/Changelog +++ b/contrib/ldns/Changelog @@ -1,3 +1,91 @@ +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). + * 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. diff --git a/contrib/ldns/README b/contrib/ldns/README index 3a93c41ece..74e470a03d 100644 --- a/contrib/ldns/README +++ b/contrib/ldns/README @@ -8,6 +8,7 @@ Contents: INFORMATION FOR SPECIFIC OPERATING SYSTEMS Mac OS X Solaris + Your Support Project page: http://www.nlnetlabs.nl/ldns/ @@ -64,10 +65,11 @@ commands may be a little bit different on your machine. Most notable, you'll nee * Developers ldns is developed by the ldns team at NLnet Labs. This team currently consists of: - o Jelte Jansen o Wouter Wijngaards + o Matthijs Mekking Former main developers: + o Jelte Jansen o Miek Gieben * Credits @@ -101,3 +103,27 @@ compile in 64-bit mode. Jakob Schlyter has kindly contributed a build script that sets the right build and link options. You can find it in contrib/build-solaris.sh + +Your Support +NLnet Labs offers all of its software products as open source, most are +published under a BDS license. You can download them, not only from the +NLnet Labs website but also through the various OS distributions for +which NSD, ldns, and Unbound are packaged. We therefore have little idea +who uses our software in production environments and have no direct ties +with 'our customers'. + +Therefore, we ask you to contact us at users@NLnetLabs.nl and tell us +whether you use one of our products in your production environment, +what that environment looks like, and maybe even share some praise. +We would like to refer to the fact that your organization is using our +products. We will only do that if you explicitly allow us. In all other +cases we will keep the information you share with us to ourselves. + +In addition to the moral support you can also support us +financially. NLnet Labs is a recognized not-for-profit charity foundation +that is chartered to develop open-source software and open-standards +for the Internet. If you use our software to satisfaction please express +that by giving us a donation. For small donations PayPal can be used. For +larger and regular donations please contact us at users@NLnetLabs.nl. Also +see http://www.nlnetlabs.nl/labs/contributors/. + diff --git a/contrib/ldns/README.DELETED b/contrib/ldns/README.DELETED deleted file mode 100644 index 142e1587dc..0000000000 --- a/contrib/ldns/README.DELETED +++ /dev/null @@ -1,24 +0,0 @@ -Makefile.in -ac_pkg_swig.m4 -aclocal.m4 -acx_nlnetlabs.m4 -acx_python.m4 -config.guess -config.sub -configure -configure.ac -contrib/ -doc/ -drill/Makefile.in -drill/config.h.in -drill/configure -drill/configure.ac -drill/drill.h.in -drill/install-sh -examples/ -install-sh -ldns_symbols.def -libdns.doxygen -libdns.vim -ltmain.sh -packaging/ diff --git a/contrib/ldns/README.DRAGONFLY b/contrib/ldns/README.DRAGONFLY deleted file mode 100644 index 2d896efac7..0000000000 --- a/contrib/ldns/README.DRAGONFLY +++ /dev/null @@ -1,9 +0,0 @@ -Original source can be downloaded from: -http://www.nlnetlabs.nl/projects/ldns/ - - MD5 (ldns-1.6.4.tar.gz) = 6747d7bd96552ee5d8943f3abb24815f - SHA1 (ldns-1.6.4.tar.gz) = 9015968ad3ddd015c750c15b60e60b9cccd393ec - -A list of deleted files is in README.DELETED. - -When Upgrading please stick to development(7). diff --git a/contrib/ldns/buffer.c b/contrib/ldns/buffer.c index c6259b4e20..5a6b0ba74c 100644 --- a/contrib/ldns/buffer.c +++ b/contrib/ldns/buffer.c @@ -44,9 +44,13 @@ ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size) buffer->_position = 0; buffer->_limit = buffer->_capacity = size; + buffer->_fixed = 0; buffer->_data = LDNS_XMALLOC(uint8_t, size); + if(!buffer->_data) { + buffer->_status = LDNS_STATUS_MEM_ERR; + return; + } memcpy(buffer->_data, data, size); - buffer->_fixed = 0; buffer->_status = LDNS_STATUS_OK; ldns_buffer_invariant(buffer); diff --git a/contrib/ldns/compat/b32_ntop.c b/contrib/ldns/compat/b32_ntop.c index ec4104f235..038ebdc958 100644 --- a/contrib/ldns/compat/b32_ntop.c +++ b/contrib/ldns/compat/b32_ntop.c @@ -41,8 +41,6 @@ */ #include -#include - #include #include #ifdef HAVE_SYS_SOCKET_H @@ -256,41 +254,56 @@ ldns_b32_ntop_ar(uint8_t const *src, size_t srclength, char *target, size_t targ } target[datalength++] = B32_ar[output[0]]; if (srclength >= 1) { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = B32_ar[output[1]]; if (srclength == 1 && output[2] == 0) { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = Pad32; } else { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = B32_ar[output[2]]; } } else { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = Pad32; + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = Pad32; } if (srclength >= 2) { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = B32_ar[output[3]]; } else { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = Pad32; } if (srclength >= 3) { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = B32_ar[output[4]]; if (srclength == 3 && output[5] == 0) { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = Pad32; } else { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = B32_ar[output[5]]; } } else { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = Pad32; + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = Pad32; } if (srclength >= 4) { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = B32_ar[output[6]]; } else { + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = Pad32; } + if (datalength + 1 > targsize) { return (-2); } target[datalength++] = Pad32; } - if (datalength > targsize) { - return (-3); + if (datalength+1 > targsize) { + return (int) (datalength); } target[datalength] = '\0'; /* Returned value doesn't count \0. */ return (int) (datalength); diff --git a/contrib/ldns/compat/b32_pton.c b/contrib/ldns/compat/b32_pton.c index 5a3c2ea697..9c261e615b 100644 --- a/contrib/ldns/compat/b32_pton.c +++ b/contrib/ldns/compat/b32_pton.c @@ -41,8 +41,6 @@ */ #include -#include - #include #include #ifdef HAVE_SYS_SOCKET_H diff --git a/contrib/ldns/compat/b64_ntop.c b/contrib/ldns/compat/b64_ntop.c index 93c209ab07..d0b52b514b 100644 --- a/contrib/ldns/compat/b64_ntop.c +++ b/contrib/ldns/compat/b64_ntop.c @@ -41,8 +41,6 @@ */ #include -#include - #include #include #ifdef HAVE_SYS_SOCKET_H diff --git a/contrib/ldns/compat/b64_pton.c b/contrib/ldns/compat/b64_pton.c index a4babea421..aa637d2275 100644 --- a/contrib/ldns/compat/b64_pton.c +++ b/contrib/ldns/compat/b64_pton.c @@ -41,8 +41,6 @@ */ #include -#include - #include #include #ifdef HAVE_SYS_SOCKET_H diff --git a/contrib/ldns/compat/fake-rfc2553.h b/contrib/ldns/compat/fake-rfc2553.h index 1e9add1eb0..4c277ee902 100644 --- a/contrib/ldns/compat/fake-rfc2553.h +++ b/contrib/ldns/compat/fake-rfc2553.h @@ -44,6 +44,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* * First, socket and INET6 related definitions */ @@ -171,5 +175,9 @@ int getnameinfo(const struct sockaddr *, size_t, char *, size_t, char *, size_t, int); #endif /* !HAVE_GETNAMEINFO */ +#ifdef __cplusplus +} +#endif + #endif /* !_FAKE_RFC2553_H */ diff --git a/contrib/ldns/compat/snprintf.c b/contrib/ldns/compat/snprintf.c index c668daea16..b7445111cb 100644 --- a/contrib/ldns/compat/snprintf.c +++ b/contrib/ldns/compat/snprintf.c @@ -671,15 +671,15 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, */ dopr_outch (buffer, currlen, maxlen, '.'); - while (fplace > 0) - dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); - while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + while (padlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); diff --git a/contrib/ldns/dname.c b/contrib/ldns/dname.c index e5c80317d1..0e63ef2689 100644 --- a/contrib/ldns/dname.c +++ b/contrib/ldns/dname.c @@ -73,6 +73,7 @@ ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2) { uint16_t left_size; uint16_t size; + uint8_t* newd; if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME || ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) { @@ -86,10 +87,17 @@ ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2) if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) { 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); + if(!newd) { + return LDNS_STATUS_MEM_ERR; + } - ldns_rdf_set_data(rd1, LDNS_XREALLOC(ldns_rdf_data(rd1), uint8_t, size)); + ldns_rdf_set_data(rd1, newd); memcpy(ldns_rdf_data(rd1) + left_size, ldns_rdf_data(rd2), ldns_rdf_size(rd2)); ldns_rdf_set_size(rd1, size); @@ -108,10 +116,17 @@ ldns_dname_reverse(const ldns_rdf *d) 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); @@ -416,15 +431,21 @@ ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2) return result; } +int +ldns_dname_is_wildcard(const ldns_rdf* dname) +{ + return ( ldns_dname_label_count(dname) > 0 && + ldns_rdf_data(dname)[0] == 1 && + ldns_rdf_data(dname)[1] == '*'); +} + int ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard) { ldns_rdf *wc_chopped; int result; /* check whether it really is a wildcard */ - if (ldns_dname_label_count(wildcard) > 0 && - ldns_rdf_data(wildcard)[0] == 1 && - ldns_rdf_data(wildcard)[1] == '*') { + if (ldns_dname_is_wildcard(wildcard)) { /* ok, so the dname needs to be a subdomain of the wildcard * without the * */ @@ -475,12 +496,30 @@ ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, bool ldns_dname_str_absolute(const char *dname_str) { + const char* s; if(dname_str && strcmp(dname_str, ".") == 0) return 1; - return (dname_str && - strlen(dname_str) > 1 && - dname_str[strlen(dname_str) - 1] == '.' && - dname_str[strlen(dname_str) - 2] != '\\'); + if(!dname_str || strlen(dname_str) < 2) + return 0; + if(dname_str[strlen(dname_str) - 1] != '.') + return 0; + if(dname_str[strlen(dname_str) - 2] != '\\') + return 1; /* ends in . and no \ before it */ + /* so we have the case of ends in . and there is \ before it */ + for(s=dname_str; *s; s++) { + if(*s == '\\') { + if(s[1] && s[2] && s[3] /* check length */ + && isdigit(s[1]) && isdigit(s[2]) && + isdigit(s[3])) + s += 3; + else if(!s[1] || isdigit(s[1])) /* escape of nul,0-9 */ + return 0; /* parse error */ + else s++; /* another character escaped */ + } + else if(!*(s+1) && *s == '.') + return 1; /* trailing dot, unescaped */ + } + return 0; } ldns_rdf * diff --git a/contrib/ldns/dnssec.c b/contrib/ldns/dnssec.c index c39985f92a..5d394d1d74 100644 --- a/contrib/ldns/dnssec.c +++ b/contrib/ldns/dnssec.c @@ -42,7 +42,7 @@ ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name, if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_RRSIG) { if (ldns_dname_compare(ldns_rr_owner(candidate), name) == 0 && - ldns_rdf2native_int8(ldns_rr_rrsig_typecovered(candidate)) + ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(candidate)) == type ) { return candidate; @@ -148,6 +148,12 @@ ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, salt); status = ldns_dname_cat(hashed_sname, zone_name); + if(status != LDNS_STATUS_OK) { + LDNS_FREE(salt); + ldns_rdf_deep_free(zone_name); + ldns_rdf_deep_free(sname); + return NULL; + } for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { nsec = ldns_rr_list_rr(nsec3s, nsec_i); @@ -506,7 +512,7 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) return NULL; } break; - case LDNS_HASH_GOST94: + case LDNS_HASH_GOST: #ifdef USE_GOST (void)ldns_key_EVP_load_gost_id(); md = EVP_get_digestbyname("md_gost94"); @@ -519,12 +525,25 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) ldns_rr_free(ds); return NULL; } + break; +#else + /* not implemented */ + ldns_rr_free(ds); + return NULL; +#endif +#ifdef USE_ECDSA + case LDNS_SHA384: + 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 - break; } data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); @@ -593,7 +612,7 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) digest); ldns_rr_push_rdf(ds, tmp); break; - case LDNS_HASH_GOST94: + case LDNS_HASH_GOST: #ifdef USE_GOST if(!ldns_digest_evp((unsigned char *) ldns_buffer_begin(data_buf), (unsigned int) ldns_buffer_position(data_buf), @@ -609,6 +628,17 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) ldns_rr_push_rdf(ds, tmp); #endif break; +#ifdef USE_ECDSA + case LDNS_SHA384: + (void) SHA384((unsigned char *) ldns_buffer_begin(data_buf), + (unsigned int) ldns_buffer_position(data_buf), + (unsigned char *) digest); + tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, + SHA384_DIGEST_LENGTH, + digest); + ldns_rr_push_rdf(ds, tmp); + break; +#endif } LDNS_FREE(digest); @@ -807,6 +837,10 @@ ldns_dnssec_create_nsec3(ldns_dnssec_name *from, salt_length, salt)); status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name); + if(status != LDNS_STATUS_OK) { + ldns_rr_free(nsec_rr); + return NULL; + } ldns_nsec3_add_param_rdfs(nsec_rr, algorithm, flags, @@ -960,7 +994,7 @@ ldns_nsec3_hash_name(ldns_rdf *name, (uint8_t *) hashed_owner_str, hashed_owner_str_len, hashed_owner_b32, - ldns_b32_ntop_calculate_size(hashed_owner_str_len)); + ldns_b32_ntop_calculate_size(hashed_owner_str_len)+1); if (hashed_owner_b32_len < 1) { fprintf(stderr, "Error in base32 extended hex encoding "); fprintf(stderr, "of hashed owner name (name: "); @@ -970,7 +1004,6 @@ ldns_nsec3_hash_name(ldns_rdf *name, LDNS_FREE(hashed_owner_b32); return NULL; } - hashed_owner_str_len = hashed_owner_b32_len; hashed_owner_b32[hashed_owner_b32_len] = '\0'; status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32); @@ -1075,8 +1108,12 @@ ldns_create_nsec3(ldns_rdf *cur_owner, salt_length, salt); status = ldns_dname_cat(hashed_owner, cur_zone); + if(status != LDNS_STATUS_OK) + return NULL; nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); + if(!nsec) + return NULL; ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3); ldns_rr_set_owner(nsec, hashed_owner); @@ -1530,14 +1567,14 @@ ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, const ldns_rdf *sig_rdf) { /* the EVP api wants the DER encoding of the signature... */ - uint8_t t; BIGNUM *R, *S; DSA_SIG *dsasig; unsigned char *raw_sig = NULL; int raw_sig_len; + if(ldns_rdf_size(sig_rdf) < 1 + 2*SHA_DIGEST_LENGTH) + return LDNS_STATUS_SYNTAX_RDATA_ERR; /* extract the R and S field from the sig buffer */ - t = ldns_rdf_data(sig_rdf)[0]; R = BN_new(); if(!R) return LDNS_STATUS_MEM_ERR; (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 1, @@ -1575,4 +1612,65 @@ ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, return ldns_buffer_status(target_buffer); } + +#ifdef USE_ECDSA +ldns_rdf * +ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len) +{ + ECDSA_SIG* ecdsa_sig; + unsigned char *data = (unsigned char*)ldns_buffer_begin(sig); + ldns_rdf* rdf; + ecdsa_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&data, sig_len); + if(!ecdsa_sig) return NULL; + + /* "r | s". */ + data = LDNS_XMALLOC(unsigned char, + BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)); + if(!data) { + ECDSA_SIG_free(ecdsa_sig); + return NULL; + } + BN_bn2bin(ecdsa_sig->r, data); + BN_bn2bin(ecdsa_sig->s, data+BN_num_bytes(ecdsa_sig->r)); + rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, + BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s), data); + ECDSA_SIG_free(ecdsa_sig); + return rdf; +} + +ldns_status +ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, + const ldns_rdf *sig_rdf) +{ + ECDSA_SIG* sig; + int raw_sig_len; + long bnsize = ldns_rdf_size(sig_rdf) / 2; + /* if too short, or not even length, do not bother */ + if(bnsize < 16 || (size_t)bnsize*2 != ldns_rdf_size(sig_rdf)) + return LDNS_STATUS_ERR; + + /* use the raw data to parse two evenly long BIGNUMs, "r | s". */ + sig = ECDSA_SIG_new(); + if(!sig) return LDNS_STATUS_MEM_ERR; + sig->r = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf), + bnsize, sig->r); + sig->s = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf)+bnsize, + bnsize, sig->s); + if(!sig->r || !sig->s) { + ECDSA_SIG_free(sig); + return LDNS_STATUS_MEM_ERR; + } + + raw_sig_len = i2d_ECDSA_SIG(sig, NULL); + if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) { + unsigned char* pp = ldns_buffer_current(target_buffer); + raw_sig_len = i2d_ECDSA_SIG(sig, &pp); + ldns_buffer_skip(target_buffer, (size_t) raw_sig_len); + } + ECDSA_SIG_free(sig); + + return ldns_buffer_status(target_buffer); +} + +#endif /* USE_ECDSA */ #endif /* HAVE_SSL */ diff --git a/contrib/ldns/dnssec_sign.c b/contrib/ldns/dnssec_sign.c index 2b5cad9c77..d571c93b26 100644 --- a/contrib/ldns/dnssec_sign.c +++ b/contrib/ldns/dnssec_sign.c @@ -31,35 +31,38 @@ ldns_create_empty_rrsig(ldns_rr_list *rrset, label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset, 0))); - + /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */ + if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)))) + label_count --; + current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG); - + /* set the type on the new signature */ orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)); orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0)); ldns_rr_set_ttl(current_sig, orig_ttl); ldns_rr_set_class(current_sig, orig_class); - ldns_rr_set_owner(current_sig, + ldns_rr_set_owner(current_sig, ldns_rdf_clone( ldns_rr_owner( ldns_rr_list_rr(rrset, 0)))); /* fill in what we know of the signature */ - + /* set the orig_ttl */ (void)ldns_rr_rrsig_set_origttl( - current_sig, + current_sig, ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, orig_ttl)); /* the signers name */ (void)ldns_rr_rrsig_set_signame( - current_sig, + current_sig, ldns_rdf_clone(ldns_key_pubkey_owner(current_key))); /* label count - get it from the first rr in the rr_list */ (void)ldns_rr_rrsig_set_labels( - current_sig, + current_sig, ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, label_count)); /* inception, expiration */ @@ -68,7 +71,7 @@ ldns_create_empty_rrsig(ldns_rr_list *rrset, (void)ldns_rr_rrsig_set_inception( current_sig, ldns_native2rdf_int32( - LDNS_RDF_TYPE_TIME, + LDNS_RDF_TYPE_TIME, ldns_key_inception(current_key))); } else { (void)ldns_rr_rrsig_set_inception( @@ -79,25 +82,25 @@ ldns_create_empty_rrsig(ldns_rr_list *rrset, (void)ldns_rr_rrsig_set_expiration( current_sig, ldns_native2rdf_int32( - LDNS_RDF_TYPE_TIME, + LDNS_RDF_TYPE_TIME, ldns_key_expiration(current_key))); } else { (void)ldns_rr_rrsig_set_expiration( current_sig, ldns_native2rdf_int32( - LDNS_RDF_TYPE_TIME, + LDNS_RDF_TYPE_TIME, now + LDNS_DEFAULT_EXP_TIME)); } (void)ldns_rr_rrsig_set_keytag( current_sig, - ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, + ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_key_keytag(current_key))); (void)ldns_rr_rrsig_set_algorithm( current_sig, ldns_native2rdf_int8( - LDNS_RDF_TYPE_ALG, + LDNS_RDF_TYPE_ALG, ldns_key_algorithm(current_key))); (void)ldns_rr_rrsig_set_typecovered( @@ -145,13 +148,27 @@ ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key) break; #endif /* USE_SHA2 */ #ifdef USE_GOST - case LDNS_SIGN_GOST: + case LDNS_SIGN_ECC_GOST: b64rdf = ldns_sign_public_evp( sign_buf, ldns_key_evp_key(current_key), EVP_get_digestbyname("md_gost94")); break; #endif /* USE_GOST */ +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_sha256()); + break; + case LDNS_SIGN_ECDSAP384SHA384: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_sha384()); + break; +#endif case LDNS_SIGN_RSAMD5: b64rdf = ldns_sign_public_evp( sign_buf, @@ -164,7 +181,7 @@ ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key) printf("is the one used available on this system?\n"); break; } - + return b64rdf; } @@ -188,10 +205,9 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) { return NULL; } - + new_owner = NULL; - key_count = 0; signatures = ldns_rr_list_new(); /* prepare a signature and add all the know data @@ -209,7 +225,7 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) } /* sort */ ldns_rr_list_sort(rrset_clone); - + for (key_count = 0; key_count < ldns_key_list_key_count(keys); key_count++) { @@ -228,12 +244,7 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) current_key = ldns_key_list_key(keys, key_count); /* sign all RRs with keys that have ZSKbit, !SEPbit. sign DNSKEY RRs with keys that have ZSKbit&SEPbit */ - if ( - ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY && - (!(ldns_key_flags(current_key) & LDNS_KEY_SEP_KEY) - || ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)) - == LDNS_RR_TYPE_DNSKEY) - ) { + if (ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY) { current_sig = ldns_create_empty_rrsig(rrset_clone, current_key); @@ -300,7 +311,7 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) if (!b64sig) { return NULL; } - + sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), ldns_buffer_position(to_sign), NULL); if (!sha1_hash) { @@ -336,6 +347,32 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) return sigdata_rdf; } +#ifdef USE_ECDSA +static int +ldns_pkey_is_ecdsa(EVP_PKEY* pkey) +{ + EC_KEY* ec; + const EC_GROUP* g; + if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) + return 0; + ec = EVP_PKEY_get1_EC_KEY(pkey); + g = EC_KEY_get0_group(ec); + if(!g) { + EC_KEY_free(ec); + return 0; + } + if(EC_GROUP_get_curve_name(g) == NID_secp224r1 || + EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 || + EC_GROUP_get_curve_name(g) == NID_secp384r1) { + EC_KEY_free(ec); + return 1; + } + /* downref the eckey, the original is still inside the pkey */ + EC_KEY_free(ec); + return 0; +} +#endif /* USE_ECDSA */ + ldns_rdf * ldns_sign_public_evp(ldns_buffer *to_sign, EVP_PKEY *key, @@ -366,7 +403,7 @@ ldns_sign_public_evp(ldns_buffer *to_sign, r = EVP_SignInit(&ctx, md_type); if(r == 1) { r = EVP_SignUpdate(&ctx, (unsigned char*) - ldns_buffer_begin(to_sign), + ldns_buffer_begin(to_sign), ldns_buffer_position(to_sign)); } else { ldns_buffer_free(b64sig); @@ -387,6 +424,11 @@ ldns_sign_public_evp(ldns_buffer *to_sign, /* unfortunately, OpenSSL output is differenct from DNS DSA format */ if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) { sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen); +#ifdef USE_ECDSA + } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC && + ldns_pkey_is_ecdsa(key)) { + sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen); +#endif } else { /* ok output for other types is the same */ sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, @@ -448,7 +490,7 @@ ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key) if (!b64sig) { return NULL; } - + md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign), ldns_buffer_position(to_sign), NULL); if (!md5_hash) { @@ -460,7 +502,7 @@ ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key) (unsigned char*)ldns_buffer_begin(b64sig), &siglen, key); - sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, + sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, ldns_buffer_begin(b64sig)); ldns_buffer_free(b64sig); return sigdata_rdf; @@ -556,12 +598,12 @@ ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, ldns_rr *nsec_rr; uint32_t nsec_ttl; ldns_dnssec_rrsets *soa; - + /* the TTL of NSEC rrs should be set to the minimum TTL of * the zone SOA (RFC4035 Section 2.3) */ soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); - + /* did the caller actually set it? if not, * fall back to default ttl */ @@ -571,7 +613,7 @@ ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, } else { nsec_ttl = LDNS_DEFAULT_TTL; } - + first_node = ldns_dnssec_name_node_next_nonglue( ldns_rbtree_first(zone->names)); cur_node = first_node; @@ -632,16 +674,16 @@ ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, ldns_rr_list *nsec3_list; uint32_t nsec_ttl; ldns_dnssec_rrsets *soa; - + if (!zone || !new_rrs || !zone->names) { return LDNS_STATUS_ERR; } - + /* the TTL of NSEC rrs should be set to the minimum TTL of * the zone SOA (RFC4035 Section 2.3) */ soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); - + /* did the caller actually set it? if not, * fall back to default ttl */ @@ -656,7 +698,7 @@ ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, first_name_node = ldns_dnssec_name_node_next_nonglue( ldns_rbtree_first(zone->names)); - + current_name_node = first_name_node; while (current_name_node && @@ -688,7 +730,7 @@ ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, if (result != LDNS_STATUS_OK) { return result; } - + ldns_rr_list_free(nsec3_list); return result; } @@ -707,7 +749,6 @@ ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures, uint16_t keytag; size_t i; - int v; key_list = key_list; @@ -726,11 +767,11 @@ ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures, } return NULL; } - v = func(cur_rr->rr, arg); + (void)func(cur_rr->rr, arg); while (cur_rr) { next_rr = cur_rr->next; - + switch (func(cur_rr->rr, arg)) { case LDNS_SIGNATURE_LEAVE_ADD_NEW: prev_rr = cur_rr; @@ -790,7 +831,7 @@ ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, int (*func)(ldns_rr *, void*), void *arg) { - return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list, + return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list, func, arg, 0); } @@ -812,6 +853,25 @@ ldns_key_list_filter_for_dnskey(ldns_key_list *key_list) ldns_key_set_use(ldns_key_list_key(key_list, i), 0); } +/** If there are no ZSKs use KSK as ZSK */ +static void +ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list) +{ + int saw_zsk = 0; + size_t i; + for(i=0; isignatures = @@ -863,16 +923,19 @@ ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone, if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) && cur_rrset->type == LDNS_RR_TYPE_DNSKEY) ldns_key_list_filter_for_dnskey(key_list); - + + if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY) + ldns_key_list_filter_for_non_dnskey(key_list); + /* TODO: just set count to zero? */ rr_list = ldns_rr_list_new(); - + cur_rr = cur_rrset->rrs; while (cur_rr) { ldns_rr_list_push_rr(rr_list, cur_rr->rr); cur_rr = cur_rr->next; } - + /* only sign non-delegation RRsets */ /* (glue should have been marked earlier) */ if ((ldns_rr_list_type(rr_list) != LDNS_RR_TYPE_NS || @@ -905,23 +968,25 @@ ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone, } ldns_rr_list_free(siglist); } - + ldns_rr_list_free(rr_list); - + cur_rrset = cur_rrset->next; } - + /* sign the nsec */ + ldns_key_list_set_use(key_list, true); cur_name->nsec_signatures = ldns_dnssec_remove_signatures(cur_name->nsec_signatures, key_list, func, arg); - + ldns_key_list_filter_for_non_dnskey(key_list); + rr_list = ldns_rr_list_new(); ldns_rr_list_push_rr(rr_list, cur_name->nsec); siglist = ldns_sign_public(rr_list, key_list); - + for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { if (cur_name->nsec_signatures) { ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures, @@ -934,7 +999,7 @@ ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone, ldns_rr_list_rr(siglist, i)); } } - + ldns_rr_list_free(siglist); ldns_rr_list_free(rr_list); } @@ -971,7 +1036,7 @@ ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, /* zone is already sorted */ ldns_dnssec_zone_mark_glue(zone); - + /* check whether we need to add nsecs */ if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) { result = ldns_dnssec_zone_create_nsecs(zone, new_rrs); @@ -1075,7 +1140,7 @@ ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone, arg, signflags); } - + return result; } @@ -1092,13 +1157,13 @@ ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list) dnssec_zone = ldns_dnssec_zone_new(); (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); - ldns_zone_set_soa(signed_zone, ldns_zone_soa(zone)); - + ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_rr_list_rr(ldns_zone_rrs(zone), i)); - ldns_zone_push_rr(signed_zone, + ldns_zone_push_rr(signed_zone, ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), i))); } @@ -1133,8 +1198,8 @@ ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm dnssec_zone = ldns_dnssec_zone_new(); (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); - ldns_zone_set_soa(signed_zone, ldns_zone_soa(zone)); - + ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_rr_list_rr(ldns_zone_rrs(zone), diff --git a/contrib/ldns/dnssec_verify.c b/contrib/ldns/dnssec_verify.c index c7cd268861..d979c58e4e 100644 --- a/contrib/ldns/dnssec_verify.c +++ b/contrib/ldns/dnssec_verify.c @@ -635,7 +635,6 @@ ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr) ldns_rr_list *cur_sigs; ldns_rr *cur_rr = NULL; ldns_rr *cur_sig_rr; - uint16_t cur_keytag; size_t i, j; ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new(); @@ -668,9 +667,6 @@ ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr) for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) { /* find the appropriate key in the parent list */ cur_sig_rr = ldns_rr_list_rr(cur_sigs, i); - cur_keytag = - ldns_rdf2native_int16( - ldns_rr_rrsig_keytag(cur_sig_rr)); if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) { if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), @@ -869,7 +865,6 @@ ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree, /*ldns_rr_print(stdout, cur_parent_rr);*/ } } - cur_rr = ldns_rr_list_rr(cur_rrset, 0); } } } @@ -1111,7 +1106,6 @@ ldns_validate_domain_dnskey(const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys) { - ldns_status status; ldns_pkt * keypkt; ldns_rr * cur_key; uint16_t key_i; uint16_t key_j; uint16_t key_k; @@ -1154,10 +1148,9 @@ ldns_validate_domain_dnskey(const ldns_resolver * res, if (ldns_rdf2native_int16( ldns_rr_rrsig_keytag(cur_sig)) == ldns_calc_keytag(cur_key)) { - if ((status = - ldns_verify_rrsig(domain_keys, + if (ldns_verify_rrsig(domain_keys, cur_sig, - cur_key)) + cur_key) == LDNS_STATUS_OK) { /* Push the whole rrset @@ -1194,7 +1187,7 @@ ldns_validate_domain_dnskey(const ldns_resolver * res, ldns_pkt_free(keypkt); } else { - status = LDNS_STATUS_CRYPTO_NO_DNSKEY; + /* LDNS_STATUS_CRYPTO_NO_DNSKEY */ } return trusted_keys; @@ -1205,7 +1198,6 @@ ldns_validate_domain_ds(const ldns_resolver *res, const ldns_rdf * domain, const ldns_rr_list * keys) { - ldns_status status; ldns_pkt * dspkt; uint16_t key_i; ldns_rr_list * rrset = NULL; @@ -1227,8 +1219,7 @@ ldns_validate_domain_ds(const ldns_resolver *res, LDNS_SECTION_ANSWER); /* Validate sigs */ - if ((status = ldns_verify(rrset, sigs, keys, NULL)) - == LDNS_STATUS_OK) { + if (ldns_verify(rrset, sigs, keys, NULL) == LDNS_STATUS_OK) { trusted_keys = ldns_rr_list_new(); for (key_i=0; key_i sizeof(buf)) + return NULL; /* sanity check */ + /* prepend the 0x02 (from docs) (or actually 0x04 from implementation + * of openssl) for uncompressed data */ + buf[0] = POINT_CONVERSION_UNCOMPRESSED; + memmove(buf+1, key, keylen); + if(!o2i_ECPublicKey(&ec, &pp, keylen+1)) { + EC_KEY_free(ec); + return NULL; + } + evp_key = EVP_PKEY_new(); + if(!evp_key) { + EC_KEY_free(ec); + return NULL; + } + EVP_PKEY_assign_EC_KEY(evp_key, ec); + return evp_key; +} + +static ldns_status +ldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen, + ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo) +{ + EVP_PKEY *evp_key; + ldns_status result; + const EVP_MD *d; + + evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo); + if(!evp_key) { + /* could not convert key */ + return LDNS_STATUS_CRYPTO_BOGUS; + } + if(algo == LDNS_ECDSAP256SHA256) + d = EVP_sha256(); + else d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */ + result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d); + EVP_PKEY_free(evp_key); + return result; +} +#endif ldns_status ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, @@ -1616,10 +1659,17 @@ ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen, break; #endif #ifdef USE_GOST - case LDNS_GOST: + case LDNS_ECC_GOST: return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf, key, keylen); break; +#endif +#ifdef USE_ECDSA + case LDNS_ECDSAP256SHA256: + case LDNS_ECDSAP384SHA384: + return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf, + key, keylen, algo); + break; #endif case LDNS_RSAMD5: return ldns_verify_rrsig_rsamd5_raw(sig, @@ -1707,7 +1757,7 @@ ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig) case LDNS_RSASHA512: #endif #ifdef USE_GOST - case LDNS_GOST: + case LDNS_ECC_GOST: #endif if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) { @@ -1726,6 +1776,17 @@ ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig) return LDNS_STATUS_MEM_ERR; } break; +#ifdef USE_ECDSA + case LDNS_ECDSAP256SHA256: + case LDNS_ECDSAP384SHA384: + /* EVP produces an ASN prefix on the signature, which is + * not used in the DNS */ + if (ldns_convert_ecdsa_rrsig_rdf2asn1(rawsig_buf, + ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) { + return LDNS_STATUS_MEM_ERR; + } + break; +#endif case LDNS_DH: case LDNS_ECC: case LDNS_INDIRECT: @@ -1941,8 +2002,8 @@ ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset, ldns_rr_list_free(validkeys); return result; } - result = LDNS_STATUS_ERR; + result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; for(i = 0; i < ldns_rr_list_rr_count(keys); i++) { status = ldns_verify_test_sig_key(rawsig_buf, verify_buf, rrsig, ldns_rr_list_rr(keys, i)); @@ -1960,10 +2021,11 @@ ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset, ldns_rr_list_free(validkeys); return LDNS_STATUS_MEM_ERR; } - /* reset no keytag match error */ - result = LDNS_STATUS_ERR; + + result = status; } - if (result == LDNS_STATUS_ERR) { + + if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) { result = status; } } diff --git a/contrib/ldns/dnssec_zone.c b/contrib/ldns/dnssec_zone.c index bb28362575..91e5651cf3 100644 --- a/contrib/ldns/dnssec_zone.c +++ b/contrib/ldns/dnssec_zone.c @@ -58,7 +58,7 @@ ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr) /* should we error on equal? */ if (cmp <= 0) { if (rrs->next) { - ldns_dnssec_rrs_add_rr(rrs->next, rr); + return ldns_dnssec_rrs_add_rr(rrs->next, rr); } else { new_rrs = ldns_dnssec_rrs_new(); new_rrs->rr = rr; @@ -421,7 +421,7 @@ ldns_dnssec_name_add_rr(ldns_dnssec_name *name, ldns_status result = LDNS_STATUS_OK; ldns_rdf *name_name; bool hashed_name = false; - ldns_rr_type rr_type = ldns_rr_get_type(rr); + ldns_rr_type rr_type; ldns_rr_type typecovered = 0; /* special handling for NSEC3 and NSECX covering RRSIGS */ diff --git a/contrib/ldns/drill/dnssec.c b/contrib/ldns/drill/dnssec.c index 22019533de..930ac7ce13 100644 --- a/contrib/ldns/drill/dnssec.c +++ b/contrib/ldns/drill/dnssec.c @@ -212,7 +212,22 @@ ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_lis } } ldns_rr_list_deep_free(nsecs); - } + } else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) { + ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION); + ldns_rr* q = ldns_rr_new(); + if(!sigs) return LDNS_STATUS_MEM_ERR; + if(!q) 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; + 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); + ldns_rr_free(q); + ldns_rr_list_deep_free(nsecs); + ldns_rr_list_deep_free(sigs); + } return result; } diff --git a/contrib/ldns/drill/drill.1 b/contrib/ldns/drill/drill.1 index 64e850cd48..24cfd6dabe 100644 --- a/contrib/ldns/drill/drill.1 +++ b/contrib/ldns/drill/drill.1 @@ -159,7 +159,7 @@ Use TCP/IP when querying a server 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. +key will be used as trust anchor. Can contain a DNSKEY or a DS record. .TP \fB\-o \fImnemonic\fR diff --git a/contrib/ldns/drill/drill.c b/contrib/ldns/drill/drill.c index 13d09f7ddc..bae04db873 100644 --- a/contrib/ldns/drill/drill.c +++ b/contrib/ldns/drill/drill.c @@ -48,7 +48,7 @@ usage(FILE *stream, const char *progname) fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n"); fprintf(stream, "\t-b \tuse as the buffer size (defaults to 512 b)\n"); fprintf(stream, "\t-c \t\tuse file for rescursive nameserver configuration (/etc/resolv.conf)\n"); - fprintf(stream, "\t-k \tspecify a file that contains a trusted DNSSEC key [**]\n"); + fprintf(stream, "\t-k \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 \tset flags to: [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"); @@ -912,9 +912,7 @@ main(int argc, char *argv[]) ldns_rr_list_deep_free(cmdline_rr_list); ldns_rdf_deep_free(trace_start_name); xfree(progname); -/* xfree(tsig_name); -*/ xfree(tsig_data); xfree(tsig_algorithm); diff --git a/contrib/ldns/drill/securetrace.c b/contrib/ldns/drill/securetrace.c index b05e2da71c..ecc21fdf49 100644 --- a/contrib/ldns/drill/securetrace.c +++ b/contrib/ldns/drill/securetrace.c @@ -134,7 +134,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, ldns_rr_list *new_nss; ldns_rr_list *ns_addr; uint16_t loop_count; - ldns_rdf *pop; + ldns_rdf *pop; ldns_rdf **labels = NULL; ldns_status status, st; ssize_t i; @@ -157,7 +157,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, ldns_rr_list *nsec_rrs = NULL; ldns_rr_list *nsec_rr_sigs = NULL; - + /* empty non-terminal check */ bool ent; @@ -165,9 +165,9 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, ldns_rr_list *new_ns_addr; ldns_rr_list *old_ns_addr; ldns_rr *ns_rr; - + int result = 0; - + /* printing niceness */ const ldns_rr_descriptor *descriptor; @@ -187,13 +187,13 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, res = ldns_resolver_new(); key_sig_list = NULL; ds_sig_list = NULL; - + if (!res) { error("Memory allocation failed"); result = -1; return result; } - + correct_key_list = ldns_rr_list_new(); if (!correct_key_list) { error("Memory allocation failed"); @@ -202,25 +202,31 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, } trusted_ds_rrs = ldns_rr_list_new(); - if (!trusted_ds_rrs) { error("Memory allocation failed"); result = -1; return result; } + /* Add all preset trusted DS signatures to the list of trusted DS RRs. */ + for (j = 0; j < ldns_rr_list_rr_count(trusted_keys); j++) { + ldns_rr* one_rr = ldns_rr_list_rr(trusted_keys, j); + if (ldns_rr_get_type(one_rr) == LDNS_RR_TYPE_DS) { + ldns_rr_list_push_rr(trusted_ds_rrs, ldns_rr_clone(one_rr)); + } + } /* transfer some properties of local_res to res */ - ldns_resolver_set_ip6(res, + ldns_resolver_set_ip6(res, ldns_resolver_ip6(local_res)); - ldns_resolver_set_port(res, + ldns_resolver_set_port(res, ldns_resolver_port(local_res)); - ldns_resolver_set_debug(res, + ldns_resolver_set_debug(res, ldns_resolver_debug(local_res)); - ldns_resolver_set_fail(res, + ldns_resolver_set_fail(res, ldns_resolver_fail(local_res)); - ldns_resolver_set_usevc(res, + ldns_resolver_set_usevc(res, ldns_resolver_usevc(local_res)); - ldns_resolver_set_random(res, + ldns_resolver_set_random(res, ldns_resolver_random(local_res)); ldns_resolver_set_recursive(local_res, true); @@ -264,7 +270,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, } /* get the nameserver for the label - * ask: dnskey and ds for the label + * ask: dnskey and ds for the label */ for(i = (ssize_t)labels_count + 1; i > 0; i--) { status = ldns_resolver_send(&local_p, res, labels[i], LDNS_RR_TYPE_NS, c, 0); @@ -313,14 +319,14 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, ldns_rr_list_deep_free(new_ns_addr); } ldns_rr_list_deep_free(new_nss); - + if (ns_addr) { remove_resolver_nameservers(res); - if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != + if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != LDNS_STATUS_OK) { error("Error adding new nameservers"); - ldns_pkt_free(local_p); + ldns_pkt_free(local_p); goto done; } ldns_rr_list_deep_free(ns_addr); @@ -336,7 +342,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, printf("correct keys:\n"); ldns_rr_list_print(stdout, correct_key_list); } - + if (status == LDNS_STATUS_OK) { if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) { fprintf(stdout, "%s ", TRUST); @@ -382,7 +388,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, ldns_rdf_print(stdout, labels[i]); printf("NS: %s\n", ldns_get_errorstr_by_id(status)); } - + /* there might be an empty non-terminal, in which case we need to continue */ ent = false; for (j = 0; j < ldns_rr_list_rr_count(nsec_rrs); j++) { @@ -397,10 +403,11 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, goto done; } else { printf(";; There is an empty non-terminal here, continue\n"); + continue; } goto done; } - + if (ldns_resolver_nameserver_count(res) == 0) { error("No nameservers found for this node"); goto done; @@ -414,7 +421,7 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, /* retrieve keys for current domain, and verify them if they match an already trusted DS, or if one of the - keys used to sign these is trusted, add the keys to + 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); @@ -428,9 +435,9 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, for (j = 0; j < ldns_rr_list_rr_count(key_list); j++) { ldns_rr_list_push_rr(correct_key_list, ldns_rr_clone(ldns_rr_list_rr(key_list, j))); } - + /* check whether these keys were signed - * by a trusted keys. if so, these + * by a trusted keys. if so, these * keys are also trusted */ new_keys_trusted = false; for (k = 0; k < ldns_rr_list_rr_count(current_correct_keys); k++) { diff --git a/contrib/ldns/error.c b/contrib/ldns/error.c index 7867c2a615..ff240dcc82 100644 --- a/contrib/ldns/error.c +++ b/contrib/ldns/error.c @@ -56,7 +56,7 @@ ldns_lookup_table ldns_error_str[] = { { LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION, "DNSSEC signature has expiration date earlier than inception date" }, { LDNS_STATUS_ENGINE_KEY_NOT_LOADED, "Unable to load private key from engine" }, { LDNS_STATUS_NSEC3_ERR, "Error in NSEC3 denial of existence proof" }, - { LDNS_STATUS_RES_NO_NS, "No nameservers defined in the resolver" }, + { LDNS_STATUS_RES_NO_NS, "No (valid) nameservers defined in the resolver" }, { LDNS_STATUS_RES_QUERY, "No correct query given to resolver" }, { LDNS_STATUS_WIRE_INCOMPLETE_HEADER, "header section incomplete" }, { LDNS_STATUS_WIRE_INCOMPLETE_QUESTION, "question section incomplete" }, @@ -68,6 +68,7 @@ ldns_lookup_table ldns_error_str[] = { { LDNS_STATUS_SYNTAX_TYPE_ERR, "Syntax error, could not parse the RR's type" }, { LDNS_STATUS_SYNTAX_CLASS_ERR, "Syntax error, could not parse the RR's class" }, { LDNS_STATUS_SYNTAX_TTL_ERR, "Syntax error, could not parse the RR's TTL" }, + { LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL, "Syntax error, $INCLUDE not implemented" }, { LDNS_STATUS_SYNTAX_RDATA_ERR, "Syntax error, could not parse the RR's rdata" }, { LDNS_STATUS_SYNTAX_DNAME_ERR, "Syntax error, could not parse the RR's dname(s)" }, { LDNS_STATUS_SYNTAX_VERSION_ERR, "Syntax error, version mismatch" }, @@ -77,6 +78,7 @@ ldns_lookup_table ldns_error_str[] = { { LDNS_STATUS_SYNTAX_EMPTY, "Empty line was returned" }, { LDNS_STATUS_SYNTAX_TTL, "$TTL directive was seen in the zone" }, { LDNS_STATUS_SYNTAX_ORIGIN, "$ORIGIN directive was seen in the zone" }, + { LDNS_STATUS_SYNTAX_INCLUDE, "$INCLUDE directive was seen in the zone" }, { LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW, "Iterations count for NSEC3 record higher than maximum" }, { LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR, "Syntax error, value expected" }, { LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer value too large" }, diff --git a/contrib/ldns/higher.c b/contrib/ldns/higher.c index de1523ffd4..a4ab06f93d 100644 --- a/contrib/ldns/higher.c +++ b/contrib/ldns/higher.c @@ -110,9 +110,7 @@ ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class ldns_pkt *pkt; ldns_rr_list *names; ldns_rdf *name; - size_t i; - i = 0; names = NULL; if (!res || !addr) { @@ -166,6 +164,14 @@ ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr) ip6 = false; list = ldns_rr_list_new(); rr = NULL; + if(!line || !word || !addr || !rr_str || !list) { + LDNS_FREE(line); + LDNS_FREE(word); + LDNS_FREE(addr); + LDNS_FREE(rr_str); + ldns_rr_list_free(list); + return NULL; + } for(i = ldns_fget_token_l(fp, line, "\n", 0, line_nr); i > 0; i = ldns_fget_token_l(fp, line, "\n", 0, line_nr)) { @@ -175,6 +181,14 @@ ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr) } /* put it in a buffer for further processing */ linebuf = LDNS_MALLOC(ldns_buffer); + if(!linebuf) { + LDNS_FREE(line); + LDNS_FREE(word); + LDNS_FREE(addr); + LDNS_FREE(rr_str); + ldns_rr_list_deep_free(list); + return NULL; + } ldns_buffer_new_frm_data(linebuf, line, (size_t) i); for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, 0); diff --git a/contrib/ldns/host2str.c b/contrib/ldns/host2str.c index 7ef5e39118..32ef8a5bad 100644 --- a/contrib/ldns/host2str.c +++ b/contrib/ldns/host2str.c @@ -51,7 +51,11 @@ ldns_lookup_table ldns_algorithms[] = { { LDNS_RSASHA512, "RSASHA512"}, #endif #ifdef USE_GOST - { LDNS_GOST, "GOST"}, + { LDNS_ECC_GOST, "ECC-GOST"}, +#endif +#ifdef USE_ECDSA + { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"}, + { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"}, #endif { LDNS_INDIRECT, "INDIRECT" }, { LDNS_PRIVATEDNS, "PRIVATEDNS" }, @@ -270,8 +274,10 @@ ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname) src_pos++; } + if (src_pos < ldns_rdf_size(dname)) { + ldns_buffer_printf(output, "."); + } len = data[src_pos]; - ldns_buffer_printf(output, "."); } } return ldns_buffer_status(output); @@ -305,14 +311,10 @@ ldns_status ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf) { /* create a YYYYMMDDHHMMSS string if possible */ - uint32_t data = ldns_read_uint32(ldns_rdf_data(rdf)); - time_t data_time; + time_t data_time = (time_t) ldns_read_uint32(ldns_rdf_data(rdf)); struct tm tm; char date_buf[16]; - data_time = 0; - memcpy(&data_time, &data, sizeof(uint32_t)); - memset(&tm, 0, sizeof(tm)); if (gmtime_r(&data_time, &tm) && strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) { @@ -372,6 +374,7 @@ ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf) { size_t size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf)); char *b64 = LDNS_XMALLOC(char, size); + if(!b64) return LDNS_STATUS_MEM_ERR; if (ldns_b64_ntop(ldns_rdf_data(rdf), ldns_rdf_size(rdf), b64, size)) { ldns_buffer_printf(output, "%s", b64); } @@ -382,11 +385,17 @@ ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf) ldns_status ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf) { - size_t size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1); - char *b32 = LDNS_XMALLOC(char, size + 1); + size_t size; + char *b32; + if(ldns_rdf_size(rdf) == 0) + return LDNS_STATUS_OK; + /* remove -1 for the b32-hash-len octet */ + size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1); + /* add one for the end nul for the string */ + b32 = LDNS_XMALLOC(char, size + 1); + if(!b32) return LDNS_STATUS_MEM_ERR; size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1, - ldns_rdf_size(rdf) - 1, - b32, size); + ldns_rdf_size(rdf) - 1, b32, size+1); if (size > 0) { ldns_buffer_printf(output, "%s", b32); } @@ -455,19 +464,7 @@ ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf) /* don't use algorithm mnemonics in the presentation format this kind of got sneaked into the rfc's */ uint8_t data = ldns_rdf_data(rdf)[0]; -/* - - ldns_lookup_table *lt; - - lt = ldns_lookup_by_id(ldns_algorithms, (int) data); - if (lt) { - ldns_buffer_printf(output, "%s", lt->name); - } else { -*/ ldns_buffer_printf(output, "%d", data); -/* - } -*/ return ldns_buffer_status(output); } @@ -648,7 +645,7 @@ ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf) loc_cm_print(output, (vertical_precision & 0xf0) >> 4, vertical_precision & 0x0f); - ldns_buffer_printf(output, "m "); + ldns_buffer_printf(output, "m"); return ldns_buffer_status(output); } else { @@ -763,18 +760,14 @@ ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf) uint8_t salt_pos; uint8_t *data = ldns_rdf_data(rdf); - size_t pos; salt_length = data[0]; - /* todo: length check needed/possible? */ /* from now there are variable length entries so remember pos */ - pos = 1; - if (salt_length == 0) { + if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) { ldns_buffer_printf(output, "- "); } else { for (salt_pos = 0; salt_pos < salt_length; salt_pos++) { ldns_buffer_printf(output, "%02x", data[1 + salt_pos]); - pos++; } ldns_buffer_printf(output, " "); } @@ -816,14 +809,16 @@ ldns_status ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf) { uint8_t *data = ldns_rdf_data(rdf); - uint16_t address_family = ldns_read_uint16(data); - uint8_t prefix = data[2]; + uint16_t address_family; + uint8_t prefix; bool negation; uint8_t adf_length; unsigned short i; unsigned int pos = 0; while (pos < (unsigned int) ldns_rdf_size(rdf)) { + if(pos + 3 >= ldns_rdf_size(rdf)) + return LDNS_STATUS_SYNTAX_RDATA_ERR; address_family = ldns_read_uint16(&data[pos]); prefix = data[pos + 2]; negation = data[pos + 3] & LDNS_APL_NEGATION; @@ -840,6 +835,8 @@ ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf) ldns_buffer_printf(output, "."); } if (i < (unsigned short) adf_length) { + if(pos+i+4 >= ldns_rdf_size(rdf)) + return LDNS_STATUS_SYNTAX_RDATA_ERR; ldns_buffer_printf(output, "%d", data[pos + i + 4]); } else { @@ -859,6 +856,8 @@ ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf) ldns_buffer_printf(output, ":"); } if (i < (unsigned short) adf_length) { + if(pos+i+4 >= ldns_rdf_size(rdf)) + return LDNS_STATUS_SYNTAX_RDATA_ERR; ldns_buffer_printf(output, "%02x", data[pos + i + 4]); } else { @@ -872,6 +871,8 @@ ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf) ldns_buffer_printf(output, "Unknown address family: %u data: ", address_family); for (i = 1; i < (unsigned short) (4 + adf_length); i++) { + if(pos+i >= ldns_rdf_size(rdf)) + return LDNS_STATUS_SYNTAX_RDATA_ERR; ldns_buffer_printf(output, "%02x", data[i]); } } @@ -944,6 +945,8 @@ ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf) break; case 3: status = ldns_wire2dname(&gateway, data, ldns_rdf_size(rdf), &offset); + if(status != LDNS_STATUS_OK) + return status; break; default: /* error? */ @@ -980,7 +983,7 @@ ldns_rdf2buffer_str_tsig(ldns_buffer *output, const ldns_rdf *rdf) ldns_status ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf) { - ldns_status res; + ldns_status res = LDNS_STATUS_OK; /*ldns_buffer_printf(buffer, "%u:", ldns_rdf_get_type(rdf));*/ if (rdf) { @@ -1078,8 +1081,9 @@ ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf) } } else { ldns_buffer_printf(buffer, "(null) "); + res = ldns_buffer_status(buffer); } - return LDNS_STATUS_OK; + return res; } ldns_status @@ -1122,6 +1126,8 @@ ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr) for (i = 0; i < ldns_rr_rd_count(rr); i++) { 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) { ldns_buffer_printf(output, " "); } @@ -1162,7 +1168,8 @@ ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr) uint8_t *data = ldns_rdf_data(ldns_rr_rdf(rr, 3)); size_t len = ldns_rdf_size(ldns_rr_rdf(rr, 3)); char *babble = ldns_bubblebabble(data, len); - ldns_buffer_printf(output, " ; %s", babble); + if(babble) + ldns_buffer_printf(output, " ; %s", babble); LDNS_FREE(babble); } break; @@ -1693,14 +1700,41 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) printf("(Not available)\n"); } break; - case LDNS_SIGN_GOST: + case LDNS_SIGN_ECC_GOST: /* no format defined, use blob */ #if defined(HAVE_SSL) && defined(USE_GOST) ldns_buffer_printf(output, "Private-key-format: v1.2\n"); - ldns_buffer_printf(output, "Algorithm: %d (GOST)\n", LDNS_SIGN_GOST); + ldns_buffer_printf(output, "Algorithm: %d (ECC-GOST)\n", LDNS_SIGN_ECC_GOST); status = ldns_gost_key2buffer_str(output, k->_key.key); #endif break; +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + case LDNS_SIGN_ECDSAP384SHA384: + ldns_buffer_printf(output, "Private-key-format: v1.2\n"); + ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k)); + ldns_algorithm2buffer_str(output, ldns_key_algorithm(k)); + ldns_buffer_printf(output, ")\n"); + if(k->_key.key) { + EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key); + const BIGNUM* b = EC_KEY_get0_private_key(ec); + ldns_buffer_printf(output, "PrivateKey: "); + i = (uint16_t)BN_bn2bin(b, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + /* down reference count in EC_KEY + * its still assigned to the PKEY */ + EC_KEY_free(ec); + } + 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 */ @@ -1771,7 +1805,7 @@ char * ldns_rdf2str(const ldns_rdf *rdf) { char *result = NULL; - ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MIN_BUFLEN); + ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ @@ -1786,7 +1820,7 @@ char * ldns_rr2str(const ldns_rr *rr) { char *result = NULL; - ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MIN_BUFLEN); + ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (ldns_rr2buffer_str(tmp_buffer, rr) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ @@ -1815,7 +1849,7 @@ char * ldns_key2str(const ldns_key *k) { char *result = NULL; - ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MIN_BUFLEN); + ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ result = ldns_buffer2str(tmp_buffer); @@ -1828,7 +1862,7 @@ char * ldns_rr_list2str(const ldns_rr_list *list) { char *result = NULL; - ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MIN_BUFLEN); + ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (list) { if (ldns_rr_list2buffer_str(tmp_buffer, list) == LDNS_STATUS_OK) { @@ -1911,20 +1945,32 @@ ldns_resolver_print(FILE *output, const ldns_resolver *r) fprintf(output, "igntc: %d\n", ldns_resolver_igntc(r)); fprintf(output, "fail: %d\n", ldns_resolver_fail(r)); fprintf(output, "retry: %d\n", (int)ldns_resolver_retry(r)); + fprintf(output, "retrans: %d\n", (int)ldns_resolver_retrans(r)); + fprintf(output, "fallback: %d\n", ldns_resolver_fallback(r)); + fprintf(output, "random: %d\n", ldns_resolver_random(r)); fprintf(output, "timeout: %d\n", (int)ldns_resolver_timeout(r).tv_sec); + fprintf(output, "dnssec: %d\n", ldns_resolver_dnssec(r)); + fprintf(output, "dnssec cd: %d\n", ldns_resolver_dnssec_cd(r)); + fprintf(output, "trust anchors (%d listed):\n", + (int)ldns_rr_list_rr_count(ldns_resolver_dnssec_anchors(r))); + ldns_rr_list_print(output, ldns_resolver_dnssec_anchors(r)); + fprintf(output, "tsig: %s %s\n", ldns_resolver_tsig_keyname(r), ldns_resolver_tsig_algorithm(r)); + fprintf(output, "debug: %d\n", ldns_resolver_debug(r)); fprintf(output, "default domain: "); ldns_rdf_print(output, ldns_resolver_domain(r)); fprintf(output, "\n"); + fprintf(output, "apply default domain: %d\n", ldns_resolver_defnames(r)); - fprintf(output, "searchlist:\n"); + fprintf(output, "searchlist (%d listed):\n", (int)ldns_resolver_searchlist_count(r)); for (i = 0; i < ldns_resolver_searchlist_count(r); i++) { fprintf(output, "\t"); ldns_rdf_print(output, s[i]); fprintf(output, "\n"); } + fprintf(output, "apply search list: %d\n", ldns_resolver_dnsrch(r)); - fprintf(output, "nameservers:\n"); + fprintf(output, "nameservers (%d listed):\n", (int)ldns_resolver_nameserver_count(r)); for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { fprintf(output, "\t"); ldns_rdf_print(output, n[i]); diff --git a/contrib/ldns/host2wire.c b/contrib/ldns/host2wire.c index c1f0f0dc5d..93b017df74 100644 --- a/contrib/ldns/host2wire.c +++ b/contrib/ldns/host2wire.c @@ -75,7 +75,7 @@ ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list) rr_count = ldns_rr_list_rr_count(rr_list); for(i = 0; i < rr_count; i++) { - (void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), + ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANY); } return ldns_buffer_status(buffer); @@ -308,6 +308,7 @@ ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) /* add EDNS to additional if it is needed */ if (ldns_pkt_edns(packet)) { edns_rr = ldns_rr_new(); + if(!edns_rr) return LDNS_STATUS_MEM_ERR; ldns_rr_set_owner(edns_rr, ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, ".")); ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT); @@ -343,17 +344,23 @@ ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size) ldns_status status; *result_size = 0; *dest = NULL; + if(!buffer) return LDNS_STATUS_MEM_ERR; 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)); } @@ -369,17 +376,23 @@ ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size ldns_status status; *result_size = 0; *dest = NULL; + if(!buffer) return LDNS_STATUS_MEM_ERR; 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)); } @@ -395,17 +408,23 @@ ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size) ldns_status status; *result_size = 0; *dest = NULL; + if(!buffer) return LDNS_STATUS_MEM_ERR; 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; } 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)); } diff --git a/contrib/ldns/keys.c b/contrib/ldns/keys.c index 4d03542460..e0fffc7068 100644 --- a/contrib/ldns/keys.c +++ b/contrib/ldns/keys.c @@ -23,16 +23,20 @@ ldns_lookup_table ldns_signing_algorithms[] = { { LDNS_SIGN_RSAMD5, "RSAMD5" }, { LDNS_SIGN_RSASHA1, "RSASHA1" }, - { LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1_NSEC3" }, + { LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" }, #ifdef USE_SHA2 { LDNS_SIGN_RSASHA256, "RSASHA256" }, { LDNS_SIGN_RSASHA512, "RSASHA512" }, #endif #ifdef USE_GOST - { LDNS_SIGN_GOST, "GOST" }, + { LDNS_SIGN_ECC_GOST, "ECC-GOST" }, +#endif +#ifdef USE_ECDSA + { LDNS_SIGN_ECDSAP256SHA256, "ECDSAP256SHA256" }, + { LDNS_SIGN_ECDSAP384SHA384, "ECDSAP384SHA384" }, #endif { LDNS_SIGN_DSA, "DSA" }, - { LDNS_SIGN_DSA_NSEC3, "DSA_NSEC3" }, + { LDNS_SIGN_DSA_NSEC3, "DSA-NSEC3-SHA1" }, { LDNS_SIGN_HMACMD5, "hmac-md5.sig-alg.reg.int" }, { LDNS_SIGN_HMACSHA1, "hmac-sha1" }, { LDNS_SIGN_HMACSHA256, "hmac-sha256" }, @@ -103,6 +107,9 @@ ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm #endif #ifdef USE_GOST +/** store GOST engine reference loaded into OpenSSL library */ +ENGINE* ldns_gost_engine = NULL; + int ldns_key_EVP_load_gost_id(void) { @@ -138,15 +145,27 @@ ldns_key_EVP_load_gost_id(void) } meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); - ENGINE_finish(e); - ENGINE_free(e); if(!meth) { /* algo not found */ + ENGINE_finish(e); + ENGINE_free(e); return 0; } + /* Note: do not ENGINE_finish and ENGINE_free the acquired engine + * on some platforms this frees up the meth and unloads gost stuff */ + ldns_gost_engine = e; EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); return gost_id; +} + +void ldns_key_EVP_unload_gost(void) +{ + if(ldns_gost_engine) { + ENGINE_finish(ldns_gost_engine); + ENGINE_free(ldns_gost_engine); + ldns_gost_engine = NULL; + } } /** read GOST private key */ @@ -181,6 +200,83 @@ ldns_key_new_frm_fp_gost_l(FILE* fp, int* line_nr) } #endif +#ifdef USE_ECDSA +/** calculate public key from private key */ +static int +ldns_EC_KEY_calc_public(EC_KEY* ec) +{ + EC_POINT* pub_key; + const EC_GROUP* group; + group = EC_KEY_get0_group(ec); + pub_key = EC_POINT_new(group); + if(!pub_key) return 0; + if(!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { + EC_POINT_free(pub_key); + return 0; + } + if(!EC_POINT_mul(group, pub_key, EC_KEY_get0_private_key(ec), + NULL, NULL, NULL)) { + EC_POINT_free(pub_key); + return 0; + } + if(EC_KEY_set_public_key(ec, pub_key) == 0) { + EC_POINT_free(pub_key); + return 0; + } + EC_POINT_free(pub_key); + return 1; +} + +/** read ECDSA private key */ +static EVP_PKEY* +ldns_key_new_frm_fp_ecdsa_l(FILE* fp, ldns_algorithm alg, int* line_nr) +{ + char token[16384]; + ldns_rdf* b64rdf = NULL; + unsigned char* pp; + BIGNUM* bn; + EVP_PKEY* evp_key; + EC_KEY* ec; + if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n", + sizeof(token), line_nr) == -1) + return NULL; + if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK) + return NULL; + pp = (unsigned char*)ldns_rdf_data(b64rdf); + + if(alg == LDNS_ECDSAP256SHA256) + ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + else if(alg == LDNS_ECDSAP384SHA384) + ec = EC_KEY_new_by_curve_name(NID_secp384r1); + else ec = NULL; + if(!ec) { + ldns_rdf_deep_free(b64rdf); + return NULL; + } + bn = BN_bin2bn(pp, ldns_rdf_size(b64rdf), NULL); + ldns_rdf_deep_free(b64rdf); + if(!bn) { + EC_KEY_free(ec); + return NULL; + } + EC_KEY_set_private_key(ec, bn); + BN_free(bn); + if(!ldns_EC_KEY_calc_public(ec)) { + EC_KEY_free(ec); + return NULL; + } + + evp_key = EVP_PKEY_new(); + if(!evp_key) { + EC_KEY_free(ec); + return NULL; + } + EVP_PKEY_assign_EC_KEY(evp_key, ec); + + return evp_key; +} +#endif + ldns_status ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) { @@ -266,14 +362,22 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) fprintf(stderr, "version of ldns\n"); #endif } - if (strncmp(d, "249 GOST", 4) == 0) { + if (strncmp(d, "12 ECC-GOST", 3) == 0) { #ifdef USE_GOST - alg = LDNS_SIGN_GOST; + alg = LDNS_SIGN_ECC_GOST; #else - fprintf(stderr, "Warning: GOST not compiled into this "); - fprintf(stderr, "version of ldns\n"); + fprintf(stderr, "Warning: ECC-GOST not compiled into this "); + fprintf(stderr, "version of ldns, use --enable-gost\n"); #endif } +#ifdef USE_ECDSA + if (strncmp(d, "13 ECDSAP256SHA256", 3) == 0) { + alg = LDNS_ECDSAP256SHA256; + } + if (strncmp(d, "14 ECDSAP384SHA384", 3) == 0) { + alg = LDNS_ECDSAP384SHA384; + } +#endif if (strncmp(d, "157 HMAC-MD5", 4) == 0) { alg = LDNS_SIGN_HMACMD5; } @@ -332,9 +436,13 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) ldns_key_set_hmac_key(k, hmac); #endif /* HAVE_SSL */ break; - case LDNS_SIGN_GOST: + case LDNS_SIGN_ECC_GOST: ldns_key_set_algorithm(k, alg); #if defined(HAVE_SSL) && defined(USE_GOST) + if(!ldns_key_EVP_load_gost_id()) { + ldns_key_free(k); + return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL; + } ldns_key_set_evp_key(k, ldns_key_new_frm_fp_gost_l(fp, line_nr)); if(!k->_key.key) { @@ -343,10 +451,21 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) } #endif break; +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + case LDNS_SIGN_ECDSAP384SHA384: + ldns_key_set_algorithm(k, alg); + ldns_key_set_evp_key(k, + ldns_key_new_frm_fp_ecdsa_l(fp, alg, line_nr)); + if(!k->_key.key) { + ldns_key_free(k); + return LDNS_STATUS_ERR; + } + break; +#endif case 0: default: return LDNS_STATUS_SYNTAX_ALG_ERR; - break; } key_rr = ldns_key2rr(k); ldns_key_set_keytag(k, ldns_calc_keytag(key_rr)); @@ -664,6 +783,9 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) #ifdef HAVE_SSL DSA *d; RSA *r; +# ifdef USE_ECDSA + EC_KEY *ec = NULL; +# endif #else int i; uint16_t offset = 0; @@ -733,11 +855,31 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) ldns_key_set_flags(k, 0); break; - case LDNS_SIGN_GOST: + case LDNS_SIGN_ECC_GOST: #if defined(HAVE_SSL) && defined(USE_GOST) ldns_key_set_evp_key(k, ldns_gen_gost_key()); #endif /* HAVE_SSL and USE_GOST */ + break; +#ifdef USE_ECDSA + case LDNS_ECDSAP256SHA256: + case LDNS_ECDSAP384SHA384: + if(alg == LDNS_ECDSAP256SHA256) + ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + else if(alg == LDNS_ECDSAP384SHA384) + ec = EC_KEY_new_by_curve_name(NID_secp384r1); + if(!ec) return NULL; + if(!EC_KEY_generate_key(ec)) { + EC_KEY_free(ec); + return NULL; + } + k->_key.key = EVP_PKEY_new(); + if(!k->_key.key) { + EC_KEY_free(ec); + return NULL; + } + EVP_PKEY_assign_EC_KEY(k->_key.key, ec); break; +#endif } ldns_key_set_algorithm(k, alg); return k; @@ -994,7 +1136,6 @@ ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key) ldns_key **keys; key_count = ldns_key_list_key_count(key_list); - keys = key_list->_keys; /* grow the array */ keys = LDNS_XREALLOC( @@ -1111,13 +1252,10 @@ ldns_key_gost2bin(unsigned char* data, EVP_PKEY* k, uint16_t* size) return false; } /* omit ASN header */ - /* insert parameters */ - data[0] = 0; - data[1] = 0; for(i=0; i<64; i++) - data[i+2] = pp[i+37]; + data[i] = pp[i+37]; CRYPTO_free(pp); - *size = 66; + *size = 64; return true; } #endif /* USE_GOST */ @@ -1139,6 +1277,9 @@ ldns_key2rr(const ldns_key *k) RSA *rsa = NULL; DSA *dsa = NULL; #endif /* HAVE_SSL */ +#ifdef USE_ECDSA + EC_KEY* ec; +#endif int internal_data = 0; pubkey = ldns_rr_new(); @@ -1229,7 +1370,7 @@ ldns_key2rr(const ldns_key *k) } #endif /* HAVE_SSL */ break; - case LDNS_SIGN_GOST: + case LDNS_SIGN_ECC_GOST: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8( LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); #if defined(HAVE_SSL) && defined(USE_GOST) @@ -1240,8 +1381,34 @@ ldns_key2rr(const ldns_key *k) return NULL; } internal_data = 1; - break; #endif /* HAVE_SSL and USE_GOST */ + break; +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + case LDNS_SIGN_ECDSAP384SHA384: + ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8( + LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); + bin = NULL; + ec = EVP_PKEY_get1_EC_KEY(k->_key.key); + EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); + size = i2o_ECPublicKey(ec, NULL); + if(!i2o_ECPublicKey(ec, &bin)) + return NULL; + if(size > 1) { + /* move back one byte to shave off the 0x02 + * 'uncompressed' indicator that openssl made + * Actually its 0x04 (from implementation). + */ + assert(bin[0] == POINT_CONVERSION_UNCOMPRESSED); + size -= 1; + memmove(bin, bin+1, size); + } + /* down the reference count for ec, its still assigned + * to the pkey */ + EC_KEY_free(ec); + internal_data = 1; + break; +#endif case LDNS_SIGN_HMACMD5: case LDNS_SIGN_HMACSHA1: case LDNS_SIGN_HMACSHA256: @@ -1371,3 +1538,41 @@ int ldns_key_algo_supported(int algo) } return 0; } + +ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name) +{ + /* list of (signing algorithm id, alias_name) */ + ldns_lookup_table aliases[] = { + /* from bind dnssec-keygen */ + {LDNS_SIGN_HMACMD5, "HMAC-MD5"}, + {LDNS_SIGN_DSA_NSEC3, "NSEC3DSA"}, + {LDNS_SIGN_RSASHA1_NSEC3, "NSEC3RSASHA1"}, + /* old ldns usage, now RFC names */ + {LDNS_SIGN_DSA_NSEC3, "DSA_NSEC3" }, + {LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1_NSEC3" }, +#ifdef USE_GOST + {LDNS_SIGN_ECC_GOST, "GOST"}, +#endif + /* compat with possible output */ + {LDNS_DH, "DH"}, + {LDNS_ECC, "ECC"}, + {LDNS_INDIRECT, "INDIRECT"}, + {LDNS_PRIVATEDNS, "PRIVATEDNS"}, + {LDNS_PRIVATEOID, "PRIVATEOID"}, + {0, NULL}}; + ldns_lookup_table* lt = ldns_signing_algorithms; + while(lt->name) { + if(strcasecmp(lt->name, name) == 0) + return lt->id; + lt++; + } + lt = aliases; + while(lt->name) { + if(strcasecmp(lt->name, name) == 0) + return lt->id; + lt++; + } + if(atoi(name) != 0) + return atoi(name); + return 0; +} diff --git a/contrib/ldns/ldns/buffer.h b/contrib/ldns/ldns/buffer.h index 4e5f9feb65..65b8bdc4ad 100644 --- a/contrib/ldns/ldns/buffer.h +++ b/contrib/ldns/ldns/buffer.h @@ -22,6 +22,10 @@ #include "ldns/util.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * number of initial bytes in buffer of * which we cannot tell the size before hand @@ -633,4 +637,8 @@ void *ldns_buffer_export(ldns_buffer *buffer); */ void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_BUFFER_H */ diff --git a/contrib/ldns/ldns/common.h b/contrib/ldns/ldns/common.h index 8e09f3b008..cc7dd89d1a 100644 --- a/contrib/ldns/ldns/common.h +++ b/contrib/ldns/ldns/common.h @@ -23,7 +23,7 @@ /*@ignore@*/ /* splint barfs on this construct */ -typedef unsigned char bool; +typedef unsigned int bool; #define bool bool #define false 0 #define true 1 diff --git a/contrib/ldns/ldns/config.h.in b/contrib/ldns/ldns/config.h.in deleted file mode 100644 index 9db78432a6..0000000000 --- a/contrib/ldns/ldns/config.h.in +++ /dev/null @@ -1,443 +0,0 @@ -/* ldns/config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if building universal (internal helper macro) */ -#undef AC_APPLE_UNIVERSAL_BUILD - -/* Define to 1 if you have the header file. */ -#undef HAVE_ARPA_INET_H - -/* Whether the C compiler accepts the "format" attribute */ -#undef HAVE_ATTR_FORMAT - -/* Whether the C compiler accepts the "unused" attribute */ -#undef HAVE_ATTR_UNUSED - -/* Define to 1 if you have the `b32_ntop' function. */ -#undef HAVE_B32_NTOP - -/* Define to 1 if you have the `b32_pton' function. */ -#undef HAVE_B32_PTON - -/* Define to 1 if you have the `b64_ntop' function. */ -#undef HAVE_B64_NTOP - -/* Define to 1 if you have the `b64_pton' function. */ -#undef HAVE_B64_PTON - -/* Define to 1 if you have the `ctime_r' function. */ -#undef HAVE_CTIME_R - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the `endprotoent' function. */ -#undef HAVE_ENDPROTOENT - -/* Define to 1 if you have the `endservent' function. */ -#undef HAVE_ENDSERVENT - -/* Define to 1 if you have the `EVP_sha256' function. */ -#undef HAVE_EVP_SHA256 - -/* Define to 1 if you have the `fcntl' function. */ -#undef HAVE_FCNTL - -/* Whether getaddrinfo is available */ -#undef HAVE_GETADDRINFO - -/* Define to 1 if you have the header file. */ -#undef HAVE_GETOPT_H - -/* Define to 1 if you have the `gmtime_r' function. */ -#undef HAVE_GMTIME_R - -/* If you have HMAC_CTX_init */ -#undef HAVE_HMAC_CTX_INIT - -/* Define to 1 if you have the `inet_aton' function. */ -#undef HAVE_INET_ATON - -/* Define to 1 if you have the `inet_ntop' function. */ -#undef HAVE_INET_NTOP - -/* Define to 1 if you have the `inet_pton' function. */ -#undef HAVE_INET_PTON - -/* define if you have inttypes.h */ -#undef HAVE_INTTYPES_H - -/* if the function 'ioctlsocket' is available */ -#undef HAVE_IOCTLSOCKET - -/* Define to 1 if you have the `isblank' function. */ -#undef HAVE_ISBLANK - -/* Define to 1 if you have the `crypto' library (-lcrypto). */ -#undef HAVE_LIBCRYPTO - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#undef HAVE_LIBNSL - -/* Define to 1 if you have the `socket' library (-lsocket). */ -#undef HAVE_LIBSOCKET - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#undef HAVE_MALLOC - -/* Define to 1 if you have the `memmove' function. */ -#undef HAVE_MEMMOVE - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETDB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETINET_IN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_ERR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_RAND_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_SSL_H - -/* Define if you have Python libraries and header files. */ -#undef HAVE_PYTHON - -/* Define to 1 if you have the `random' function. */ -#undef HAVE_RANDOM - -/* Define to 1 if your system has a GNU libc compatible `realloc' function, - and to 0 otherwise. */ -#undef HAVE_REALLOC - -/* Define to 1 if you have the `sleep' function. */ -#undef HAVE_SLEEP - -/* Define to 1 if you have the `snprintf' function. */ -#undef HAVE_SNPRINTF - -/* Define if you have the SSL libraries installed. */ -#undef HAVE_SSL - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDARG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDBOOL_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the `strlcpy' function. */ -#undef HAVE_STRLCPY - -/* Define if you have Swig libraries and header files. */ -#undef HAVE_SWIG - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_MOUNT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_PARAM_H - -/* define if you have sys/socket.h */ -#undef HAVE_SYS_SOCKET_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the `timegm' function. */ -#undef HAVE_TIMEGM - -/* Define to 1 if you have the header file. */ -#undef HAVE_TIME_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_WINSOCK2_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_WS2TCPIP_H - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* System configuration dir */ -#undef SYSCONFDIR - -/* Define this to enable GOST support. */ -#undef USE_GOST - -/* Define this to enable SHA256 and SHA512 support. */ -#undef USE_SHA2 - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# undef _ALL_SOURCE -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# undef _GNU_SOURCE -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# undef _POSIX_PTHREAD_SEMANTICS -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -# undef _TANDEM_SOURCE -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# undef __EXTENSIONS__ -#endif - - -/* Whether the windows socket API is used */ -#undef USE_WINSOCK - -/* the version of the windows API enabled */ -#undef WINVER - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif - -/* Define to 1 if on MINIX. */ -#undef _MINIX - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -#undef _POSIX_1_SOURCE - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -#undef _POSIX_SOURCE - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* in_addr_t */ -#undef in_addr_t - -/* in_port_t */ -#undef in_port_t - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to `short' if does not define. */ -#undef int16_t - -/* Define to `int' if does not define. */ -#undef int32_t - -/* Define to `long long' if does not define. */ -#undef int64_t - -/* Define to `char' if does not define. */ -#undef int8_t - -/* Define to rpl_malloc if the replacement function should be used. */ -#undef malloc - -/* Define to rpl_realloc if the replacement function should be used. */ -#undef realloc - -/* Define to 'int' if not defined */ -#undef socklen_t - -/* Define to `int' if does not define. */ -#undef ssize_t - -/* Define to `unsigned short' if does not define. */ -#undef uint16_t - -/* Define to `unsigned int' if does not define. */ -#undef uint32_t - -/* Define to `unsigned long long' if does not define. */ -#undef uint64_t - -/* Define to `unsigned char' if does not define. */ -#undef uint8_t - - -#include -#include -#include -#include - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif - -#ifndef BYTE_ORDER -#ifdef WORDS_BIGENDIAN -#define BYTE_ORDER BIG_ENDIAN -#else -#define BYTE_ORDER LITTLE_ENDIAN -#endif /* WORDS_BIGENDIAN */ -#endif /* BYTE_ORDER */ - -#if STDC_HEADERS -#include -#include -#endif - -#ifdef HAVE_STDINT_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif - - -/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ -#ifdef HAVE_WINSOCK2_H -#define FD_SET_T (u_int) -#else -#define FD_SET_T -#endif - - - - -#ifndef B64_PTON -int ldns_b64_ntop(uint8_t const *src, size_t srclength, - char *target, size_t targsize); -/** - * calculates the size needed to store the result of b64_ntop - */ -/*@unused@*/ -static inline size_t ldns_b64_ntop_calculate_size(size_t srcsize) -{ - return ((((srcsize + 2) / 3) * 4) + 1); -} -#endif /* !B64_PTON */ -#ifndef B64_NTOP -int ldns_b64_pton(char const *src, uint8_t *target, size_t targsize); -/** - * calculates the size needed to store the result of ldns_b64_pton - */ -/*@unused@*/ -static inline size_t ldns_b64_pton_calculate_size(size_t srcsize) -{ - return ((((srcsize / 4) * 3) - 2) + 2); -} -#endif /* !B64_NTOP */ - -#ifndef HAVE_SLEEP -/* use windows sleep, in millisecs, instead */ -#define sleep(x) Sleep((x)*1000) -#endif - -#ifndef HAVE_RANDOM -#define srandom(x) srand(x) -#define random(x) rand(x) -#endif - -#ifndef HAVE_TIMEGM -#include -time_t timegm (struct tm *tm); -#endif /* !TIMEGM */ -#ifndef HAVE_GMTIME_R -struct tm *gmtime_r(const time_t *timep, struct tm *result); -#endif -#ifndef HAVE_ISBLANK -int isblank(int c); -#endif /* !HAVE_ISBLANK */ -#ifndef HAVE_SNPRINTF -#include -int snprintf (char *str, size_t count, const char *fmt, ...); -int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); -#endif /* HAVE_SNPRINTF */ -#ifndef HAVE_INET_PTON -int inet_pton(int af, const char* src, void* dst); -#endif /* HAVE_INET_PTON */ -#ifndef HAVE_INET_NTOP -const char *inet_ntop(int af, const void *src, char *dst, size_t size); -#endif -#ifndef HAVE_INET_ATON -int inet_aton(const char *cp, struct in_addr *addr); -#endif -#ifndef HAVE_MEMMOVE -void *memmove(void *dest, const void *src, size_t n); -#endif -#ifndef HAVE_STRLCPY -size_t strlcpy(char *dst, const char *src, size_t siz); -#endif -#ifndef HAVE_GETADDRINFO -#include "compat/fake-rfc2553.h" -#endif - diff --git a/contrib/ldns/ldns/dname.h b/contrib/ldns/ldns/dname.h index b144b4c78c..a91f075257 100644 --- a/contrib/ldns/ldns/dname.h +++ b/contrib/ldns/ldns/dname.h @@ -31,7 +31,7 @@ * * Domain names are stored in \ref ldns_rdf structures, with the type * \ref LDNS_RDF_TYPE_DNAME - * + * * This module is *NOT* about the RR type called DNAME. */ @@ -42,6 +42,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define LDNS_DNAME_NORMALIZE tolower /** @@ -74,14 +78,14 @@ ldns_rdf *ldns_dname_reverse(const ldns_rdf *d); * \param[in] n the label nr to clone from, if this is 0, the complete * dname is cloned * \return A newly allocated *rdf structure, containing the cloned dname, - * or NULL if either d was NULL, not a dname, or if n >= + * or NULL if either d was NULL, not a dname, or if n >= * label_count */ ldns_rdf * ldns_dname_clone_from(const ldns_rdf *d, uint16_t n); /** - * chop one label off the left side of a dname. so + * chop one label off the left side of a dname. so * wwww.nlnetlabs.nl, becomes nlnetlabs.nl * This new name is a clone and must be freed with ldns_deep_free() * \param[in] d the dname to chop @@ -93,7 +97,7 @@ ldns_rdf *ldns_dname_left_chop(const ldns_rdf *d); * count the number of labels inside a LDNS_RDF_DNAME type rdf. * \param[in] *r the rdf * \return the number of labels - */ + */ uint8_t ldns_dname_label_count(const ldns_rdf *r); /** @@ -105,7 +109,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] s the size of the new dname * \param[in] *data pointer to the actual data * \return ldns_rdf* */ @@ -183,4 +187,15 @@ bool ldns_dname_str_absolute(const char *dname_str); */ ldns_rdf * ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos); +/** + * Check if dname is a wildcard, starts with *. + * \param[in] dname: the rdf to look in + * \return true if a wildcard, false if not. + */ +int ldns_dname_is_wildcard(const ldns_rdf* dname); + +#ifdef __cplusplus +} +#endif + #endif /* LDNS_DNAME_H */ diff --git a/contrib/ldns/ldns/dnssec.h b/contrib/ldns/ldns/dnssec.h index c95b32b6f6..7bfc70b710 100644 --- a/contrib/ldns/ldns/dnssec.h +++ b/contrib/ldns/ldns/dnssec.h @@ -34,6 +34,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define LDNS_MAX_KEYLEN 2048 #define LDNS_DNSSEC_KEYPROTO 3 /* default time before sigs expire */ @@ -159,6 +163,16 @@ int ldns_digest_evp(unsigned char* data, unsigned int len, */ EVP_PKEY* ldns_gost2pkey_raw(unsigned char* key, size_t keylen); +/** + * Converts a holding buffer with key material to EVP PKEY in openssl. + * Only available if ldns was compiled with ECDSA. + * \param[in] key data to convert + * \param[in] keylen length of the key data + * \param[in] algo precise algorithm to initialize ECC group values. + * \return the key or NULL on error. + */ +EVP_PKEY* ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo); + #endif /* HAVE_SSL */ #ifdef HAVE_SSL @@ -363,7 +377,7 @@ bool ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name); * 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 ckeck + * \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[out] good_keys keys which validated the packet @@ -449,6 +463,35 @@ ldns_status ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, const ldns_rdf *sig_rdf); +/** + * Converts the ECDSA signature from ASN1 representation (as + * used by OpenSSL) to raw signature data as used in DNS + * This routine is only present if ldns is compiled with ecdsa support. + * + * \param[in] sig The signature in ASN1 format + * \param[in] sig_len The length of the signature + * \return a new rdf with the signature + */ +ldns_rdf * +ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len); + +/** + * Converts the RRSIG signature RDF (from DNS) to a buffer with the + * signature in ASN1 format as openssl uses it. + * This routine is only present if ldns is compiled with ecdsa support. + * + * \param[out] target_buffer buffer to place the signature data in ASN1. + * \param[in] sig_rdf The signature rdf to convert + * \return LDNS_STATUS_OK on success, error code otherwise + */ +ldns_status +ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, + const ldns_rdf *sig_rdf); + #endif /* HAVE_SSL */ +#ifdef __cplusplus +} +#endif + #endif /* LDNS_DNSSEC_H */ diff --git a/contrib/ldns/ldns/dnssec_sign.h b/contrib/ldns/ldns/dnssec_sign.h index 64683c0649..5b3921ab20 100644 --- a/contrib/ldns/ldns/dnssec_sign.h +++ b/contrib/ldns/ldns/dnssec_sign.h @@ -5,6 +5,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* sign functions */ /** Sign flag that makes DNSKEY type signed by all keys, not only by SEP keys*/ @@ -307,6 +311,8 @@ ldns_zone *ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list); */ ldns_zone *ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt); - +#ifdef __cplusplus +} +#endif #endif diff --git a/contrib/ldns/ldns/dnssec_verify.h b/contrib/ldns/ldns/dnssec_verify.h index 58e74678b5..8d380f9cee 100644 --- a/contrib/ldns/ldns/dnssec_verify.h +++ b/contrib/ldns/ldns/dnssec_verify.h @@ -7,6 +7,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /** * Chain structure that contains all DNSSEC data needed to * verify an rrset @@ -258,7 +262,7 @@ ldns_status ldns_dnssec_trust_tree_contains_keys( * \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[out] good_keys if this is a (initialized) list, the keys + * \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 @@ -275,7 +279,7 @@ ldns_status ldns_verify(ldns_rr_list *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[out] good_keys if this is a (initialized) list, the keys + * \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 @@ -337,7 +341,7 @@ ldns_rr_list *ldns_validate_domain_ds(const ldns_resolver *res, * \param[in] res the current resolver * \param[in] rrset the rrset to verify * \param[in] rrsigs a list of signatures to check - * \param[out] validating_keys if this is a (initialized) list, the + * \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 @@ -423,7 +427,7 @@ ldns_status ldns_verify_rrsig_buffers_raw(unsigned char* sig, * \param[in] rrset the rrset to check * \param[in] rrsig the signature of the rrset * \param[in] keys the keys to try - * \param[out] good_keys if this is a (initialized) list, the keys + * \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 @@ -439,7 +443,7 @@ ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset, * \param[in] rrset the rrset to check * \param[in] rrsig the signature of the rrset * \param[in] keys the keys to try - * \param[out] good_keys if this is a (initialized) list, the keys + * \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 @@ -600,5 +604,9 @@ ldns_status ldns_verify_rrsig_rsamd5_raw(unsigned char* sig, unsigned char* key, size_t keylen); +#ifdef __cplusplus +} +#endif + #endif diff --git a/contrib/ldns/ldns/dnssec_zone.h b/contrib/ldns/ldns/dnssec_zone.h index 196f1931b7..88117dafb3 100644 --- a/contrib/ldns/ldns/dnssec_zone.h +++ b/contrib/ldns/ldns/dnssec_zone.h @@ -11,6 +11,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** * Singly linked list of rrs */ @@ -355,4 +359,8 @@ void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone); */ ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone); +#ifdef __cplusplus +} +#endif + #endif diff --git a/contrib/ldns/ldns/error.h b/contrib/ldns/ldns/error.h index 73dbb2b0cb..e17846f38b 100644 --- a/contrib/ldns/ldns/error.h +++ b/contrib/ldns/ldns/error.h @@ -18,6 +18,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + enum ldns_enum_status { LDNS_STATUS_OK, LDNS_STATUS_EMPTY_LABEL, @@ -75,6 +79,7 @@ enum ldns_enum_status { LDNS_STATUS_SYNTAX_TYPE_ERR, LDNS_STATUS_SYNTAX_CLASS_ERR, LDNS_STATUS_SYNTAX_TTL_ERR, + LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL, LDNS_STATUS_SYNTAX_RDATA_ERR, LDNS_STATUS_SYNTAX_DNAME_ERR, LDNS_STATUS_SYNTAX_VERSION_ERR, @@ -82,6 +87,7 @@ enum ldns_enum_status { LDNS_STATUS_SYNTAX_KEYWORD_ERR, LDNS_STATUS_SYNTAX_TTL, LDNS_STATUS_SYNTAX_ORIGIN, + LDNS_STATUS_SYNTAX_INCLUDE, LDNS_STATUS_SYNTAX_EMPTY, LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW, LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR, @@ -106,4 +112,8 @@ extern ldns_lookup_table ldns_error_str[]; */ const char *ldns_get_errorstr_by_id(ldns_status err); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_ERROR_H */ diff --git a/contrib/ldns/ldns/higher.h b/contrib/ldns/ldns/higher.h index c98d013bb7..597e1343a9 100644 --- a/contrib/ldns/ldns/higher.h +++ b/contrib/ldns/ldns/higher.h @@ -22,6 +22,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** * Ask the resolver about name * and return all address records @@ -102,4 +106,8 @@ bool ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t); */ void ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_HIGHER_H */ diff --git a/contrib/ldns/ldns/host2str.h b/contrib/ldns/ldns/host2str.h index 727ab05e91..07180bbd28 100644 --- a/contrib/ldns/ldns/host2str.h +++ b/contrib/ldns/ldns/host2str.h @@ -30,6 +30,10 @@ #include "ldns/util.h" +#ifdef __cplusplus +extern "C" { +#endif + #define LDNS_APL_IP4 1 #define LDNS_APL_IP6 2 #define LDNS_APL_MASK 0x7f @@ -150,6 +154,14 @@ ldns_status ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf); */ ldns_status ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf); +/** + * Converts an LDNS_RDF_TYPE_B32_EXT rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf); + /** * Converts an LDNS_RDF_TYPE_HEX rdata element to string format and adds it to the output buffer * \param[in] *rdf The rdata to convert @@ -255,6 +267,14 @@ ldns_status ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf */ ldns_status ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf); +/** + * Converts an LDNS_RDF_TYPE_ATMA rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf); + /** * Converts an LDNS_RDF_TYPE_WKS rdata element to string format and adds it to the output buffer * \param[in] *rdf The rdata to convert @@ -350,6 +370,15 @@ ldns_status ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr); */ ldns_status ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt); +/** + * Converts an LDNS_RDF_TYPE_NSEC3_SALT rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf); + + /** * Converts the data in the DNS packet to presentation * format (as char *) and appends it to the given buffer @@ -361,15 +390,37 @@ ldns_status ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt); ldns_status ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k); /** - * Converts the data in the int16 typed rdata field to presentation - * format (as char *) and appends it to the given buffer - * - * \param[in] output pointer to the buffer to append the data to - * \param[in] rdf the pointer to the rdafa field containing the data - * \return status + * Converts an LDNS_RDF_TYPE_INT8 rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_INT16 rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure */ ldns_status ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf); +/** + * Converts an LDNS_RDF_TYPE_INT32 rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_TIME rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf); + /** * Converts the data in the rdata field to presentation format and * returns that as a char *. @@ -508,5 +559,8 @@ void ldns_zone_print(FILE *output, const ldns_zone *z); */ ldns_status ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname); +#ifdef __cplusplus +} +#endif #endif /* LDNS_HOST2STR_H */ diff --git a/contrib/ldns/ldns/host2wire.h b/contrib/ldns/ldns/host2wire.h index 51011118a4..5eafe9ddc4 100644 --- a/contrib/ldns/ldns/host2wire.h +++ b/contrib/ldns/ldns/host2wire.h @@ -27,6 +27,10 @@ #include "ldns/util.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Copies the dname data to the buffer in wire format * \param[out] *buffer buffer to append the result to @@ -153,4 +157,8 @@ ldns_status ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int, size_t *size); */ ldns_status ldns_pkt2wire(uint8_t **dest, const ldns_pkt *p, size_t *size); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_HOST2WIRE_H */ diff --git a/contrib/ldns/ldns/keys.h b/contrib/ldns/ldns/keys.h index a84f503404..e0f568d8f8 100644 --- a/contrib/ldns/ldns/keys.h +++ b/contrib/ldns/ldns/keys.h @@ -28,6 +28,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + extern ldns_lookup_table ldns_signing_algorithms[]; #define LDNS_KEY_ZONE_KEY 0x0100 /* rfc 4034 */ @@ -48,7 +52,13 @@ enum ldns_enum_algorithm LDNS_RSASHA1_NSEC3 = 7, LDNS_RSASHA256 = 8, /* RFC 5702 */ LDNS_RSASHA512 = 10, /* RFC 5702 */ - LDNS_GOST = 249, /* not official */ + LDNS_ECC_GOST = 12, /* RFC 5933 */ +#ifdef 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_INDIRECT = 252, LDNS_PRIVATEDNS = 253, LDNS_PRIVATEOID = 254 @@ -62,7 +72,12 @@ enum ldns_enum_hash { LDNS_SHA1 = 1, /* RFC 4034 */ LDNS_SHA256 = 2, /* RFC 4509 */ - LDNS_HASH_GOST94 = 203 /* not official */ + LDNS_HASH_GOST = 3 /* RFC 5933 */ +#ifdef 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_SHA384 = 4 /* draft-hoffman-dnssec-ecdsa EXPERIMENTAL */ +#endif }; typedef enum ldns_enum_hash ldns_hash; @@ -78,7 +93,13 @@ enum ldns_enum_signing_algorithm LDNS_SIGN_RSASHA256 = LDNS_RSASHA256, LDNS_SIGN_RSASHA512 = LDNS_RSASHA512, LDNS_SIGN_DSA_NSEC3 = LDNS_DSA_NSEC3, - LDNS_SIGN_GOST = LDNS_GOST, + LDNS_SIGN_ECC_GOST = LDNS_ECC_GOST, +#ifdef 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_SIGN_ECDSAP256SHA256 = LDNS_ECDSAP256SHA256, + LDNS_SIGN_ECDSAP384SHA384 = LDNS_ECDSAP384SHA384, +#endif LDNS_SIGN_HMACMD5 = 157, /* not official! This type is for TSIG, not DNSSEC */ LDNS_SIGN_HMACSHA1 = 158, /* not official! This type is for TSIG, not DNSSEC */ LDNS_SIGN_HMACSHA256 = 159 /* ditto */ @@ -307,6 +328,9 @@ void ldns_key_set_dsa_key(ldns_key *k, DSA *d); * \return the gost id for EVP_CTX creation. */ int ldns_key_EVP_load_gost_id(void); + +/** Release the engine reference held for the GOST engine. */ +void ldns_key_EVP_unload_gost(void); #endif /* HAVE_SSL */ /** @@ -576,4 +600,15 @@ char *ldns_key_get_file_base_name(ldns_key *key); */ int ldns_key_algo_supported(int algo); +/** + * Get signing algorithm by name. Comparison is case insensitive. + * \param[in] name string with the name. + * \returns 0 on parse failure or the algorithm number. + */ +ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name); + +#ifdef __cplusplus +} +#endif + #endif /* LDNS_KEYS_H */ diff --git a/contrib/ldns/ldns/ldns.h b/contrib/ldns/ldns/ldns.h deleted file mode 100644 index b403392fc3..0000000000 --- a/contrib/ldns/ldns/ldns.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * dns.h -- defines for the Domain Name System - * - * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. - * - * See LICENSE for the license. - * - * This library was created by: - * Jelte Jansen, Erik Rozendaal and Miek Gieben - * - * A bunch of defines that are used in the DNS. - */ - - -/** -\mainpage LDNS Documentation - -\section introduction Introduction - -The goal of ldns is to simplify DNS programming, it supports recent RFCs -like the DNSSEC documents, and allow developers to easily create software -conforming to current RFCs, and experimental software for current Internet -drafts. A secondary benefit of using ldns is speed, because ldns is written -in C, and although it is not optimized for performance, it should be a lot -faster than Perl. - -The first main tool to use ldns is Drill, from which part of the library was -derived. From version 1.0.0 on, drill is included in the ldns release -and will not be distributed seperately anymore. The library also includes some -other examples and tools to show how it can be used. These can be found in the -examples/ directory in the tarball. - -ldns depends on OpenSSL for it's cryptographic functions. -Feature list - - - Transparent IPv4 and IPv6 support (overridable if necessary), - - TSIG support, - - DNSSEC support; signing and verification, - - small size, - - online documentation as well as manual pages. - -If you want to send us patches please use the code from subversion (trunk). - -\section using_ldns Using ldns - -Almost all interaction between an application and ldns goes through the ldns -data structures (\ref ldns_rr, \ref ldns_pkt, etc.). These are input or -output to the functions of ldns. For example, \ref ldns_zone_new_frm_fp -reads a zone from a \c FILE pointer, and returns an \ref ldns_zone -structure. - - -Let's use Drill as an example. Drill is a tool much like dig, whose most -basic function is to send 1 query to a nameserver and print the response. - -To be able to do this, drill uses the resolver module of ldns, which acts as -a stub resolver. The resolver module uses the net module to actually send -the query that drill requested. It then uses the wire2host module to -translate the response and place it in ldns' internal structures. These are -passed back to drill, which then uses the host2str module to print the -response in presentation format. - -\section gettingstarted Getting Started - -See the \ref design page for a very high level description of the design -choices made for ldns. - -For an overview of the functions and types ldns provides, you can check out -the \ref ldns ldns header file descriptions. - -If you want to see some libdns action, you can read our tutorials: - - \ref tutorial1_mx - - \ref tutorial2_zone - - \ref tutorial3_signzone - -Or you can just use the menu above to browse through the API docs. - -
-\image html LogoInGradientBar2-y100.png -
-*/ - -/** - * \file ldns.h - * - * Including this file will include all ldns files, and define some lookup tables. - */ - -#ifndef LDNS_DNS_H -#define LDNS_DNS_H - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LDNS_IP4ADDRLEN (32/8) -#define LDNS_IP6ADDRLEN (128/8) -#define LDNS_PORT 53 -#define LDNS_ROOT_LABEL_STR "." -#define LDNS_DEFAULT_TTL 3600 - -/* lookup tables for standard DNS stuff */ - -/** Taken from RFC 2538, section 2.1. */ -extern ldns_lookup_table ldns_certificate_types[]; -/** Taken from RFC 2535, section 7. */ -extern ldns_lookup_table ldns_algorithms[]; -/** Taken from RFC 2538. */ -extern ldns_lookup_table ldns_cert_algorithms[]; -/** rr types */ -extern ldns_lookup_table ldns_rr_classes[]; -/** Response codes */ -extern ldns_lookup_table ldns_rcodes[]; -/** Operation codes */ -extern ldns_lookup_table ldns_opcodes[]; -/** EDNS flags */ -extern ldns_lookup_table ldns_edns_flags[]; - -#endif /* LDNS_DNS_H */ diff --git a/contrib/ldns/ldns/net.h.in b/contrib/ldns/ldns/net.h.in deleted file mode 100644 index d4beb7d992..0000000000 --- a/contrib/ldns/ldns/net.h.in +++ /dev/null @@ -1,200 +0,0 @@ -/* - * net.h - * - * DNS Resolver definitions - * - * a Net::DNS like library for C - * - * (c) NLnet Labs, 2005-2006 - * - * See the file LICENSE for the license - */ - -#ifndef LDNS_NET_H -#define LDNS_NET_H - -#include -@include_sys_socket_h@ - -#define LDNS_DEFAULT_TIMEOUT_SEC 2 -#define LDNS_DEFAULT_TIMEOUT_USEC 0 - -/** - * \file - * - * Contains functions to send and receive packets over a network. - */ - -/** - * Sends a buffer to an ip using udp and return the respons as a ldns_pkt - * \param[in] qbin the ldns_buffer to be send - * \param[in] to the ip addr to send to - * \param[in] tolen length of the ip addr - * \param[in] timeout the timeout value for the network - * \param[out] answersize size of the packet - * \param[out] result packet with the answer - * \return status - */ -ldns_status ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize); - -/** - * Send an udp query and don't wait for an answer but return - * the socket - * \param[in] qbin the ldns_buffer to be send - * \param[in] to the ip addr to send to - * \param[in] tolen length of the ip addr - * \param[in] timeout *unused*, was the timeout value for the network - * \return the socket used - */ - -int ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); - -/** - * Send an tcp query and don't wait for an answer but return - * the socket - * \param[in] qbin the ldns_buffer to be send - * \param[in] to the ip addr to send to - * \param[in] tolen length of the ip addr - * \param[in] timeout the timeout value for the connect attempt - * \return the socket used - */ -int ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); - -/** - * Sends a buffer to an ip using tcp and return the respons as a ldns_pkt - * \param[in] qbin the ldns_buffer to be send - * \param[in] qbin the ldns_buffer to be send - * \param[in] to the ip addr to send to - * \param[in] tolen length of the ip addr - * \param[in] timeout the timeout value for the network - * \param[out] answersize size of the packet - * \param[out] result packet with the answer - * \return status - */ -ldns_status ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize); - -/** - * Sends ptk to the nameserver at the resolver object. Returns the data - * as a ldns_pkt - * - * \param[out] pkt packet received from the nameserver - * \param[in] r the resolver to use - * \param[in] query_pkt the query to send - * \return status - */ -ldns_status ldns_send(ldns_pkt **pkt, ldns_resolver *r, const ldns_pkt *query_pkt); - -/** - * Sends and ldns_buffer (presumably containing a packet to the nameserver at the resolver object. Returns the data - * as a ldns_pkt - * - * \param[out] pkt packet received from the nameserver - * \param[in] r the resolver to use - * \param[in] qb the buffer to send - * \param[in] tsig_mac the tsig MAC to authenticate the response with (NULL to do no TSIG authentication) - * \return status - */ -ldns_status ldns_send_buffer(ldns_pkt **pkt, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac); - -/** - * Create a tcp socket to the specified address - * \param[in] to ip and family - * \param[in] tolen length of to - * \param[in] timeout timeout for the connect attempt - * \return a socket descriptor - */ -int ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); - -/** - * Create a udp socket to the specified address - * \param[in] to ip and family - * \param[in] timeout *unused*, was timeout for the socket - * \return a socket descriptor - */ -int ldns_udp_connect(const struct sockaddr_storage *to, struct timeval timeout); - -/** - * send a query via tcp to a server. Don't want for the answer - * - * \param[in] qbin the buffer to send - * \param[in] sockfd the socket to use - * \param[in] to which ip to send it - * \param[in] tolen socketlen - * \return number of bytes sent - */ -ssize_t ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen); - -/** - * send a query via udp to a server. Don;t want for the answer - * - * \param[in] qbin the buffer to send - * \param[in] sockfd the socket to use - * \param[in] to which ip to send it - * \param[in] tolen socketlen - * \return number of bytes sent - */ -ssize_t ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen); - -/** - * Gives back a raw packet from the wire and reads the header data from the given - * socket. Allocates the data (of size size) itself, so don't forget to free - * - * \param[in] sockfd the socket to read from - * \param[out] size the number of bytes that are read - * \param[in] timeout the time allowed between packets. - * \return the data read - */ -uint8_t *ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout); - -/** - * This routine may block. Use ldns_tcp_read_wire_timeout, it checks timeouts. - * Gives back a raw packet from the wire and reads the header data from the given - * socket. Allocates the data (of size size) itself, so don't forget to free - * - * \param[in] sockfd the socket to read from - * \param[out] size the number of bytes that are read - * \return the data read - */ -uint8_t *ldns_tcp_read_wire(int sockfd, size_t *size); - -/** - * Gives back a raw packet from the wire and reads the header data from the given - * socket. Allocates the data (of size size) itself, so don't forget to free - * - * \param[in] sockfd the socket to read from - * \param[in] fr the address of the client (if applicable) - * \param[in] *frlen the lenght of the client's addr (if applicable) - * \param[out] size the number of bytes that are read - * \return the data read - */ -uint8_t *ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *fr, socklen_t *frlen); - -/** - * returns the native sockaddr representation from the rdf. - * \param[in] rd the ldns_rdf to operate on - * \param[in] port what port to use. 0 means; use default (53) - * \param[out] size what is the size of the sockaddr_storage - * \return struct sockaddr* the address in the format so other - * functions can use it (sendto) - */ -struct sockaddr_storage * ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, uint16_t port, size_t *size); - -/** - * returns an rdf with the sockaddr info. works for ip4 and ip6 - * \param[in] sock the struct sockaddr_storage to convert - * \param[in] port what port was used. When NULL this is not set - * \return ldns_rdf* wth the address - */ -ldns_rdf * ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port); - -/** - * Prepares the resolver for an axfr query - * The query is sent and the answers can be read with ldns_axfr_next - * \param[in] resolver the resolver to use - * \param[in] domain the domain to exfr - * \param[in] c the class to use - * \return ldns_status the status of the transfer - */ -ldns_status ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class c); - -#endif /* LDNS_NET_H */ diff --git a/contrib/ldns/ldns/packet.h b/contrib/ldns/ldns/packet.h index 45f80b8b8c..1a927d2b48 100644 --- a/contrib/ldns/ldns/packet.h +++ b/contrib/ldns/ldns/packet.h @@ -37,6 +37,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* opcodes for pkt's */ enum ldns_enum_pkt_opcode { LDNS_PACKET_QUERY = 0, @@ -840,8 +844,12 @@ bool ldns_pkt_safe_push_rr_list(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr_lis /** * check if a packet is empty * \param[in] p packet - * \return true: empty, false: empty + * \return true: empty, false: not empty */ bool ldns_pkt_empty(ldns_pkt *p); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_PACKET_H */ diff --git a/contrib/ldns/ldns/parse.h b/contrib/ldns/ldns/parse.h index 5d3dfd42bc..0e9034c341 100644 --- a/contrib/ldns/ldns/parse.h +++ b/contrib/ldns/ldns/parse.h @@ -13,6 +13,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define LDNS_PARSE_SKIP_SPACE "\f\n\r\v" #define LDNS_PARSE_NORMAL " \f\n\r\t\v" #define LDNS_PARSE_NO_NL " \t" @@ -156,4 +160,8 @@ void ldns_fskipcs(FILE *fp, const char *s); */ void ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_PARSE_H */ diff --git a/contrib/ldns/ldns/rbtree.h b/contrib/ldns/ldns/rbtree.h index ac20dde17e..98bd880329 100644 --- a/contrib/ldns/ldns/rbtree.h +++ b/contrib/ldns/ldns/rbtree.h @@ -2,24 +2,24 @@ * rbtree.h -- generic red-black tree * * Copyright (c) 2001-2008, NLnet Labs. All rights reserved. - * + * * This software is open source. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * 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. - * + * * Neither the name of the NLNET LABS nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -43,10 +43,15 @@ #ifndef LDNS_RBTREE_H_ #define LDNS_RBTREE_H_ +#ifdef __cplusplus +extern "C" { +#endif + /** * This structure must be the first member of the data structure in * the rbtree. This allows easy casting between an rbnode_t and the * user data (poor man's inheritance). + * Or you can use the data pointer member to get to your data item. */ typedef struct ldns_rbnode_t ldns_rbnode_t; /** @@ -82,15 +87,15 @@ struct ldns_rbtree_t { /** The number of the nodes in the tree */ size_t count; - /** - * Key compare function. <0,0,>0 like strcmp. - * Return 0 on two NULL ptrs. + /** + * Key compare function. <0,0,>0 like strcmp. + * Return 0 on two NULL ptrs. */ int (*cmp) (const void *, const void *); }; -/** - * Create new tree (malloced) with given key compare function. +/** + * Create new tree (malloced) with given key compare function. * @param cmpf: compare function (like strcmp) takes pointers to two keys. * @return: new tree, empty. */ @@ -102,18 +107,18 @@ ldns_rbtree_t *ldns_rbtree_create(int (*cmpf)(const void *, const void *)); */ void ldns_rbtree_free(ldns_rbtree_t *rbtree); -/** - * Init a new tree (malloced by caller) with given key compare function. +/** + * Init a new tree (malloced by caller) with given key compare function. * @param rbtree: uninitialised memory for new tree, returned empty. * @param cmpf: compare function (like strcmp) takes pointers to two keys. */ void ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *)); -/** - * Insert data into the tree. +/** + * Insert data into the tree. * @param rbtree: tree to insert to. - * @param data: element to insert. - * @return: data ptr or NULL if key already present. + * @param data: element to insert. + * @return: data ptr or NULL if key already present. */ ldns_rbnode_t *ldns_rbtree_insert(ldns_rbtree_t *rbtree, ldns_rbnode_t *data); @@ -129,8 +134,8 @@ void ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree); * Delete element from tree. * @param rbtree: tree to delete from. * @param key: key of item to delete. - * @return: node that is now unlinked from the tree. User to delete it. - * returns 0 if node not present + * @return: node that is now unlinked from the tree. User to delete it. + * returns 0 if node not present */ ldns_rbnode_t *ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key); @@ -149,9 +154,9 @@ ldns_rbnode_t *ldns_rbtree_search(ldns_rbtree_t *rbtree, const void *key); * @param result: set to the exact node if present, otherwise to element that * precedes the position of key in the tree. NULL if no smaller element. * @return: true if exact match in result. Else result points to <= element, - * or NULL if key is smaller than the smallest key. + * or NULL if key is smaller than the smallest key. */ -int ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, +int ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, ldns_rbnode_t **result); /** @@ -197,7 +202,7 @@ void ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2); /** * Call with node=variable of struct* with rbnode_t as first element. - * with type is the type of a pointer to that struct. + * with type is the type of a pointer to that struct. */ #define LDNS_RBTREE_FOR(node, type, rbtree) \ for(node=(type)ldns_rbtree_first(rbtree); \ @@ -215,7 +220,11 @@ void ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2); * The function must not alter the rbtree. * @param arg: user argument. */ -void ldns_traverse_postorder(ldns_rbtree_t* tree, +void ldns_traverse_postorder(ldns_rbtree_t* tree, void (*func)(ldns_rbnode_t*, void*), void* arg); +#ifdef __cplusplus +} +#endif + #endif /* UTIL_RBTREE_H_ */ diff --git a/contrib/ldns/ldns/rdata.h b/contrib/ldns/ldns/rdata.h index dc90270a18..2d5af88da4 100644 --- a/contrib/ldns/ldns/rdata.h +++ b/contrib/ldns/ldns/rdata.h @@ -24,6 +24,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define LDNS_MAX_RDFLEN 8192 #define LDNS_RDF_SIZE_BYTE 1 @@ -369,4 +373,8 @@ ldns_rdf *ldns_rdf_clone(const ldns_rdf *rd); */ int ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_RDATA_H */ diff --git a/contrib/ldns/ldns/resolver.h b/contrib/ldns/ldns/resolver.h index 80b853e1c3..f887aaf676 100644 --- a/contrib/ldns/ldns/resolver.h +++ b/contrib/ldns/ldns/resolver.h @@ -14,7 +14,7 @@ * \file * * Defines the ldns_resolver structure, a stub resolver that can send queries and parse answers. - * + * */ #ifndef LDNS_RESOLVER_H @@ -28,12 +28,16 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** Default location of the resolv.conf file */ #define LDNS_RESOLV_CONF "/etc/resolv.conf" /** Default location of the hosts file */ #define LDNS_RESOLV_HOSTS "/etc/hosts" -#define LDNS_RESOLV_KEYWORD -1 +#define LDNS_RESOLV_KEYWORD -1 #define LDNS_RESOLV_DEFDOMAIN 0 #define LDNS_RESOLV_NAMESERVER 1 #define LDNS_RESOLV_SEARCH 2 @@ -58,7 +62,7 @@ struct ldns_struct_resolver uint16_t _port; /** Array of nameservers to query (IP addresses or dnames) */ - ldns_rdf **_nameservers; + ldns_rdf **_nameservers; /** Number of nameservers in \c _nameservers */ size_t _nameserver_count; /* how many do we have */ @@ -70,9 +74,9 @@ struct ldns_struct_resolver /** Print debug information */ bool _debug; - + /** Default domain to add to non fully qualified domain names */ - ldns_rdf *_domain; + ldns_rdf *_domain; /** Searchlist array, add the names in this array if a query cannot be found */ ldns_rdf **_searchlist; @@ -124,7 +128,7 @@ struct ldns_struct_resolver uint16_t _axfr_i; /* EDNS0 available buffer size */ uint16_t _edns_udp_size; - + /* Optional tsig key for signing queries, outgoing messages are signed if and only if both are set */ @@ -143,7 +147,7 @@ typedef struct ldns_struct_resolver ldns_resolver; /** * Get the port the resolver should use * \param[in] r the resolver - * \return the port number + * \return the port number */ uint16_t ldns_resolver_port(const ldns_resolver *r); @@ -207,6 +211,18 @@ bool ldns_resolver_usevc(const ldns_resolver *r); * \return true: yes, fail, false: no, try the others */ bool ldns_resolver_fail(const ldns_resolver *r); +/** + * Does the resolver apply default domain name + * \param[in] r the resolver + * \return true: yes, false: no + */ +bool ldns_resolver_defnames(const ldns_resolver *r); +/** + * Does the resolver apply search list + * \param[in] r the resolver + * \return true: yes, false: no + */ +bool ldns_resolver_dnsrch(const ldns_resolver *r); /** * Does the resolver do DNSSEC * \param[in] r the resolver @@ -214,7 +230,7 @@ bool ldns_resolver_fail(const ldns_resolver *r); */ bool ldns_resolver_dnssec(const ldns_resolver *r); /** - * Does the resolver set the CD bit + * Does the resolver set the CD bit * \param[in] r the resolver * \return true: yes, false: no */ @@ -362,7 +378,7 @@ void ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c); void ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **rd); /** - * Set the resolver's default domain. This gets appended when no + * Set the resolver's default domain. This gets appended when no * absolute name is given * \param[in] r the resolver * \param[in] rd the name to append @@ -528,7 +544,7 @@ void ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value void ldns_resolver_set_random(ldns_resolver *r, bool b); /** - * push a new nameserver to the resolver. It must be an IP + * Push a new nameserver to the resolver. It must be an IP * address v4 or v6. * \param[in] r the resolver * \param[in] n the ip address @@ -537,16 +553,16 @@ void ldns_resolver_set_random(ldns_resolver *r, bool b); ldns_status ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n); /** - * push a new nameserver to the resolver. It must be an + * Push a new nameserver to the resolver. It must be an * A or AAAA RR record type * \param[in] r the resolver - * \param[in] rr the resource record + * \param[in] rr the resource record * \return ldns_status a status */ ldns_status ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr); /** - * push a new nameserver rr_list to the resolver. + * Push a new nameserver rr_list to the resolver. * \param[in] r the resolver * \param[in] rrlist the rr_list to push * \return ldns_status a status @@ -579,7 +595,7 @@ ldns_pkt* ldns_resolver_search(const ldns_resolver *r, const ldns_rdf *rdf, ldns ldns_status ldns_resolver_prepare_query_pkt(ldns_pkt **q, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t f); /** - * Send the query for name as-is + * Send the query for name as-is * \param[out] **answer a pointer to a ldns_pkt pointer (initialized by this function) * \param[in] *r operate using this resolver * \param[in] *name query for this name @@ -611,8 +627,8 @@ ldns_status ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, ldns_pkt ldns_pkt* ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags); -/** - * Create a new resolver structure +/** + * Create a new resolver structure * \return ldns_resolver* pointer to new strcture */ ldns_resolver* ldns_resolver_new(void); @@ -637,44 +653,46 @@ ldns_status ldns_resolver_new_frm_fp(ldns_resolver **r, FILE *fp); ldns_status ldns_resolver_new_frm_fp_l(ldns_resolver **r, FILE *fp, int *line_nr); /** - * configure a resolver by means of a resolv.conf file + * Configure a resolver by means of a resolv.conf file * The file may be NULL in which case there will be * looked the RESOLV_CONF (defaults to /etc/resolv.conf * \param[out] r the new resolver * \param[in] filename the filename to use * \return LDNS_STATUS_OK or the error - */ + */ ldns_status ldns_resolver_new_frm_file(ldns_resolver **r, const char *filename); -/** +/** * Frees the allocated space for this resolver. Only frees the resolver pionter! You should probably be using _deep_free. - * \param res resolver to free - */ + * \param res resolver to free + */ void ldns_resolver_free(ldns_resolver *res); -/** +/** * Frees the allocated space for this resolver and all it's data - * \param res resolver to free - */ + * \param res resolver to free + */ void ldns_resolver_deep_free(ldns_resolver *res); /** - * get the next stream of RRs in a AXFR + * Get the next stream of RRs in a AXFR * \param[in] resolver the resolver to use. First ldns_axfr_start() must be * called * \return ldns_rr the next RR from the AXFR stream + * After you get this returned RR (not NULL: on error), then check if + * ldns_axfr_complete() is true to see if the zone transfer has completed. */ ldns_rr* ldns_axfr_next(ldns_resolver *resolver); /** - * returns true if the axfr transfer has completed (i.e. 2 SOA RRs and no errors were encountered + * Returns true if the axfr transfer has completed (i.e. 2 SOA RRs and no errors were encountered * \param[in] resolver the resolver that is used * \return bool true if axfr transfer was completed without error */ bool ldns_axfr_complete(const ldns_resolver *resolver); /** - * returns a pointer to the last ldns_pkt that was sent by the server in the AXFR transfer + * Returns a pointer to the last ldns_pkt that was sent by the server in the AXFR transfer * uasable for instance to get the error code on failure * \param[in] res the resolver that was used in the axfr transfer * \return ldns_pkt the last packet sent @@ -682,12 +700,12 @@ bool ldns_axfr_complete(const ldns_resolver *resolver); ldns_pkt *ldns_axfr_last_pkt(const ldns_resolver *res); /** - * randomize the nameserver list in the resolver + * Randomize the nameserver list in the resolver * \param[in] r the resolver */ void ldns_resolver_nameservers_randomize(ldns_resolver *r); -/** +/** * Returns true if at least one of the provided keys is a trust anchor * \param[in] r the current resolver * \param[in] keys the keyset to check @@ -696,4 +714,8 @@ void ldns_resolver_nameservers_randomize(ldns_resolver *r); */ bool ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_RESOLVER_H */ diff --git a/contrib/ldns/ldns/rr.h b/contrib/ldns/ldns/rr.h index f9ae0c18fc..86e31de1f2 100644 --- a/contrib/ldns/ldns/rr.h +++ b/contrib/ldns/ldns/rr.h @@ -23,6 +23,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** Maximum length of a dname label */ #define LDNS_MAX_LABELLEN 63 /** Maximum length of a complete dname */ @@ -33,7 +37,7 @@ #define LDNS_RR_OVERHEAD 10 /* The first fields are 'common' and can be referenced instantly */ -#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 51 +#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 52 @@ -174,6 +178,9 @@ enum ldns_enum_rr_type LDNS_RR_TYPE_NSEC3 = 50, LDNS_RR_TYPE_NSEC3PARAMS = 51, + /** draft-ietf-dnsop-trust-history */ + LDNS_RR_TYPE_TALINK = 58, + LDNS_RR_TYPE_SPF = 99, LDNS_RR_TYPE_UINFO = 100, @@ -871,4 +878,8 @@ ldns_rr_list_type(const ldns_rr_list *rr_list); ldns_rdf * ldns_rr_list_owner(const ldns_rr_list *rr_list); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_RR_H */ diff --git a/contrib/ldns/ldns/rr_functions.h b/contrib/ldns/ldns/rr_functions.h index 617e9429ae..635a1256f3 100644 --- a/contrib/ldns/ldns/rr_functions.h +++ b/contrib/ldns/ldns/rr_functions.h @@ -13,6 +13,10 @@ #ifndef LDNS_RR_FUNCTIONS_H #define LDNS_RR_FUNCTIONS_H +#ifdef __cplusplus +extern "C" { +#endif + /** * \file * @@ -248,4 +252,8 @@ size_t ldns_rr_dnskey_key_size_raw(const unsigned char *keydata, */ size_t ldns_rr_dnskey_key_size(const ldns_rr *key); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_RR_FUNCTIONS_H */ diff --git a/contrib/ldns/ldns/sha1.h b/contrib/ldns/ldns/sha1.h index 7ff62d26c7..d5b1082e67 100644 --- a/contrib/ldns/ldns/sha1.h +++ b/contrib/ldns/ldns/sha1.h @@ -1,5 +1,9 @@ #ifndef LDNS_SHA1_H #define LDNS_SHA1_H + +#ifdef __cplusplus +extern "C" { +#endif #define LDNS_SHA1_BLOCK_LENGTH 64 #define LDNS_SHA1_DIGEST_LENGTH 20 @@ -26,4 +30,9 @@ void ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ct * \return the SHA1 digest of the given data */ unsigned char *ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest); + +#ifdef __cplusplus +} +#endif + #endif /* LDNS_SHA1_H */ diff --git a/contrib/ldns/ldns/str2host.h b/contrib/ldns/ldns/str2host.h index cccad01b38..09416cd225 100644 --- a/contrib/ldns/ldns/str2host.h +++ b/contrib/ldns/ldns/str2host.h @@ -19,6 +19,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** * \file * @@ -240,4 +244,8 @@ ldns_status ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str); */ ldns_status ldns_str2rdf_dname(ldns_rdf **rd, const char *str); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_2HOST_H */ diff --git a/contrib/ldns/ldns/tsig.h b/contrib/ldns/ldns/tsig.h index c3a10a6a0f..4ce666a6b9 100644 --- a/contrib/ldns/ldns/tsig.h +++ b/contrib/ldns/ldns/tsig.h @@ -9,6 +9,10 @@ #ifndef LDNS_TSIG_H #define LDNS_TSIG_H +#ifdef __cplusplus +extern "C" { +#endif + /** * \file * @@ -36,11 +40,21 @@ char *ldns_tsig_keydata_clone(ldns_tsig_credentials *); /** * verifies the tsig rr for the given packet and key. * The wire must be given too because tsig does not sign normalized packets. - * + * \param[in] pkt the packet to verify + * \param[in] wire needed to verify the mac + * \param[in] wire_size size of wire + * \param[in] key_name the name of the shared key + * \param[in] key_data the key in base 64 format + * \param[in] mac original mac + * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest + components are used to verify the _mac. If non-zero, only the TSIG timers are used to verify the mac. * \return true if tsig is correct, false if not, or if tsig is not set */ bool ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac); +bool ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac, + int tsig_timers_only); + /** * creates a tsig rr for the given packet and key. * \param[in] pkt the packet to sign @@ -49,8 +63,18 @@ bool ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const * \param[in] fudge seconds of error permitted in time signed * \param[in] algorithm_name the name of the algorithm used * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers) + * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest + components are used to create the query_mac. If non-zero, only the TSIG timers are used to create the query_mac. * \return status (OK if success) */ -ldns_status ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac); +ldns_status ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, + const char *algorithm_name, ldns_rdf *query_mac); + +ldns_status ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, + const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only); + +#ifdef __cplusplus +} +#endif #endif /* LDNS_TSIG_H */ diff --git a/contrib/ldns/ldns/update.h b/contrib/ldns/ldns/update.h index 1d0d8f8ef2..d3459d325e 100644 --- a/contrib/ldns/ldns/update.h +++ b/contrib/ldns/ldns/update.h @@ -20,6 +20,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /** * create an update packet from zone name, class and the rr lists * \param[in] zone_rdf name of the zone @@ -104,4 +108,8 @@ ldns_status ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r, ldns_rr_clas */ ldns_status ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r, ldns_rr_class c, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_UPDATE_H */ diff --git a/contrib/ldns/ldns/util.h.in b/contrib/ldns/ldns/util.h.in deleted file mode 100644 index d63d617f8a..0000000000 --- a/contrib/ldns/ldns/util.h.in +++ /dev/null @@ -1,331 +0,0 @@ -/* - * util.h - * - * helper function header file - * - * a Net::DNS like library for C - * - * (c) NLnet Labs, 2004 - * - * See the file LICENSE for the license - */ - -#ifndef _UTIL_H -#define _UTIL_H - -@include_inttypes_h@ -#include -#include -#include - -#define dprintf(X,Y) fprintf(stderr, (X), (Y)) -/* #define dprintf(X, Y) */ - -#define LDNS_VERSION "@PACKAGE_VERSION@" -#define LDNS_REVISION @PACKAGE_REVISION@ - -/** - * splint static inline workaround - */ -#ifdef S_SPLINT_S -# define INLINE -#else -# ifdef SWIG -# define INLINE static -# else -# define INLINE static inline -# endif -#endif - -/** - * Memory management macros - */ -#define LDNS_MALLOC(type) LDNS_XMALLOC(type, 1) - -#define LDNS_XMALLOC(type, count) ((type *) malloc((count) * sizeof(type))) - -#define LDNS_REALLOC(ptr, type) LDNS_XREALLOC((ptr), type, 1) - -#define LDNS_XREALLOC(ptr, type, count) \ - ((type *) realloc((ptr), (count) * sizeof(type))) - -#define LDNS_FREE(ptr) \ - do { free((ptr)); (ptr) = NULL; } while (0) - -#define LDNS_DEP printf("DEPRECATED FUNCTION!\n"); - -/* - * Copy data allowing for unaligned accesses in network byte order - * (big endian). - */ -INLINE uint16_t -ldns_read_uint16(const void *src) -{ -#ifdef ALLOW_UNALIGNED_ACCESSES - return ntohs(*(uint16_t *) src); -#else - uint8_t *p = (uint8_t *) src; - return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; -#endif -} - -INLINE uint32_t -ldns_read_uint32(const void *src) -{ -#ifdef ALLOW_UNALIGNED_ACCESSES - return ntohl(*(uint32_t *) src); -#else - uint8_t *p = (uint8_t *) src; - return ( ((uint32_t) p[0] << 24) - | ((uint32_t) p[1] << 16) - | ((uint32_t) p[2] << 8) - | (uint32_t) p[3]); -#endif -} - -/* - * Copy data allowing for unaligned accesses in network byte order - * (big endian). - */ -INLINE void -ldns_write_uint16(void *dst, uint16_t data) -{ -#ifdef ALLOW_UNALIGNED_ACCESSES - * (uint16_t *) dst = htons(data); -#else - uint8_t *p = (uint8_t *) dst; - p[0] = (uint8_t) ((data >> 8) & 0xff); - p[1] = (uint8_t) (data & 0xff); -#endif -} - -INLINE void -ldns_write_uint32(void *dst, uint32_t data) -{ -#ifdef ALLOW_UNALIGNED_ACCESSES - * (uint32_t *) dst = htonl(data); -#else - uint8_t *p = (uint8_t *) dst; - p[0] = (uint8_t) ((data >> 24) & 0xff); - p[1] = (uint8_t) ((data >> 16) & 0xff); - p[2] = (uint8_t) ((data >> 8) & 0xff); - p[3] = (uint8_t) (data & 0xff); -#endif -} - -/* warning. */ -INLINE void -ldns_write_uint64_as_uint48(void *dst, uint64_t data) -{ - uint8_t *p = (uint8_t *) dst; - p[0] = (uint8_t) ((data >> 40) & 0xff); - p[1] = (uint8_t) ((data >> 32) & 0xff); - p[2] = (uint8_t) ((data >> 24) & 0xff); - p[3] = (uint8_t) ((data >> 16) & 0xff); - p[4] = (uint8_t) ((data >> 8) & 0xff); - p[5] = (uint8_t) (data & 0xff); -} - - -/** - * Structure to do a Schwartzian-like transformation, for instance when - * sorting. If you need a transformation on the objects that are sorted, - * you can sue this to store the transformed values, so you do not - * need to do the transformation again for each comparison - */ -struct ldns_schwartzian_compare_struct { - void *original_object; - void *transformed_object; -}; - -/** A general purpose lookup table - * - * Lookup tables are arrays of (id, name) pairs, - * So you can for instance lookup the RCODE 3, which is "NXDOMAIN", - * and vice versa. The lookup tables themselves are defined wherever needed, - * for instance in \ref host2str.c - */ -struct ldns_struct_lookup_table { - int id; - const char *name; -}; -typedef struct ldns_struct_lookup_table ldns_lookup_table; - -/** - * Looks up the table entry by name, returns NULL if not found. - * \param[in] table the lookup table to search in - * \param[in] name what to search for - * \return the item found - */ -ldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[], - const char *name); - -/** - * Looks up the table entry by id, returns NULL if not found. - * \param[in] table the lookup table to search in - * \param[in] id what to search for - * \return the item found - */ -ldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id); - -/** - * Returns the value of the specified bit - * The bits are counted from left to right, so bit #0 is the - * left most bit. - * \param[in] bits array holding the bits - * \param[in] index to the wanted bit - * \return - */ -int ldns_get_bit(uint8_t bits[], size_t index); - - -/** - * Returns the value of the specified bit - * The bits are counted from right to left, so bit #0 is the - * right most bit. - * \param[in] bits array holding the bits - * \param[in] index to the wanted bit - * \return 1 or 0 depending no the bit state - */ -int ldns_get_bit_r(uint8_t bits[], size_t index); - -/** - * sets the specified bit in the specified byte to - * 1 if value is true, 0 if false - * The bits are counted from right to left, so bit #0 is the - * right most bit. - * \param[in] byte the bit to set the bit in - * \param[in] bit_nr the bit to set (0 <= n <= 7) - * \param[in] value whether to set the bit to 1 or 0 - * \return 1 or 0 depending no the bit state - */ -void ldns_set_bit(uint8_t *byte, int bit_nr, bool value); - -/** - * Returns the value of a to the power of b - * (or 1 of b < 1) - */ -/*@unused@*/ -INLINE long -ldns_power(long a, long b) { - long result = 1; - while (b > 0) { - if (b & 1) { - result *= a; - if (b == 1) { - return result; - } - } - a *= a; - b /= 2; - } - return result; -} - -/** - * Returns the int value of the given (hex) digit - * \param[in] ch the hex char to convert - * \return the converted decimal value - */ -int ldns_hexdigit_to_int(char ch); - -/** - * Returns the char (hex) representation of the given int - * \param[in] ch the int to convert - * \return the converted hex char - */ -char ldns_int_to_hexdigit(int ch); - -/** - * Converts a hex string to binary data - * - * \param[out] data The binary result is placed here. - * At least strlen(str)/2 bytes should be allocated - * \param[in] str The hex string to convert. - * This string should not contain spaces - * \return The number of bytes of converted data, or -1 if one of the arguments * is NULL, or -2 if the string length is not an even number - */ -int -ldns_hexstring_to_data(uint8_t *data, const char *str); - -/** - * Show the internal library version - * \return a string with the version in it - */ -const char * ldns_version(void); - -/** - * Convert TM to seconds since epoch (midnight, January 1st, 1970). - * Like timegm(3), which is not always available. - * \param[in] tm a struct tm* with the date - * \return the seconds since epoch - */ -time_t mktime_from_utc(const struct tm *tm); - -/** - * Seed the random function. - * If the file descriptor is specified, the random generator is seeded with - * data from that file. If not, /dev/urandom is used. - * - * applications should call this if they need entropy data within ldns - * If openSSL is available, it is automatically seeded from /dev/urandom - * or /dev/random. - * - * If you need more entropy, or have no openssl available, this function - * MUST be called at the start of the program - * - * If openssl *is* available, this function just adds more entropy - * - * \param[in] fd a file providing entropy data for the seed - * \param[in] size the number of bytes to use as entropy data. If this is 0, - * only the minimal amount is taken (usually 4 bytes) - * \return 0 if seeding succeeds, 1 if it fails - */ -int ldns_init_random(FILE *fd, unsigned int size); - - -/** - * Encode data as BubbleBabble - * - * \param[in] data a pointer to data to be encoded - * \param[in] len size the number of bytes of data - * \return a string of BubbleBabble - */ -char *ldns_bubblebabble(uint8_t *data, size_t len); - -#ifndef B32_NTOP -int ldns_b32_ntop(uint8_t const *src, size_t srclength, - char *target, size_t targsize); -int b32_ntop(uint8_t const *src, size_t srclength, - char *target, size_t targsize); -int ldns_b32_ntop_extended_hex(uint8_t const *src, size_t srclength, - char *target, size_t targsize); -int b32_ntop_extended_hex(uint8_t const *src, size_t srclength, - char *target, size_t targsize); -/** - * calculates the size needed to store the result of b32_ntop - */ -/*@unused@*/ -INLINE size_t ldns_b32_ntop_calculate_size(size_t srcsize) -{ - size_t result = ((((srcsize / 5) * 8) - 2) + 2); - return result; -} -#endif /* !B32_NTOP */ -#ifndef B32_PTON -int ldns_b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); -int b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); -int ldns_b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); -int b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); -/** - * calculates the size needed to store the result of b32_pton - */ -/*@unused@*/ -INLINE size_t ldns_b32_pton_calculate_size(size_t srcsize) -{ - size_t result = ((((srcsize) / 8) * 5)); - return result; -} -#endif /* !B32_PTON */ - -#endif /* !_UTIL_H */ diff --git a/contrib/ldns/ldns/wire2host.h b/contrib/ldns/ldns/wire2host.h index 5c4941cc97..53155b3066 100644 --- a/contrib/ldns/ldns/wire2host.h +++ b/contrib/ldns/ldns/wire2host.h @@ -24,6 +24,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* The length of the header */ #define LDNS_HEADER_SIZE 12 @@ -186,4 +190,8 @@ ldns_status ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t * */ ldns_status ldns_wire2rr(ldns_rr **rr, const uint8_t *wire, size_t max, size_t *pos, ldns_pkt_section section); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_WIRE2HOST_H */ diff --git a/contrib/ldns/ldns/zone.h b/contrib/ldns/ldns/zone.h index e8c29c8f38..a683ea87e0 100644 --- a/contrib/ldns/ldns/zone.h +++ b/contrib/ldns/ldns/zone.h @@ -28,6 +28,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** * DNS Zone * @@ -164,4 +168,8 @@ void ldns_zone_deep_free(ldns_zone *zone); */ void ldns_zone_sort(ldns_zone *zone); +#ifdef __cplusplus +} +#endif + #endif /* LDNS_ZONE_H */ diff --git a/contrib/ldns/net.c b/contrib/ldns/net.c index cdc69c5bf5..1b067545a6 100644 --- a/contrib/ldns/net.c +++ b/contrib/ldns/net.c @@ -44,7 +44,6 @@ ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt) tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3); } - if (!query_pkt || ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) { result = LDNS_STATUS_ERR; @@ -53,7 +52,7 @@ ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt) } ldns_buffer_free(qb); - + return result; } @@ -97,7 +96,6 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf /* not reachable nameserver! */ continue; } - all_servers_rtt_inf = false; /* maybe verbosity setting? printf("Sending to "); @@ -106,17 +104,21 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf */ ns = ldns_rdf2native_sockaddr_storage(ns_array[i], ldns_resolver_port(r), &ns_len); - - if ((ns->ss_family == AF_INET) && + + if ((ns->ss_family == AF_INET) && (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) { + /* not reachable */ continue; } if ((ns->ss_family == AF_INET6) && (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) { + /* not reachable */ continue; } + all_servers_rtt_inf = false; + gettimeofday(&tv_s, NULL); send_status = LDNS_STATUS_ERR; @@ -210,7 +212,7 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf #else (void)tsig_mac; #endif /* HAVE_SSL */ - + LDNS_FREE(reply_bytes); if (result) { *result = reply; @@ -281,7 +283,7 @@ ldns_sock_wait(int sockfd, struct timeval timeout, int write) } ldns_status -ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, +ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answer_size) { int sockfd; @@ -295,12 +297,20 @@ ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage /* wait for an response*/ if(!ldns_sock_wait(sockfd, timeout, 0)) { +#ifndef USE_WINSOCK close(sockfd); +#else + closesocket(sockfd); +#endif return LDNS_STATUS_NETWORK_ERR; } - + answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL); +#ifndef USE_WINSOCK close(sockfd); +#else + closesocket(sockfd); +#endif if (*answer_size == 0) { /* oops */ @@ -333,7 +343,7 @@ int ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout)) { int sockfd; - + if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) { @@ -347,7 +357,7 @@ ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout) { int sockfd; - + if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { return 0; @@ -381,7 +391,11 @@ ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, socklen_t len = (socklen_t)sizeof(error); if(!ldns_sock_wait(sockfd, timeout, 1)) { +#ifndef USE_WINSOCK close(sockfd); +#else + closesocket(sockfd); +#endif return 0; } @@ -435,6 +449,7 @@ ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, /* add length of packet */ sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2); + if(!sendbuf) return 0; ldns_write_uint16(sendbuf, ldns_buffer_position(qbin)); memcpy(sendbuf + 2, ldns_buffer_export(qbin), ldns_buffer_position(qbin)); @@ -472,7 +487,7 @@ uint8_t * ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from, socklen_t *fromlen) { - uint8_t *wire; + uint8_t *wire, *wireout; ssize_t wire_size; wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN); @@ -492,9 +507,10 @@ ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from, } *size = (size_t)wire_size; - wire = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size); + wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size); + if(!wireout) LDNS_FREE(wire); - return wire; + return wireout; } uint8_t * @@ -502,7 +518,7 @@ ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout) { uint8_t *wire; uint16_t wire_size; - ssize_t bytes = 0; + ssize_t bytes = 0, rc = 0; wire = LDNS_XMALLOC(uint8_t, 2); if (!wire) { @@ -516,12 +532,14 @@ ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout) LDNS_FREE(wire); return NULL; } - bytes = recv(sockfd, (void*)wire, 2, 0); - if (bytes == -1 || bytes == 0) { + rc = recv(sockfd, (void*) (wire + bytes), + (size_t) (2 - bytes), 0); + if (rc == -1 || rc == 0) { *size = 0; LDNS_FREE(wire); return NULL; } + bytes += rc; } wire_size = ldns_read_uint16(wire); @@ -536,13 +554,14 @@ ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout) LDNS_FREE(wire); return NULL; } - bytes += recv(sockfd, (void*) (wire + bytes), + rc = recv(sockfd, (void*) (wire + bytes), (size_t) (wire_size - bytes), 0); - if (bytes == -1 || bytes == 0) { + if (rc == -1 || rc == 0) { LDNS_FREE(wire); *size = 0; return NULL; } + bytes += rc; } *size = (size_t) bytes; @@ -554,7 +573,7 @@ ldns_tcp_read_wire(int sockfd, size_t *size) { uint8_t *wire; uint16_t wire_size; - ssize_t bytes = 0; + ssize_t bytes = 0, rc = 0; wire = LDNS_XMALLOC(uint8_t, 2); if (!wire) { @@ -563,12 +582,14 @@ ldns_tcp_read_wire(int sockfd, size_t *size) } while (bytes < 2) { - bytes = recv(sockfd, (void*)wire, 2, 0); - if (bytes == -1 || bytes == 0) { + rc = recv(sockfd, (void*) (wire + bytes), + (size_t) (2 - bytes), 0); + if (rc == -1 || rc == 0) { *size = 0; LDNS_FREE(wire); return NULL; } + bytes += rc; } wire_size = ldns_read_uint16(wire); @@ -578,13 +599,14 @@ ldns_tcp_read_wire(int sockfd, size_t *size) bytes = 0; while (bytes < (ssize_t) wire_size) { - bytes += recv(sockfd, (void*) (wire + bytes), + rc = recv(sockfd, (void*) (wire + bytes), (size_t) (wire_size - bytes), 0); - if (bytes == -1 || bytes == 0) { + if (rc == -1 || rc == 0) { LDNS_FREE(wire); *size = 0; return NULL; } + bytes += rc; } *size = (size_t) bytes; @@ -608,7 +630,11 @@ ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storag } answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout); +#ifndef USE_WINSOCK close(sockfd); +#else + closesocket(sockfd); +#endif if (*answer_size == 0) { /* oops */ @@ -734,7 +760,7 @@ ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) return LDNS_STATUS_ADDRESS_ERR; } /* For AXFR, we have to make the connection ourselves */ - /* try all nameservers (which usually would mean v4 fallback if + /* try all nameservers (which usually would mean v4 fallback if * @hostname is used */ for (ns_i = 0; ns_i < ldns_resolver_nameserver_count(resolver) && @@ -743,8 +769,8 @@ ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) ns = ldns_rdf2native_sockaddr_storage( resolver->_nameservers[ns_i], ldns_resolver_port(resolver), &ns_len); - - resolver->_socket = ldns_tcp_connect(ns, (socklen_t)ns_len, + + resolver->_socket = ldns_tcp_connect(ns, (socklen_t)ns_len, ldns_resolver_timeout(resolver)); } @@ -761,26 +787,58 @@ ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) ldns_resolver_tsig_keydata(resolver), 300, ldns_resolver_tsig_algorithm(resolver), NULL); if (status != LDNS_STATUS_OK) { + /* RoRi: to prevent problems on subsequent calls to ldns_axfr_start + we have to close the socket here! */ +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + return LDNS_STATUS_CRYPTO_TSIG_ERR; } } #endif /* HAVE_SSL */ - /* Convert the query to a buffer * Is this necessary? + /* Convert the query to a buffer + * Is this necessary? */ query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN); status = ldns_pkt2buffer_wire(query_wire, query); if (status != LDNS_STATUS_OK) { ldns_pkt_free(query); + ldns_buffer_free(query_wire); LDNS_FREE(ns); + + /* RoRi: to prevent problems on subsequent calls to ldns_axfr_start + we have to close the socket here! */ +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + return status; } /* Send the query */ - if (ldns_tcp_send_query(query_wire, resolver->_socket, ns, + if (ldns_tcp_send_query(query_wire, resolver->_socket, ns, (socklen_t)ns_len) == 0) { ldns_pkt_free(query); ldns_buffer_free(query_wire); LDNS_FREE(ns); + + /* RoRi: to prevent problems on subsequent calls to ldns_axfr_start + we have to close the socket here! */ + +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + return LDNS_STATUS_NETWORK_ERR; } diff --git a/contrib/ldns/packet.c b/contrib/ldns/packet.c index 32d5a2a09c..0ac5ca8ba3 100644 --- a/contrib/ldns/packet.c +++ b/contrib/ldns/packet.c @@ -412,9 +412,10 @@ ldns_pkt_empty(ldns_pkt *p) return true; /* NULL is empty? */ } if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) { - return true; - } else return false; + } else { + return true; + } } @@ -454,14 +455,7 @@ ldns_pkt_set_id(ldns_pkt *packet, uint16_t id) void ldns_pkt_set_random_id(ldns_pkt *packet) { - uint16_t rid = 0; -#ifdef HAVE_SSL - if (RAND_bytes((unsigned char*)&rid, 2) != 1) { - rid = (uint16_t) random(); - } -#else - rid = (uint16_t) random(); -#endif + uint16_t rid = ldns_get_random(); ldns_pkt_set_id(packet, rid); } @@ -989,7 +983,7 @@ ldns_pkt_clone(ldns_pkt *pkt) ldns_pkt_set_answerfrom(new_pkt, ldns_pkt_answerfrom(pkt)); ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt)); ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt)); - ldns_pkt_set_tsig(new_pkt, ldns_pkt_tsig(pkt)); + ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt))); ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt)); ldns_pkt_set_edns_extended_rcode(new_pkt, diff --git a/contrib/ldns/parse.c b/contrib/ldns/parse.c index 03b31b0a34..9e119751d4 100644 --- a/contrib/ldns/parse.c +++ b/contrib/ldns/parse.c @@ -1,5 +1,5 @@ /* - * a generic (simple) parser. Use to parse rr's, private key + * a generic (simple) parser. Use to parse rr's, private key * information and /etc/resolv.conf files * * a Net::DNS like library for C @@ -14,22 +14,22 @@ #include ldns_lookup_table ldns_directive_types[] = { - { LDNS_DIR_TTL, "$TTL" }, - { LDNS_DIR_ORIGIN, "$ORIGIN" }, - { LDNS_DIR_INCLUDE, "$INCLUDE" }, + { LDNS_DIR_TTL, "$TTL" }, + { LDNS_DIR_ORIGIN, "$ORIGIN" }, + { LDNS_DIR_INCLUDE, "$INCLUDE" }, { 0, NULL } }; /* add max_limit here? */ ssize_t ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit) -{ +{ return ldns_fget_token_l(f, token, delim, limit, NULL); } ssize_t ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr) -{ +{ int c, prev_c; int p; /* 0 -> no parenthese seen, >0 nr of ( seen */ int com, quoted; @@ -111,12 +111,13 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li continue; } - + if (c == '\n' && p != 0 && t > token) { /* in parentheses */ if (line_nr) { *line_nr = *line_nr + 1; } + *t++ = ' '; prev_c = c; continue; } @@ -170,7 +171,7 @@ ssize_t ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit) { - return ldns_fget_keyword_data_l(f, keyword, k_del, data, d_del, + return ldns_fget_keyword_data_l(f, keyword, k_del, data, d_del, data_limit, NULL); } @@ -183,9 +184,14 @@ ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char * ssize_t i; fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN); - i = 0; + if(!fkeyword) + return -1; i = ldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN); + if(i==0 || i==-1) { + LDNS_FREE(fkeyword); + return -1; + } /* case??? i instead of strlen? */ if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) { @@ -204,7 +210,7 @@ ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char * ssize_t ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) -{ +{ int c, lc; int p; /* 0 -> no parenthese seen, >0 nr of ( seen */ int com, quoted; @@ -227,7 +233,7 @@ ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) quoted = 0; t = token; lc = 0; - if (delim[0] == '"') { + if (del[0] == '"') { quoted = 1; } @@ -253,7 +259,6 @@ ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) if (p < 0) { /* more ) then ( */ *t = '\0'; - lc = c; return 0; } @@ -283,6 +288,7 @@ ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) if (c == '\n' && p != 0) { /* in parentheses */ + *t++ = ' '; lc = c; continue; } @@ -293,10 +299,10 @@ ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) goto tokenread; } } - + *t++ = c; i++; - if (limit > 0 && i >= limit - 1) { + if (limit > 0 && i >= limit) { *t = '\0'; return -1; } @@ -320,9 +326,9 @@ ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) tokenread: ldns_bskipcs(b, delim); *t = '\0'; - + if (p != 0) { - return -1; + return -1; } return (ssize_t)i; } @@ -331,7 +337,7 @@ void ldns_bskipc(ldns_buffer *buffer, char c) { while (c == (char) ldns_buffer_read_u8_at(buffer, ldns_buffer_position(buffer))) { - if (ldns_buffer_available_at(buffer, + if (ldns_buffer_available_at(buffer, buffer->_position + sizeof(char), sizeof(char))) { buffer->_position += sizeof(char); } else { @@ -411,17 +417,24 @@ ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, c ssize_t i; fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN); - i = 0; + if(!fkeyword) + return -1; /* out of memory */ i = ldns_bget_token(b, fkeyword, k_del, data_limit); + if(i==0 || i==-1) { + LDNS_FREE(fkeyword); + return -1; /* nothing read */ + } /* case??? */ if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) { + LDNS_FREE(fkeyword); /* whee, the match! */ /* retrieve it's data */ i = ldns_bget_token(b, data, d_del, 0); return i; } else { + LDNS_FREE(fkeyword); return -1; } } diff --git a/contrib/ldns/rbtree.c b/contrib/ldns/rbtree.c index 465bdc5b1d..9177775b5b 100644 --- a/contrib/ldns/rbtree.c +++ b/contrib/ldns/rbtree.c @@ -546,18 +546,22 @@ ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, ldns_rbnode_ ldns_rbnode_t * ldns_rbtree_first (ldns_rbtree_t *rbtree) { - ldns_rbnode_t *node; + ldns_rbnode_t *node = rbtree->root; - for (node = rbtree->root; node->left != LDNS_RBTREE_NULL; node = node->left); + if (rbtree->root != LDNS_RBTREE_NULL) { + for (node = rbtree->root; node->left != LDNS_RBTREE_NULL; node = node->left); + } return node; } ldns_rbnode_t * ldns_rbtree_last (ldns_rbtree_t *rbtree) { - ldns_rbnode_t *node; + ldns_rbnode_t *node = rbtree->root; - for (node = rbtree->root; node->right != LDNS_RBTREE_NULL; node = node->right); + if (rbtree->root != LDNS_RBTREE_NULL) { + for (node = rbtree->root; node->right != LDNS_RBTREE_NULL; node = node->right); + } return node; } diff --git a/contrib/ldns/rdata.c b/contrib/ldns/rdata.c index 05f9122b73..37e36e6c71 100644 --- a/contrib/ldns/rdata.c +++ b/contrib/ldns/rdata.c @@ -132,34 +132,46 @@ ldns_rdf * ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value) { uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1); + ldns_rdf* rdf; if (!rdf_data) { return NULL; } ldns_write_uint16(rdf_data, value); - return ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data); + rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data); + if(!rdf) + LDNS_FREE(rdf_data); + return rdf; } ldns_rdf * ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value) { uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1); + ldns_rdf* rdf; if (!rdf_data) { return NULL; } ldns_write_uint32(rdf_data, value); - return ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data); + rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data); + if(!rdf) + LDNS_FREE(rdf_data); + return rdf; } ldns_rdf * ldns_native2rdf_int16_data(size_t size, uint8_t *data) { uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2); + ldns_rdf* rdf; if (!rdf_data) { return NULL; } ldns_write_uint16(rdf_data, size); memcpy(rdf_data + 2, data, size); - return ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data); + rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data); + if(!rdf) + LDNS_FREE(rdf_data); + return rdf; } /* note: data must be allocated memory */ @@ -359,7 +371,7 @@ ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr } /* read an entire line in from the file */ - if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1) { + if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) { LDNS_FREE(line); return LDNS_STATUS_SYNTAX_RDATA_ERR; } diff --git a/contrib/ldns/resolver.c b/contrib/ldns/resolver.c index 2b01b4229b..db238c3725 100644 --- a/contrib/ldns/resolver.c +++ b/contrib/ldns/resolver.c @@ -542,19 +542,22 @@ ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d) void ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname) { - r->_tsig_keyname = tsig_keyname; + LDNS_FREE(r->_tsig_keyname); + r->_tsig_keyname = strdup(tsig_keyname); } void ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm) { - r->_tsig_algorithm = tsig_algorithm; + LDNS_FREE(r->_tsig_algorithm); + r->_tsig_algorithm = strdup(tsig_algorithm); } void ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata) { - r->_tsig_keydata = tsig_keydata; + LDNS_FREE(r->_tsig_keydata); + r->_tsig_keydata = strdup(tsig_keydata); } void @@ -594,6 +597,9 @@ ldns_resolver_new(void) ldns_resolver_set_dnssec_cd(r, false); ldns_resolver_set_dnssec_anchors(r, NULL); ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY); + ldns_resolver_set_igntc(r, false); + ldns_resolver_set_recursive(r, false); + ldns_resolver_set_dnsrch(r, true); /* randomize the nameserver to be queried * when there are multiple @@ -605,6 +611,8 @@ ldns_resolver_new(void) r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC; r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC; + /* TODO: fd=0 is actually a valid socket (stdin), + replace with -1 */ r->_socket = 0; r->_axfr_soa_count = 0; r->_axfr_i = 0; @@ -634,8 +642,10 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) #ifdef HAVE_SSL ldns_rr *tmp_rr; #endif - ssize_t gtr; + ssize_t gtr, bgtr; ldns_buffer *b; + int lnr = 0, oldline; + if(!line_nr) line_nr = &lnr; /* do this better * expect = @@ -661,25 +671,36 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) gtr = 1; word[0] = 0; + oldline = *line_nr; + expect = LDNS_RESOLV_KEYWORD; while (gtr > 0) { /* check comments */ if (word[0] == '#') { - /* read the rest of the line, should be 1 word */ - gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); - /* prepare the next string for further parsing */ - gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + word[0]='x'; + if(oldline == *line_nr) { + /* skip until end of line */ + int c; + do { + c = fgetc(fp); + } while(c != EOF && c != '\n'); + if(c=='\n' && line_nr) (*line_nr)++; + } + /* and read next to prepare for further parsing */ + oldline = *line_nr; continue; } + oldline = *line_nr; switch(expect) { case LDNS_RESOLV_KEYWORD: /* keyword */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr != 0) { + if(word[0] == '#') continue; for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) { if (strcasecmp(keyword[i], word) == 0) { /* chosen the keyword and * expect values carefully - */ + */ expect = i; break; } @@ -700,6 +721,10 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) if (gtr == 0) { return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } + if(word[0] == '#') { + expect = LDNS_RESOLV_KEYWORD; + continue; + } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); if (!tmp) { ldns_resolver_deep_free(r); @@ -716,6 +741,15 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) if (gtr == 0) { return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } + if(word[0] == '#') { + expect = LDNS_RESOLV_KEYWORD; + continue; + } + if(strchr(word, '%')) { + /* snip off interface labels, + * fe80::222:19ff:fe31:4222%eth0 */ + strchr(word, '%')[0]=0; + } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word); if (!tmp) { /* try ip4 */ @@ -734,20 +768,37 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) /* search list domain dname */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); b = LDNS_MALLOC(ldns_buffer); - ldns_buffer_new_frm_data(b, word, (size_t) gtr); + if(!b) { + ldns_resolver_deep_free(r); + return LDNS_STATUS_MEM_ERR; + } - gtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr); - while (gtr > 0) { + ldns_buffer_new_frm_data(b, word, (size_t) gtr); + if(ldns_buffer_status(b) != LDNS_STATUS_OK) { + LDNS_FREE(b); + ldns_resolver_deep_free(r); + return LDNS_STATUS_MEM_ERR; + } + bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1); + while (bgtr > 0) { + gtr -= bgtr; + if(word[0] == '#') { + expect = LDNS_RESOLV_KEYWORD; + ldns_buffer_free(b); + continue; + } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); if (!tmp) { ldns_resolver_deep_free(r); + ldns_buffer_free(b); return LDNS_STATUS_SYNTAX_DNAME_ERR; } ldns_resolver_push_searchlist(r, tmp); ldns_rdf_deep_free(tmp); - gtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr); + bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, + (size_t) gtr + 1); } ldns_buffer_free(b); gtr = 1; @@ -767,8 +818,13 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) /* a file containing a DNSSEC trust anchor */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { + ldns_resolver_deep_free(r); return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } + if(word[0] == '#') { + expect = LDNS_RESOLV_KEYWORD; + continue; + } #ifdef HAVE_SSL tmp_rr = ldns_read_anchor_file(word); @@ -784,6 +840,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) *res = r; return LDNS_STATUS_OK; } else { + ldns_resolver_deep_free(r); return LDNS_STATUS_NULL; } } @@ -845,9 +902,15 @@ ldns_resolver_deep_free(ldns_resolver *res) if (ldns_resolver_domain(res)) { ldns_rdf_deep_free(ldns_resolver_domain(res)); } - if (ldns_resolver_tsig_keyname(res)) { + if (res->_tsig_keyname) { LDNS_FREE(res->_tsig_keyname); } + if (res->_tsig_keydata) { + LDNS_FREE(res->_tsig_keydata); + } + if (res->_tsig_algorithm) { + LDNS_FREE(res->_tsig_algorithm); + } if (res->_cur_axfr_pkt) { ldns_pkt_free(res->_cur_axfr_pkt); @@ -864,7 +927,7 @@ ldns_resolver_deep_free(ldns_resolver *res) } ldns_pkt * -ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, +ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags) { @@ -879,7 +942,7 @@ ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, if (ldns_dname_str_absolute(str_dname)) { /* query as-is */ return ldns_resolver_query(r, name, t, c, flags); - } else { + } else if (ldns_resolver_dnsrch(r)) { search_list = ldns_resolver_searchlist(r); for (i = 0; i < ldns_resolver_searchlist_count(r); i++) { new_name = ldns_dname_cat_clone(name, search_list[i]); @@ -887,7 +950,12 @@ ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, p = ldns_resolver_query(r, new_name, t, c, flags); ldns_rdf_free(new_name); if (p) { - return p; + if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) { + return p; + } else { + ldns_pkt_free(p); + p = NULL; + } } } } @@ -895,7 +963,7 @@ ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, } ldns_pkt * -ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, +ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags) { ldns_rdf *newname; @@ -905,7 +973,7 @@ ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, pkt = NULL; if (!ldns_resolver_defnames(r)) { - status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, + status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, t, c, flags); if (status == LDNS_STATUS_OK) { return pkt; @@ -913,7 +981,6 @@ ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, if (pkt) { ldns_pkt_free(pkt); } - fprintf(stderr, "error: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } } @@ -939,7 +1006,8 @@ ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, } return NULL; } - status = ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, t, c, + + (void)ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, t, c, flags); ldns_rdf_free(newname); @@ -961,7 +1029,6 @@ ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, answer_pkt = NULL; } } else { - /* if tc=1 fall back to EDNS and/or TCP */ /* check for tcp first (otherwise we don't care about tc=1) */ if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) { @@ -984,7 +1051,6 @@ ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, } } - if (answer) { *answer = answer_pkt; } @@ -1087,6 +1153,7 @@ ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, #else return LDNS_STATUS_CRYPTO_TSIG_ERR; #endif /* HAVE_SSL */ + status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt); ldns_pkt_free(query_pkt); @@ -1124,7 +1191,11 @@ ldns_axfr_next(ldns_resolver *resolver) if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) { resolver->_axfr_soa_count++; if (resolver->_axfr_soa_count >= 2) { +#ifndef USE_WINSOCK close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif resolver->_socket = 0; ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; @@ -1144,10 +1215,32 @@ ldns_axfr_next(ldns_resolver *resolver) if (status != LDNS_STATUS_OK) { /* TODO: make status return type of this function (...api change) */ fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); + + /* RoRi: we must now also close the socket, otherwise subsequent uses of the + same resolver structure will fail because the link is still open or + in an undefined state */ +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + return NULL; } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); fprintf(stderr, "Error in AXFR: %s\n", rcode->name); + + /* RoRi: we must now also close the socket, otherwise subsequent uses of the + same resolver structure will fail because the link is still open or + in an undefined state */ +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + return NULL; } else { return ldns_axfr_next(resolver); @@ -1174,16 +1267,15 @@ ldns_axfr_last_pkt(const ldns_resolver *res) void ldns_resolver_nameservers_randomize(ldns_resolver *r) { - uint8_t i, j; + uint16_t i, j; ldns_rdf **ns, *tmp; /* should I check for ldns_resolver_random?? */ assert(r != NULL); ns = ldns_resolver_nameservers(r); - for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { - j = random() % ldns_resolver_nameserver_count(r); + j = ldns_get_random() % ldns_resolver_nameserver_count(r); tmp = ns[i]; ns[i] = ns[j]; ns[j] = tmp; diff --git a/contrib/ldns/rr.c b/contrib/ldns/rr.c index a8aad56667..60ce49858c 100644 --- a/contrib/ldns/rr.c +++ b/contrib/ldns/rr.c @@ -120,7 +120,8 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, const char *delimiters; ssize_t c; ldns_rdf *owner_dname; - const char* endptr; + const char* endptr; + int was_unknown_rr_format = 0; /* used for types with unknown number of rdatas */ bool done; @@ -130,12 +131,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, uint16_t r_cnt; uint16_t r_min; uint16_t r_max; - - uint16_t hex_data_size; - char *hex_data_str; - uint16_t cur_hex_data_size; - uint8_t *hex_data; - size_t hex_pos; + size_t pre_data_pos; new = ldns_rr_new(); @@ -150,9 +146,6 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, if (!new || !owner || !ttl || !clas || !rdata || !rr_buf || !rd_buf || !rd || !b64 ) { return LDNS_STATUS_MEM_ERR; } - r_cnt = 0; - ttl_val = 0; - clas_val = 0; ldns_buffer_new_frm_data(rr_buf, (char*)str, strlen(str)); @@ -213,6 +206,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, LDNS_FREE(rdata); LDNS_FREE(rd); LDNS_FREE(rd_buf); + LDNS_FREE(b64); ldns_buffer_free(rr_buf); ldns_rr_free(new); return LDNS_STATUS_SYNTAX_CLASS_ERR; @@ -238,6 +232,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, LDNS_FREE(rdata); LDNS_FREE(rd); LDNS_FREE(rd_buf); + LDNS_FREE(b64); ldns_buffer_free(rr_buf); ldns_rr_free(new); return LDNS_STATUS_SYNTAX_TYPE_ERR; @@ -298,6 +293,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, LDNS_FREE(rdata); LDNS_FREE(rd); LDNS_FREE(rd_buf); + LDNS_FREE(b64); ldns_buffer_free(rr_buf); ldns_rr_free(new); return LDNS_STATUS_SYNTAX_ERR; @@ -314,6 +310,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, LDNS_FREE(rdata); LDNS_FREE(rd); LDNS_FREE(rd_buf); + LDNS_FREE(b64); ldns_buffer_free(rr_buf); ldns_rr_free(new); return LDNS_STATUS_SYNTAX_ERR; @@ -399,6 +396,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, ldns_buffer_skip(rd_buf, 1); } + pre_data_pos = ldns_buffer_position(rd_buf); if ((c = ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN)) != -1) { /* hmmz, rfc3597 specifies that any type can be represented with @@ -408,7 +406,17 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, rd_strlen = strlen(rd); /* unknown RR data */ - if (rd_strlen == 2 && strncmp(rd, "\\#", 2) == 0 && !quoted) { + if (strncmp(rd, "\\#", 2) == 0 && !quoted && (rd_strlen == 2 || rd[2]==' ')) { + uint16_t hex_data_size; + char *hex_data_str; + uint16_t cur_hex_data_size; + + was_unknown_rr_format = 1; + /* go back to before \# and skip it while setting delimiters better */ + ldns_buffer_set_position(rd_buf, pre_data_pos); + delimiters = "\n\t "; + (void)ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN); + /* read rdata octet length */ c = ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN); if (c == -1) { /* something goes very wrong here */ @@ -437,10 +445,10 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, /* correct the rdf type */ /* if *we* know the type, interpret it as wireformat */ if (desc) { - hex_data = LDNS_XMALLOC(uint8_t, hex_data_size + 2); + size_t hex_pos = 0; + uint8_t *hex_data = LDNS_XMALLOC(uint8_t, hex_data_size + 2); ldns_write_uint16(hex_data, hex_data_size); ldns_hexstring_to_data(hex_data + 2, hex_data_str); - hex_pos = 0; (void) ldns_wire2rdf(new, hex_data, hex_data_size+2, &hex_pos); LDNS_FREE(hex_data); @@ -532,7 +540,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, ldns_buffer_free(rr_buf); LDNS_FREE(rdata); - if (!question && desc && ldns_rr_rd_count(new) < r_min) { + if (!question && desc && !was_unknown_rr_format && ldns_rr_rd_count(new) < r_min) { ldns_rr_free(new); return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } @@ -580,13 +588,12 @@ ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf char *line; const char *endptr; /* unused */ ldns_rr *rr; - char *keyword; uint32_t ttl; ldns_rdf *tmp; ldns_status s; ssize_t size; + int offset = 0; - s = LDNS_STATUS_ERR; if (default_ttl) { ttl = *default_ttl; } else { @@ -616,12 +623,16 @@ ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf return LDNS_STATUS_SYNTAX_EMPTY; } - if ((keyword = strstr(line, "$ORIGIN "))) { + if (strncmp(line, "$ORIGIN", 7) == 0 && isspace(line[7])) { if (*origin) { ldns_rdf_deep_free(*origin); *origin = NULL; } - tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, keyword + 8); + offset = 8; + while (isspace(line[offset])) { + offset++; + } + tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, line + offset); if (!tmp) { /* could not parse what next to $ORIGIN */ LDNS_FREE(line); @@ -629,11 +640,17 @@ ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf } *origin = tmp; s = LDNS_STATUS_SYNTAX_ORIGIN; - } else if ((keyword = strstr(line, "$TTL "))) { + } else if (strncmp(line, "$TTL", 4) == 0 && isspace(line[4])) { + offset = 5; + while (isspace(line[offset])) { + offset++; + } if (default_ttl) { - *default_ttl = ldns_str2period(keyword + 5, &endptr); + *default_ttl = ldns_str2period(line + offset, &endptr); } s = LDNS_STATUS_SYNTAX_TTL; + } else if (strncmp(line, "$INCLUDE", 8) == 0) { + s = LDNS_STATUS_SYNTAX_INCLUDE; } else { if (origin && *origin) { s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, *origin, prev); @@ -689,11 +706,9 @@ ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position) { size_t rd_count; ldns_rdf *pop; - ldns_rdf **rdata_fields; rd_count = ldns_rr_rd_count(rr); if (position < rd_count) { - rdata_fields = rr->_rdata_fields; /* dicard the old one */ pop = rr->_rdata_fields[position]; rr->_rdata_fields[position] = (ldns_rdf*)f; @@ -731,6 +746,7 @@ ldns_rr_pop_rdf(ldns_rr *rr) { size_t rd_count; ldns_rdf *pop; + ldns_rdf** newrd; rd_count = ldns_rr_rd_count(rr); @@ -740,9 +756,15 @@ ldns_rr_pop_rdf(ldns_rr *rr) pop = rr->_rdata_fields[rd_count - 1]; - /* shrink the array */ - rr->_rdata_fields = LDNS_XREALLOC( - rr->_rdata_fields, ldns_rdf *, rd_count - 1); + /* try to shrink the array */ + if(rd_count > 1) { + newrd = LDNS_XREALLOC( + rr->_rdata_fields, ldns_rdf *, rd_count - 1); + if(newrd) + rr->_rdata_fields = newrd; + } else { + LDNS_FREE(rr->_rdata_fields); + } ldns_rr_set_rd_count(rr, rd_count - 1); return pop; @@ -878,12 +900,9 @@ bool ldns_rr_list_cat(ldns_rr_list *left, ldns_rr_list *right) { size_t r_rr_count; - size_t l_rr_count; size_t i; - if (left) { - l_rr_count = ldns_rr_list_rr_count(left); - } else { + if (!left) { return false; } @@ -908,8 +927,6 @@ ldns_rr_list_cat_clone(ldns_rr_list *left, ldns_rr_list *right) size_t i; ldns_rr_list *cat; - l_rr_count = 0; - if (left) { l_rr_count = ldns_rr_list_rr_count(left); } else { @@ -1257,6 +1274,7 @@ ldns_rr_clone(const ldns_rr *rr) ldns_rr_set_ttl(new_rr, ldns_rr_ttl(rr)); ldns_rr_set_type(new_rr, ldns_rr_get_type(rr)); ldns_rr_set_class(new_rr, ldns_rr_get_class(rr)); + ldns_rr_set_question(new_rr, ldns_rr_is_question(rr)); for (i = 0; i < ldns_rr_rd_count(rr); i++) { if (ldns_rr_rdf(rr,i)) { @@ -1340,7 +1358,6 @@ qsort_schwartz_rr_compare(const void *a, const void *b) ldns_rr2canonical(canonical_a); sa->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_a)); if (ldns_rr2buffer_wire(sa->transformed_object, canonical_a, LDNS_SECTION_ANY) != LDNS_STATUS_OK) { - fprintf(stderr, "ERR!\n"); ldns_rr_free(canonical_a); return 0; } @@ -1351,7 +1368,6 @@ qsort_schwartz_rr_compare(const void *a, const void *b) ldns_rr2canonical(canonical_b); sb->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_b)); if (ldns_rr2buffer_wire(sb->transformed_object, canonical_b, LDNS_SECTION_ANY) != LDNS_STATUS_OK) { - fprintf(stderr, "ERR!\n"); ldns_rr_free(canonical_b); return 0; } @@ -1801,6 +1817,9 @@ static const ldns_rdf_type type_nsec_wireformat[] = { static const ldns_rdf_type type_dhcid_wireformat[] = { LDNS_RDF_TYPE_B64 }; +static const ldns_rdf_type type_talink_wireformat[] = { + LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME +}; /* nsec3 is some vars, followed by same type of data of nsec */ static const ldns_rdf_type type_nsec3_wireformat[] = { /* LDNS_RDF_TYPE_NSEC3_VARS, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC*/ @@ -1949,7 +1968,7 @@ static ldns_rr_descriptor rdata_field_descriptors[] = { {LDNS_RR_TYPE_NULL, "TYPE55", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE56", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE57", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{LDNS_RR_TYPE_NULL, "TYPE58", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_TALINK, "TALINK", 2, 2, type_talink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 }, {LDNS_RR_TYPE_NULL, "TYPE59", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE60", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE61", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, diff --git a/contrib/ldns/rr_functions.c b/contrib/ldns/rr_functions.c index 3297f7a916..f4c5e4f82f 100644 --- a/contrib/ldns/rr_functions.c +++ b/contrib/ldns/rr_functions.c @@ -312,13 +312,17 @@ ldns_rr_dnskey_key_size_raw(const unsigned char* keydata, } break; #ifdef USE_GOST - case LDNS_SIGN_GOST: + case LDNS_SIGN_ECC_GOST: return 512; - break; +#endif +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + return 256; + case LDNS_SIGN_ECDSAP384SHA384: + return 384; #endif case LDNS_SIGN_HMACMD5: return len; - break; default: return 0; } diff --git a/contrib/ldns/str2host.c b/contrib/ldns/str2host.c index 4ee3e782ae..f73b23d216 100644 --- a/contrib/ldns/str2host.c +++ b/contrib/ldns/str2host.c @@ -258,9 +258,9 @@ parse_escape(uint8_t *s, uint8_t *q) { return 3; } else { s++; - if (*s == '\0') { + if (*s == '\0' || isdigit((int) *s)) { /* apparently the string terminator - * has been escaped... + * or a digit has been escaped... */ return 0; } @@ -280,7 +280,7 @@ ldns_str2rdf_dname(ldns_rdf **d, const char *str) size_t len; int esc; - uint8_t *s,*p,*q, *pq, label_len; + uint8_t *s, *q, *pq, label_len; uint8_t buf[LDNS_MAX_DOMAINLEN + 1]; *d = NULL; @@ -301,15 +301,16 @@ ldns_str2rdf_dname(ldns_rdf **d, const char *str) /* get on with the rest */ - /* s is on the current dot - * p on the previous one - * q builds the dname + /* s is on the current character in the string + * pq points to where the labellength is going to go + * label_len keeps track of the current label's length + * q builds the dname inside the buf array */ len = 0; q = buf+1; pq = buf; label_len = 0; - for (s = p = (uint8_t *) str; *s; s++, q++) { + for (s = (uint8_t *)str; *s; s++, q++) { if (q > buf + LDNS_MAX_DOMAINLEN) { return LDNS_STATUS_DOMAINNAME_OVERFLOW; } @@ -326,7 +327,6 @@ ldns_str2rdf_dname(ldns_rdf **d, const char *str) *pq = label_len; label_len = 0; pq = q; - p = s+1; break; case '\\': /* octet value or literal char */ @@ -349,6 +349,12 @@ ldns_str2rdf_dname(ldns_rdf **d, const char *str) if (q > buf + LDNS_MAX_DOMAINLEN) { return LDNS_STATUS_DOMAINNAME_OVERFLOW; } + if (label_len > LDNS_MAX_LABELLEN) { + return LDNS_STATUS_LABEL_OVERFLOW; + } + if (label_len == 0) { /* label_len 0 but not . at end? */ + return LDNS_STATUS_EMPTY_LABEL; + } len += label_len + 1; *pq = label_len; *q = 0; @@ -390,7 +396,7 @@ ldns_status ldns_str2rdf_str(ldns_rdf **rd, const char *str) { uint8_t *data; - size_t i, str_i; + size_t i, str_i, esc_i; if (strlen(str) > 255) { return LDNS_STATUS_INVALID_STR; @@ -401,7 +407,12 @@ ldns_str2rdf_str(ldns_rdf **rd, const char *str) for (str_i = 0; str_i < strlen(str); str_i++) { if (str[str_i] == '\\') { /* octet value or literal char */ - str_i += (size_t) parse_escape((uint8_t*) &str[str_i], (uint8_t*) &data[i]); + esc_i = (size_t) parse_escape((uint8_t*) &str[str_i], (uint8_t*) &data[i]); + if (esc_i == 0) { + LDNS_FREE(data); + return LDNS_STATUS_SYNTAX_BAD_ESCAPE; + } + str_i += esc_i; } else { data[i] = (uint8_t) str[str_i]; } @@ -600,11 +611,25 @@ ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) uint16_t cur_type; size_t type_count = 0; ldns_rr_type type_list[1024]; + if(!token) return LDNS_STATUS_MEM_ERR; + if(rd == NULL) { + LDNS_FREE(token); + return LDNS_STATUS_NULL; + } str_buf = LDNS_MALLOC(ldns_buffer); + if(!str_buf) { + LDNS_FREE(token); + return LDNS_STATUS_MEM_ERR; + } ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); + if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { + LDNS_FREE(str_buf); + LDNS_FREE(token); + return LDNS_STATUS_MEM_ERR; + } - while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1) { + while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { cur_type = ldns_get_rr_type_by_name(token); type_list[type_count] = cur_type; type_count++; @@ -614,8 +639,7 @@ ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) type_count, LDNS_RR_TYPE_NSEC); - if (token) - LDNS_FREE(token); + LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_OK; } @@ -948,17 +972,28 @@ ldns_str2rdf_wks(ldns_rdf **rd, const char *str) ldns_buffer *str_buf; char *proto_str = NULL; - char *token = LDNS_XMALLOC(char, 50); + char *token; + if(strlen(str) == 0) + token = LDNS_XMALLOC(char, 50); + else token = LDNS_XMALLOC(char, strlen(str)+2); + if(!token) return LDNS_STATUS_MEM_ERR; str_buf = LDNS_MALLOC(ldns_buffer); + if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); + if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { + LDNS_FREE(str_buf); + LDNS_FREE(token); + return LDNS_STATUS_MEM_ERR; + } while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { if (!proto_str) { proto_str = strdup(token); if (!proto_str) { + LDNS_FREE(bitmap); LDNS_FREE(token); - LDNS_FREE(str_buf); + ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } } else { @@ -969,7 +1004,15 @@ ldns_str2rdf_wks(ldns_rdf **rd, const char *str) serv_port = atoi(token); } if (serv_port / 8 >= bm_len) { - bitmap = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); + uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); + if(!b2) { + LDNS_FREE(bitmap); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + free(proto_str); + return LDNS_STATUS_INVALID_STR; + } + bitmap = b2; /* set to zero to be sure */ for (; bm_len <= serv_port / 8; bm_len++) { bitmap[bm_len] = 0; @@ -979,13 +1022,22 @@ ldns_str2rdf_wks(ldns_rdf **rd, const char *str) } } - if (!proto_str) { + if (!proto_str || !bitmap) { + LDNS_FREE(bitmap); LDNS_FREE(token); - LDNS_FREE(str_buf); + ldns_buffer_free(str_buf); + free(proto_str); return LDNS_STATUS_INVALID_STR; } data = LDNS_XMALLOC(uint8_t, bm_len + 1); + if(!data) { + LDNS_FREE(token); + ldns_buffer_free(str_buf); + LDNS_FREE(bitmap); + free(proto_str); + return LDNS_STATUS_INVALID_STR; + } if (proto_str) proto = getprotobyname(proto_str); if (proto) { @@ -1011,6 +1063,8 @@ ldns_str2rdf_wks(ldns_rdf **rd, const char *str) endprotoent(); #endif + if(!*rd) return LDNS_STATUS_MEM_ERR; + return LDNS_STATUS_OK; } @@ -1063,15 +1117,26 @@ ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) char* publickey = NULL; uint8_t *data; ldns_buffer *str_buf; - char *token = LDNS_XMALLOC(char, 256); + char *token; int token_count = 0; int ipseckey_len = 0; ldns_rdf* gateway_rdf = NULL; ldns_rdf* publickey_rdf = NULL; ldns_status status = LDNS_STATUS_OK; + + if(strlen(str) == 0) + token = LDNS_XMALLOC(char, 256); + else token = LDNS_XMALLOC(char, strlen(str)+2); + if(!token) return LDNS_STATUS_MEM_ERR; str_buf = LDNS_MALLOC(ldns_buffer); + if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); + if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { + LDNS_FREE(str_buf); + LDNS_FREE(token); + return LDNS_STATUS_MEM_ERR; + } while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { switch (token_count) { case 0: @@ -1089,7 +1154,7 @@ ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) (token[0] != '.' || token[1] != '\0'))) { LDNS_FREE(gateway); LDNS_FREE(token); - LDNS_FREE(str_buf); + ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } break; @@ -1098,7 +1163,7 @@ ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) break; default: LDNS_FREE(token); - LDNS_FREE(str_buf); + ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; break; } @@ -1111,7 +1176,7 @@ ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) if (publickey) LDNS_FREE(publickey); LDNS_FREE(token); - LDNS_FREE(str_buf); + ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } @@ -1129,7 +1194,7 @@ ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) if (publickey) LDNS_FREE(publickey); LDNS_FREE(token); - LDNS_FREE(str_buf); + ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } @@ -1141,7 +1206,8 @@ ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) if (publickey) LDNS_FREE(publickey); LDNS_FREE(token); - LDNS_FREE(str_buf); + ldns_buffer_free(str_buf); + if (gateway_rdf) ldns_rdf_free(gateway_rdf); return LDNS_STATUS_INVALID_STR; } @@ -1152,6 +1218,17 @@ ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) ipseckey_len = 3 + ldns_rdf_size(publickey_rdf); data = LDNS_XMALLOC(uint8_t, ipseckey_len); + if(!data) { + if (gateway) + LDNS_FREE(gateway); + if (publickey) + LDNS_FREE(publickey); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + if (gateway_rdf) ldns_rdf_free(gateway_rdf); + if (publickey_rdf) ldns_rdf_free(publickey_rdf); + return LDNS_STATUS_MEM_ERR; + } data[0] = precedence; data[1] = gateway_type; @@ -1178,5 +1255,6 @@ ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) ldns_rdf_free(gateway_rdf); ldns_rdf_free(publickey_rdf); LDNS_FREE(data); + if(!*rd) return LDNS_STATUS_MEM_ERR; return LDNS_STATUS_OK; } diff --git a/contrib/ldns/tsig.c b/contrib/ldns/tsig.c index 38a9a0e862..4083960952 100644 --- a/contrib/ldns/tsig.c +++ b/contrib/ldns/tsig.c @@ -1,4 +1,4 @@ -/* +/* * tsig.c * * contains the functions needed for TSIG [RFC2845] @@ -149,7 +149,7 @@ static ldns_status ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, const char *key_data, ldns_rdf *key_name_rdf, ldns_rdf *fudge_rdf, ldns_rdf *algorithm_rdf, ldns_rdf *time_signed_rdf, ldns_rdf *error_rdf, - ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf) + ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf, int tsig_timers_only) { char *wireformat; int wiresize; @@ -166,37 +166,63 @@ ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, * prepare the digestable information */ data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if(!data_buffer) { + return LDNS_STATUS_MEM_ERR; + } /* if orig_mac is not NULL, add it too */ if (orig_mac_rdf) { (void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf); } ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size); - (void)ldns_rdf2buffer_wire(data_buffer, key_name_rdf); - ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY); - ldns_buffer_write_u32(data_buffer, 0); - (void)ldns_rdf2buffer_wire(data_buffer, algorithm_rdf); + if (!tsig_timers_only) { + (void)ldns_rdf2buffer_wire(data_buffer, key_name_rdf); + ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY); + ldns_buffer_write_u32(data_buffer, 0); + (void)ldns_rdf2buffer_wire(data_buffer, algorithm_rdf); + } (void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf); (void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf); - (void)ldns_rdf2buffer_wire(data_buffer, error_rdf); - (void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf); + if (!tsig_timers_only) { + (void)ldns_rdf2buffer_wire(data_buffer, error_rdf); + (void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf); + } wireformat = (char *) data_buffer->_data; wiresize = (int) ldns_buffer_position(data_buffer); algorithm_name = ldns_rdf2str(algorithm_rdf); + if(!algorithm_name) { + ldns_buffer_free(data_buffer); + return LDNS_STATUS_MEM_ERR; + } /* prepare the key */ key_bytes = LDNS_XMALLOC(unsigned char, ldns_b64_pton_calculate_size(strlen(key_data))); - key_size = ldns_b64_pton(key_data, key_bytes, strlen(key_data) * 2); + if(!key_bytes) { + LDNS_FREE(algorithm_name); + ldns_buffer_free(data_buffer); + return LDNS_STATUS_MEM_ERR; + } + key_size = ldns_b64_pton(key_data, key_bytes, + ldns_b64_pton_calculate_size(strlen(key_data))); if (key_size < 0) { + LDNS_FREE(algorithm_name); + LDNS_FREE(key_bytes); + ldns_buffer_free(data_buffer); /* LDNS_STATUS_INVALID_B64 */ return LDNS_STATUS_INVALID_B64; } /* hmac it */ /* 2 spare bytes for the length */ - mac_bytes = LDNS_XMALLOC(unsigned char, md_len); - memset(mac_bytes, 0, md_len); + mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2); + if(!mac_bytes) { + LDNS_FREE(algorithm_name); + LDNS_FREE(key_bytes); + ldns_buffer_free(data_buffer); + return LDNS_STATUS_MEM_ERR; + } + memset(mac_bytes, 0, md_len+2); digester = ldns_digest_function(algorithm_name); @@ -208,6 +234,10 @@ ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2, mac_bytes); } else { + LDNS_FREE(algorithm_name); + LDNS_FREE(mac_bytes); + LDNS_FREE(key_bytes); + ldns_buffer_free(data_buffer); return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; } @@ -225,8 +255,15 @@ ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, #ifdef HAVE_SSL bool -ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, - const char *key_name, const char *key_data, ldns_rdf *orig_mac_rdf) +ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char *key_name, + const char *key_data, ldns_rdf *orig_mac_rdf) +{ + return ldns_pkt_tsig_verify_next(pkt, wire, wirelen, key_name, key_data, orig_mac_rdf, 0); +} + +bool +ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char* key_name, + const char *key_data, ldns_rdf *orig_mac_rdf, int tsig_timers_only) { ldns_rdf *fudge_rdf; ldns_rdf *algorithm_rdf; @@ -268,7 +305,7 @@ ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size, key_data, key_name_rdf, fudge_rdf, algorithm_rdf, - time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf); + time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only); LDNS_FREE(prepared_wire); @@ -296,7 +333,14 @@ ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, /* TODO: memory :p */ ldns_status ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, - uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac) + uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac) +{ + return ldns_pkt_tsig_sign_next(pkt, key_name, key_data, fudge, algorithm_name, query_mac, 0); +} + +ldns_status +ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, + uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only) { ldns_rr *tsig_rr; ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name); @@ -346,7 +390,7 @@ ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len, key_data, key_name_rdf, fudge_rdf, algorithm_rdf, - time_signed_rdf, error_rdf, other_data_rdf, query_mac); + time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only); if (!mac_rdf) { goto clean; diff --git a/contrib/ldns/util.c b/contrib/ldns/util.c index 82fa264189..3b446ba719 100644 --- a/contrib/ldns/util.c +++ b/contrib/ldns/util.c @@ -262,7 +262,6 @@ ldns_init_random(FILE *fd, unsigned int size) size_t read = 0; unsigned int seed_i; struct timeval tv; - struct timezone tz; /* we'll need at least sizeof(unsigned int) bytes for the standard prng seed */ @@ -279,7 +278,7 @@ ldns_init_random(FILE *fd, unsigned int size) /* no readable /dev/random either, and no entropy source given. we'll have to improvise */ for (read = 0; read < size; read++) { - gettimeofday(&tv, &tz); + gettimeofday(&tv, NULL); seed[read] = (uint8_t) (tv.tv_usec % 256); } } else { @@ -312,12 +311,30 @@ ldns_init_random(FILE *fd, unsigned int size) } if (!fd) { - fclose(rand_f); + if (rand_f) fclose(rand_f); } return 0; } +/** + * Get random number. + * + */ +uint16_t +ldns_get_random(void) +{ + uint16_t rid = 0; +#ifdef HAVE_SSL + if (RAND_bytes((unsigned char*)&rid, 2) != 1) { + rid = (uint16_t) random(); + } +#else + rid = (uint16_t) random(); +#endif + return rid; +} + /* * BubbleBabble code taken from OpenSSH * Copyright (c) 2001 Carsten Raskgaard. All rights reserved. @@ -333,6 +350,7 @@ ldns_bubblebabble(uint8_t *data, size_t len) rounds = (len / 2) + 1; retval = LDNS_XMALLOC(char, rounds * 6); + if(!retval) return NULL; retval[j++] = 'x'; for (i = 0; i < rounds; i++) { size_t idx0, idx1, idx2, idx3, idx4; diff --git a/contrib/ldns/wire2host.c b/contrib/ldns/wire2host.c index c694aa0b9d..e87fcdf5df 100644 --- a/contrib/ldns/wire2host.c +++ b/contrib/ldns/wire2host.c @@ -88,7 +88,7 @@ ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos) if (pointer_target == 0) { return LDNS_STATUS_INVALID_POINTER; - } else if (pointer_target > max) { + } else if (pointer_target >= max) { return LDNS_STATUS_INVALID_POINTER; } else if (pointer_count > LDNS_MAX_POINTERS) { return LDNS_STATUS_INVALID_POINTER; @@ -101,7 +101,7 @@ ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos) if (label_size > LDNS_MAX_LABELLEN) { return LDNS_STATUS_LABEL_OVERFLOW; } - if (*pos + label_size > max) { + if (*pos + 1 + label_size > max) { return LDNS_STATUS_LABEL_OVERFLOW; } @@ -433,7 +433,7 @@ ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max) ldns_pkt_set_edns_data(packet, ldns_rdf_clone(ldns_rr_rdf(rr, 0))); } ldns_rr_free(rr); - have_edns = 1; + have_edns += 1; } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_TSIG) { ldns_pkt_set_tsig(packet, rr); ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) - 1); @@ -444,7 +444,8 @@ ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max) } ldns_pkt_set_size(packet, max); if(have_edns) - ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) - 1); + ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + - have_edns); *packet_p = packet; return status; diff --git a/contrib/ldns/zone.c b/contrib/ldns/zone.c index 77c39b4b25..8cd02adf5a 100644 --- a/contrib/ldns/zone.c +++ b/contrib/ldns/zone.c @@ -81,7 +81,7 @@ ldns_zone_strip_glue_rrs(const ldns_rdf *zone_name, const ldns_rr_list *rrs, ldn ldns_rr_list *zone_cuts; ldns_rr_list *addr; ldns_rr *r, *ns, *a; - ldns_rdf *dname_a, *dname_ns, *ns_owner; + ldns_rdf *dname_a, *ns_owner; uint16_t i,j; new_list = NULL; @@ -120,7 +120,6 @@ ldns_zone_strip_glue_rrs(const ldns_rdf *zone_name, const ldns_rr_list *rrs, ldn for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) { ns = ldns_rr_list_rr(zone_cuts, i); ns_owner = ldns_rr_owner(ns); - dname_ns = ldns_rr_ns_nsdname(ns); for(j = 0; j < ldns_rr_list_rr_count(addr); j++) { a = ldns_rr_list_rr(addr, j); dname_a = ldns_rr_owner(a); @@ -180,7 +179,7 @@ ldns_zone_glue_rr_list(const ldns_zone *z) ldns_rr_list *addr; ldns_rr_list *glue; ldns_rr *r, *ns, *a; - ldns_rdf *dname_a, *dname_ns, *ns_owner; + ldns_rdf *dname_a, *ns_owner; size_t i,j; zone_cuts = NULL; @@ -225,7 +224,6 @@ ldns_zone_glue_rr_list(const ldns_zone *z) ns = ldns_rr_list_rr(zone_cuts, i); ns_owner = ldns_rr_owner(ns); - dname_ns = ldns_rr_ns_nsdname(ns); for(j = 0; j < ldns_rr_list_rr_count(addr); j++) { a = ldns_rr_list_rr(addr, j); dname_a = ldns_rr_owner(a); @@ -290,13 +288,12 @@ ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ld /* XXX: class is never used */ ldns_status -ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c, - int *line_nr) +ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, + ldns_rr_class ATTR_UNUSED(c), int *line_nr) { ldns_zone *newzone; ldns_rr *rr; uint32_t my_ttl; - ldns_rr_class my_class; ldns_rdf *my_origin; ldns_rdf *my_prev; bool soa_seen = false; /* 2 soa are an error */ @@ -311,7 +308,6 @@ ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, my_prev = NULL; my_ttl = ttl; - my_class = c; if (origin) { my_origin = ldns_rdf_clone(origin); @@ -350,7 +346,6 @@ ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, /*my_origin = ldns_rr_owner(rr);*/ my_ttl = ldns_rr_ttl(rr); /* XXX: this seems like an error */ - my_class = ldns_rr_get_class(rr); case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ case LDNS_STATUS_SYNTAX_TTL: @@ -359,6 +354,9 @@ ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, case LDNS_STATUS_SYNTAX_ORIGIN: /* the function set the origin */ break; + case LDNS_STATUS_SYNTAX_INCLUDE: + ret = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL; + break; default: ret = s; goto error; -- 2.41.0