diff options
author | Stuart Henderson <sthen@cvs.openbsd.org> | 2013-09-22 11:58:44 +0000 |
---|---|---|
committer | Stuart Henderson <sthen@cvs.openbsd.org> | 2013-09-22 11:58:44 +0000 |
commit | 10c1827d4b55aefe78d87de1d175a77ac07c3ed6 (patch) | |
tree | d69757dde70e3229e09107d86a1e37a3de206ed2 | |
parent | 090f474021a3c7c46dbe024f2db2fdde018645a8 (diff) |
update to ldns 1.6.16
53 files changed, 2271 insertions, 411 deletions
diff --git a/usr.sbin/unbound/ldns/Changelog b/usr.sbin/unbound/ldns/Changelog index 93e53931d84..845d5b8a738 100644 --- a/usr.sbin/unbound/ldns/Changelog +++ b/usr.sbin/unbound/ldns/Changelog @@ -1,3 +1,51 @@ +1.6.16 2012-11-13 + * Fix Makefile to build pyldns with BSD make + * Fix typo in exporting b32_* symbols to make pyldns load again + * Allow leaving the RR owner name empty in ldns-testns datafiles. + * Fix fail to create NSEC3 bitmap for empty non-terminal (bug + introduced in 1.6.14). + +1.6.15 2012-10-25 + * Remove LDNS_STATUS_EXISTS_ERR from ldns/error.h to make ldns + binary compatible with earlier releases again. + +1.6.14 2012-10-23 + * DANE support (RFC6698), including ldns-dane example tool. + * Configurable default CA certificate repository for ldns-dane with + --with-ca-file=CAFILE and --with-ca-path=CAPATH + * Configurable default trust anchor with --with-trust-anchor=FILE + for drill, ldns-verify-zone and ldns-dane + * bugfix #474: Define socklen_t when undefined (like in Win32) + * bugfix #473: Dead code removal and resource leak fix in drill + * bugfix #471: Let ldns_resolver_push_dnssec_anchor accept DS RR's too. + * Various bugfixes from code reviews from CZ.NIC and Paul Wouters + * ldns-notify TSIG option argument checking + * Let ldns_resolver_nameservers_randomize keep nameservers and rtt's + in sync. + * Let ldns_pkt_push_rr now return false on (memory) errors. + * Make buffer_export comply to documentation and fix buffer2str + * Various improvements and fixes of pyldns from Katel Slany + now documented in their own Changelog. + * bugfix: Make ldns_resolver_pop_nameserver clear the array when + there was only one. + * bugfix #459: Remove ldns_symbols and export symbols based on regex + * bugfix #458: Track all newly created signatures when signing. + * bugfix #454: Only set -g and -O2 CFLAGS when no CFLAGS was given. + * bugfix #457: Memory leak fix for ldns_key_new_frm_algorithm. + * pyldns memory handling fixes and the python3/ldns-signzone.py + examples script contribution from Karel Slany. + * bugfix #450: Base # bytes for P, G and Y (T) on the guaranteed + to be bigger (or equal) P in ldns_key_dsa2bin. + * bugfix #449: Deep free cloned rdf's in ldns_tsig_mac_new. + * bugfix #448: Copy nameserver value (in stead of reference) of the + answering nameserver to the answer packet in ldns_send_buffer, so + the original value may be deep freed with the ldns_resolver struct. + * New -0 option for ldns-read-zone to replace inception, expiration + and signature rdata fields with (null). Thanks Paul Wouters. + * New -p option for ldns-read-zone to prepend-pad SOA serial to take + up ten characters. + * Return error if printing RR fails due to unknown/null RDATA. + 1.6.13 2012-05-21 * New -S option for ldns-verify-zone to chase signatures online. * New -k option for ldns-verify-zone to validate using a trusted key. diff --git a/usr.sbin/unbound/ldns/buffer.c b/usr.sbin/unbound/ldns/buffer.c index 5a6b0ba74c8..fc6c17e7a9f 100644 --- a/usr.sbin/unbound/ldns/buffer.c +++ b/usr.sbin/unbound/ldns/buffer.c @@ -140,7 +140,8 @@ ldns_buffer_free(ldns_buffer *buffer) return; } - LDNS_FREE(buffer->_data); + if (!buffer->_fixed) + LDNS_FREE(buffer->_data); LDNS_FREE(buffer); } diff --git a/usr.sbin/unbound/ldns/dane.c b/usr.sbin/unbound/ldns/dane.c new file mode 100644 index 00000000000..793005ddcb3 --- /dev/null +++ b/usr.sbin/unbound/ldns/dane.c @@ -0,0 +1,742 @@ +/* + * Verify or create TLS authentication with DANE (RFC6698) + * + * (c) NLnetLabs 2012 + * + * See the file LICENSE for the license. + * + */ + +#include <ldns/config.h> + +#include <ldns/ldns.h> +#include <ldns/dane.h> + +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> + +#ifdef HAVE_SSL +#include <openssl/ssl.h> +#include <openssl/err.h> +#include <openssl/x509v3.h> +#endif + +ldns_status +ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name, + uint16_t port, ldns_dane_transport transport) +{ + char buf[LDNS_MAX_DOMAINLEN]; + size_t s; + + assert(tlsa_owner != NULL); + assert(name != NULL); + assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME); + + s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port); + buf[0] = (char)(s - 1); + + switch(transport) { + case LDNS_DANE_TRANSPORT_TCP: + s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp"); + break; + + case LDNS_DANE_TRANSPORT_UDP: + s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp"); + break; + + case LDNS_DANE_TRANSPORT_SCTP: + s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp"); + break; + + default: + return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT; + } + if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) { + return LDNS_STATUS_DOMAINNAME_OVERFLOW; + } + memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name)); + *tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, + s + ldns_rdf_size(name), buf); + if (*tlsa_owner == NULL) { + return LDNS_STATUS_MEM_ERR; + } + return LDNS_STATUS_OK; +} + + +#ifdef HAVE_SSL +ldns_status +ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type) +{ + unsigned char* buf = NULL; + size_t len; + + X509_PUBKEY* xpubkey; + EVP_PKEY* epubkey; + + unsigned char* digest; + + assert(rdf != NULL); + assert(cert != NULL); + + switch(selector) { + case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE: + + len = (size_t)i2d_X509(cert, &buf); + break; + + case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO: + +#ifndef S_SPLINT_S + xpubkey = X509_get_X509_PUBKEY(cert); +#endif + if (! xpubkey) { + return LDNS_STATUS_SSL_ERR; + } + epubkey = X509_PUBKEY_get(xpubkey); + if (! epubkey) { + return LDNS_STATUS_SSL_ERR; + } + len = (size_t)i2d_PUBKEY(epubkey, &buf); + break; + + default: + return LDNS_STATUS_DANE_UNKNOWN_SELECTOR; + } + + switch(matching_type) { + case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED: + + *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf); + + return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; + break; + + case LDNS_TLSA_MATCHING_TYPE_SHA256: + + digest = LDNS_XMALLOC(unsigned char, SHA256_DIGEST_LENGTH); + if (digest == NULL) { + LDNS_FREE(buf); + return LDNS_STATUS_MEM_ERR; + } + (void) ldns_sha256(buf, (unsigned int)len, digest); + *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH, + digest); + LDNS_FREE(buf); + + return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; + break; + + case LDNS_TLSA_MATCHING_TYPE_SHA512: + + digest = LDNS_XMALLOC(unsigned char, SHA512_DIGEST_LENGTH); + if (digest == NULL) { + LDNS_FREE(buf); + return LDNS_STATUS_MEM_ERR; + } + (void) ldns_sha512(buf, (unsigned int)len, digest); + *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA512_DIGEST_LENGTH, + digest); + LDNS_FREE(buf); + + return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; + break; + + default: + LDNS_FREE(buf); + return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE; + } +} + + +/* Ordinary PKIX validation of cert (with extra_certs to help) + * against the CA's in store + */ +static ldns_status +ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* store) +{ + X509_STORE_CTX* vrfy_ctx; + ldns_status s; + + if (! store) { + return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; + } + vrfy_ctx = X509_STORE_CTX_new(); + if (! vrfy_ctx) { + + return LDNS_STATUS_SSL_ERR; + + } else if (X509_STORE_CTX_init(vrfy_ctx, store, + cert, extra_certs) != 1) { + s = LDNS_STATUS_SSL_ERR; + + } else if (X509_verify_cert(vrfy_ctx) == 1) { + + s = LDNS_STATUS_OK; + + } else { + s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; + } + X509_STORE_CTX_free(vrfy_ctx); + return s; +} + + +/* Orinary PKIX validation of cert (with extra_certs to help) + * against the CA's in store, but also return the validation chain. + */ +static ldns_status +ldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert, + STACK_OF(X509)* extra_certs, X509_STORE* store) +{ + ldns_status s; + X509_STORE* empty_store = NULL; + X509_STORE_CTX* vrfy_ctx; + + assert(chain != NULL); + + if (! store) { + store = empty_store = X509_STORE_new(); + } + s = LDNS_STATUS_SSL_ERR; + vrfy_ctx = X509_STORE_CTX_new(); + if (! vrfy_ctx) { + + goto exit_free_empty_store; + + } else if (X509_STORE_CTX_init(vrfy_ctx, store, + cert, extra_certs) != 1) { + goto exit_free_vrfy_ctx; + + } else if (X509_verify_cert(vrfy_ctx) == 1) { + + s = LDNS_STATUS_OK; + + } else { + s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; + } + *chain = X509_STORE_CTX_get1_chain(vrfy_ctx); + if (! *chain) { + s = LDNS_STATUS_SSL_ERR; + } + +exit_free_vrfy_ctx: + X509_STORE_CTX_free(vrfy_ctx); + +exit_free_empty_store: + if (empty_store) { + X509_STORE_free(empty_store); + } + return s; +} + + +/* Return the validation chain that can be build out of cert, with extra_certs. + */ +static ldns_status +ldns_dane_pkix_get_chain(STACK_OF(X509)** chain, + X509* cert, STACK_OF(X509)* extra_certs) +{ + ldns_status s; + X509_STORE* empty_store = NULL; + X509_STORE_CTX* vrfy_ctx; + + assert(chain != NULL); + + empty_store = X509_STORE_new(); + s = LDNS_STATUS_SSL_ERR; + vrfy_ctx = X509_STORE_CTX_new(); + if (! vrfy_ctx) { + + goto exit_free_empty_store; + + } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store, + cert, extra_certs) != 1) { + goto exit_free_vrfy_ctx; + } + (void) X509_verify_cert(vrfy_ctx); + *chain = X509_STORE_CTX_get1_chain(vrfy_ctx); + if (! *chain) { + s = LDNS_STATUS_SSL_ERR; + } else { + s = LDNS_STATUS_OK; + } +exit_free_vrfy_ctx: + X509_STORE_CTX_free(vrfy_ctx); + +exit_free_empty_store: + X509_STORE_free(empty_store); + return s; +} + + +/* Pop n+1 certs and return the last popped. + */ +static ldns_status +ldns_dane_get_nth_cert_from_validation_chain( + X509** cert, STACK_OF(X509)* chain, int n, bool ca) +{ + if (n >= sk_X509_num(chain) || n < 0) { + return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE; + } + *cert = sk_X509_pop(chain); + while (n-- > 0) { + X509_free(*cert); + *cert = sk_X509_pop(chain); + } + if (ca && ! X509_check_ca(*cert)) { + return LDNS_STATUS_DANE_NON_CA_CERTIFICATE; + } + return LDNS_STATUS_OK; +} + + +/* Create validation chain with cert and extra_certs and returns the last + * self-signed (if present). + */ +static ldns_status +ldns_dane_pkix_get_last_self_signed(X509** out_cert, + X509* cert, STACK_OF(X509)* extra_certs) +{ + ldns_status s; + X509_STORE* empty_store = NULL; + X509_STORE_CTX* vrfy_ctx; + + assert(out_cert != NULL); + + empty_store = X509_STORE_new(); + s = LDNS_STATUS_SSL_ERR; + vrfy_ctx = X509_STORE_CTX_new(); + if (! vrfy_ctx) { + goto exit_free_empty_store; + + } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store, + cert, extra_certs) != 1) { + goto exit_free_vrfy_ctx; + + } + (void) X509_verify_cert(vrfy_ctx); + if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || + vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){ + + *out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx); + s = LDNS_STATUS_OK; + } else { + s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR; + } +exit_free_vrfy_ctx: + X509_STORE_CTX_free(vrfy_ctx); + +exit_free_empty_store: + X509_STORE_free(empty_store); + return s; +} + + +ldns_status +ldns_dane_select_certificate(X509** selected_cert, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store, + ldns_tlsa_certificate_usage cert_usage, int offset) +{ + ldns_status s; + STACK_OF(X509)* pkix_validation_chain = NULL; + + assert(selected_cert != NULL); + assert(cert != NULL); + + /* With PKIX validation explicitely turned off (pkix_validation_store + * == NULL), treat the "CA constraint" and "Service certificate + * constraint" the same as "Trust anchor assertion" and "Domain issued + * certificate" respectively. + */ + if (pkix_validation_store == NULL) { + switch (cert_usage) { + + case LDNS_TLSA_USAGE_CA_CONSTRAINT: + + cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION; + break; + + case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: + + cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE; + break; + + default: + break; + } + } + + /* Now what to do with each Certificate usage... + */ + switch (cert_usage) { + + case LDNS_TLSA_USAGE_CA_CONSTRAINT: + + s = ldns_dane_pkix_validate_and_get_chain( + &pkix_validation_chain, + cert, extra_certs, + pkix_validation_store); + if (! pkix_validation_chain) { + return s; + } + if (s == LDNS_STATUS_OK) { + if (offset == -1) { + offset = 0; + } + s = ldns_dane_get_nth_cert_from_validation_chain( + selected_cert, pkix_validation_chain, + offset, true); + } + sk_X509_pop_free(pkix_validation_chain, X509_free); + return s; + break; + + + case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: + + *selected_cert = cert; + return ldns_dane_pkix_validate(cert, extra_certs, + pkix_validation_store); + break; + + + case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: + + if (offset == -1) { + s = ldns_dane_pkix_get_last_self_signed( + selected_cert, cert, extra_certs); + return s; + } else { + s = ldns_dane_pkix_get_chain( + &pkix_validation_chain, + cert, extra_certs); + if (s == LDNS_STATUS_OK) { + s = + ldns_dane_get_nth_cert_from_validation_chain( + selected_cert, pkix_validation_chain, + offset, false); + } else if (! pkix_validation_chain) { + return s; + } + sk_X509_pop_free(pkix_validation_chain, X509_free); + return s; + } + break; + + + case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: + + *selected_cert = cert; + return LDNS_STATUS_OK; + break; + + default: + return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE; + break; + } +} + + +ldns_status +ldns_dane_create_tlsa_rr(ldns_rr** tlsa, + ldns_tlsa_certificate_usage certificate_usage, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type, + X509* cert) +{ + ldns_rdf* rdf; + ldns_status s; + + assert(tlsa != NULL); + assert(cert != NULL); + + /* create rr */ + *tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA); + if (*tlsa == NULL) { + return LDNS_STATUS_MEM_ERR; + } + + rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, + (uint8_t)certificate_usage); + if (rdf == NULL) { + goto memerror; + } + (void) ldns_rr_set_rdf(*tlsa, rdf, 0); + + rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector); + if (rdf == NULL) { + goto memerror; + } + (void) ldns_rr_set_rdf(*tlsa, rdf, 1); + + rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type); + if (rdf == NULL) { + goto memerror; + } + (void) ldns_rr_set_rdf(*tlsa, rdf, 2); + + s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type); + if (s == LDNS_STATUS_OK) { + (void) ldns_rr_set_rdf(*tlsa, rdf, 3); + return LDNS_STATUS_OK; + } + ldns_rr_free(*tlsa); + *tlsa = NULL; + return s; + +memerror: + ldns_rr_free(*tlsa); + *tlsa = NULL; + return LDNS_STATUS_MEM_ERR; +} + + +/* Return tlsas that actually are TLSA resource records with known values + * for the Certificate usage, Selector and Matching type rdata fields. + */ +static ldns_rr_list* +ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas) +{ + size_t i; + ldns_rr_list* r = ldns_rr_list_new(); + ldns_rr* tlsa_rr; + + if (! r) { + return NULL; + } + for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) { + tlsa_rr = ldns_rr_list_rr(tlsas, i); + if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA && + ldns_rr_rd_count(tlsa_rr) == 4 && + ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 && + ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 && + ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) { + + if (! ldns_rr_list_push_rr(r, tlsa_rr)) { + ldns_rr_list_free(r); + return NULL; + } + } + } + return r; +} + + +/* Return whether cert/selector/matching_type matches data. + */ +static ldns_status +ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type, ldns_rdf* data) +{ + ldns_status s; + ldns_rdf* match_data; + + s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type); + if (s == LDNS_STATUS_OK) { + if (ldns_rdf_compare(data, match_data) != 0) { + s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH; + } + ldns_rdf_free(match_data); + } + return s; +} + + +/* Return whether any certificate from the chain with selector/matching_type + * matches data. + * ca should be true if the certificate has to be a CA certificate too. + */ +static ldns_status +ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type, + ldns_rdf* data, bool ca) +{ + ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH; + size_t n, i; + X509* cert; + + n = (size_t)sk_X509_num(chain); + for (i = 0; i < n; i++) { + cert = sk_X509_pop(chain); + if (! cert) { + s = LDNS_STATUS_SSL_ERR; + break; + } + s = ldns_dane_match_cert_with_data(cert, + selector, matching_type, data); + if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) { + s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE; + } + X509_free(cert); + if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) { + break; + } + /* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH, + * try to match the next certificate + */ + } + return s; +} + + +ldns_status +ldns_dane_verify_rr(const ldns_rr* tlsa_rr, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store) +{ + ldns_status s; + + STACK_OF(X509)* pkix_validation_chain = NULL; + + ldns_tlsa_certificate_usage cert_usage; + ldns_tlsa_selector selector; + ldns_tlsa_matching_type matching_type; + ldns_rdf* data; + + if (! tlsa_rr) { + /* No TLSA, so regular PKIX validation + */ + return ldns_dane_pkix_validate(cert, extra_certs, + pkix_validation_store); + } + cert_usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)); + selector = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)); + matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)); + data = ldns_rr_rdf(tlsa_rr, 3) ; + + switch (cert_usage) { + case LDNS_TLSA_USAGE_CA_CONSTRAINT: + s = ldns_dane_pkix_validate_and_get_chain( + &pkix_validation_chain, + cert, extra_certs, + pkix_validation_store); + if (! pkix_validation_chain) { + return s; + } + if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) { + /* + * NO PKIX validation. We still try to match *any* + * certificate from the chain, so we return + * TLSA errors over PKIX errors. + * + * i.e. When the TLSA matches no certificate, we return + * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE + */ + s = ldns_dane_match_any_cert_with_data( + pkix_validation_chain, + selector, matching_type, data, true); + + if (s == LDNS_STATUS_OK) { + /* A TLSA record did match a cert from the + * chain, thus the error is failed PKIX + * validation. + */ + s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; + } + + } else if (s == LDNS_STATUS_OK) { + /* PKIX validated, does the TLSA match too? */ + + s = ldns_dane_match_any_cert_with_data( + pkix_validation_chain, + selector, matching_type, data, true); + } + sk_X509_pop_free(pkix_validation_chain, X509_free); + return s; + break; + + case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: + s = ldns_dane_match_cert_with_data(cert, + selector, matching_type, data); + + if (s == LDNS_STATUS_OK) { + return ldns_dane_pkix_validate(cert, extra_certs, + pkix_validation_store); + } + return s; + break; + + case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: + s = ldns_dane_pkix_get_chain(&pkix_validation_chain, + cert, extra_certs); + + if (s == LDNS_STATUS_OK) { + s = ldns_dane_match_any_cert_with_data( + pkix_validation_chain, + selector, matching_type, data, false); + + } else if (! pkix_validation_chain) { + return s; + } + sk_X509_pop_free(pkix_validation_chain, X509_free); + return s; + break; + + case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: + return ldns_dane_match_cert_with_data(cert, + selector, matching_type, data); + break; + + default: + break; + } + return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE; +} + + +ldns_status +ldns_dane_verify(ldns_rr_list* tlsas, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store) +{ + size_t i; + ldns_rr* tlsa_rr; + ldns_status s = LDNS_STATUS_OK, ps; + + assert(cert != NULL); + + if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) { + tlsas = ldns_dane_filter_unusable_records(tlsas); + if (! tlsas) { + return LDNS_STATUS_MEM_ERR; + } + } + if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) { + /* No TLSA's, so regular PKIX validation + */ + return ldns_dane_pkix_validate(cert, extra_certs, + pkix_validation_store); + } else { + for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) { + tlsa_rr = ldns_rr_list_rr(tlsas, i); + ps = s; + s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs, + pkix_validation_store); + + if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH && + s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) { + + /* which would be LDNS_STATUS_OK (match) + * or some fatal error preventing use from + * trying the next TLSA record. + */ + break; + } + s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE + * over TLSA_DID_NOT_MATCH + */ + } + ldns_rr_list_free(tlsas); + } + return s; +} +#endif /* HAVE_SSL */ diff --git a/usr.sbin/unbound/ldns/dname.c b/usr.sbin/unbound/ldns/dname.c index f3770feafb5..55aba5d65a1 100644 --- a/usr.sbin/unbound/ldns/dname.c +++ b/usr.sbin/unbound/ldns/dname.c @@ -30,6 +30,24 @@ #include <arpa/inet.h> #endif +/* Returns whether the last label in the name is a root label (a empty label). + * Note that it is not enough to just test the last character to be 0, + * because it may be part of the last label itself. + */ +static bool +ldns_dname_last_label_is_root_label(const ldns_rdf* dname) +{ + size_t src_pos; + size_t len = 0; + + for (src_pos = 0; src_pos < ldns_rdf_size(dname); src_pos += len + 1) { + len = ldns_rdf_data(dname)[src_pos]; + } + assert(src_pos == ldns_rdf_size(dname)); + + return src_pos > 0 && len == 0; +} + ldns_rdf * ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2) { @@ -47,7 +65,7 @@ ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2) * rd, by reducing the size with 1 */ left_size = ldns_rdf_size(rd1); - if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) { + if (ldns_dname_last_label_is_root_label(rd1)) { left_size--; } @@ -84,7 +102,7 @@ ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2) * rd, by reducing the size with 1 */ left_size = ldns_rdf_size(rd1); - if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) { + if (ldns_dname_last_label_is_root_label(rd1)) { left_size--; } @@ -102,36 +120,39 @@ ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2) return LDNS_STATUS_OK; } -ldns_rdf * -ldns_dname_reverse(const ldns_rdf *d) +ldns_rdf* +ldns_dname_reverse(const ldns_rdf *dname) { - ldns_rdf *new; - ldns_rdf *tmp; - ldns_rdf *d_tmp; - ldns_status status; - - d_tmp = ldns_rdf_clone(d); - - new = ldns_dname_new_frm_str("."); - if(!new) - return NULL; - - while(ldns_dname_label_count(d_tmp) > 0) { - tmp = ldns_dname_label(d_tmp, 0); - status = ldns_dname_cat(tmp, new); - if(status != LDNS_STATUS_OK) { - ldns_rdf_deep_free(new); - ldns_rdf_deep_free(d_tmp); - return NULL; - } - ldns_rdf_deep_free(new); - new = tmp; - tmp = ldns_dname_left_chop(d_tmp); - ldns_rdf_deep_free(d_tmp); - d_tmp = tmp; + size_t rd_size; + uint8_t* buf; + ldns_rdf* new; + size_t src_pos; + size_t len ; + + assert(ldns_rdf_get_type(dname) == LDNS_RDF_TYPE_DNAME); + + rd_size = ldns_rdf_size(dname); + buf = LDNS_XMALLOC(uint8_t, rd_size); + if (! buf) { + return NULL; + } + new = ldns_rdf_new(LDNS_RDF_TYPE_DNAME, rd_size, buf); + if (! new) { + LDNS_FREE(buf); + return NULL; + } + + /* If dname ends in a root label, the reverse should too. + */ + if (ldns_dname_last_label_is_root_label(dname)) { + buf[rd_size - 1] = 0; + rd_size -= 1; + } + for (src_pos = 0; src_pos < rd_size; src_pos += len + 1) { + len = ldns_rdf_data(dname)[src_pos]; + memcpy(&buf[rd_size - src_pos - len - 1], + &ldns_rdf_data(dname)[src_pos], len + 1); } - ldns_rdf_deep_free(d_tmp); - return new; } @@ -519,6 +540,18 @@ ldns_dname_str_absolute(const char *dname_str) return 0; } +bool +ldns_dname_absolute(const ldns_rdf *rdf) +{ + char *str = ldns_rdf2str(rdf); + if (str) { + bool r = ldns_dname_str_absolute(str); + LDNS_FREE(str); + return r; + } + return false; +} + ldns_rdf * ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos) { diff --git a/usr.sbin/unbound/ldns/dnssec.c b/usr.sbin/unbound/ldns/dnssec.c index c6e93211787..684d17169e2 100644 --- a/usr.sbin/unbound/ldns/dnssec.c +++ b/usr.sbin/unbound/ldns/dnssec.c @@ -743,7 +743,6 @@ ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1); cur_data_size += cur_window_max + 3; } - bitmap_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC, cur_data_size, data); @@ -1154,12 +1153,15 @@ ldns_create_nsec3(ldns_rdf *cur_owner, salt_length, salt); status = ldns_dname_cat(hashed_owner, cur_zone); - if(status != LDNS_STATUS_OK) + if(status != LDNS_STATUS_OK) { + ldns_rdf_deep_free(hashed_owner); return NULL; - + } nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); - if(!nsec) + if(!nsec) { + ldns_rdf_deep_free(hashed_owner); return NULL; + } ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3); ldns_rr_set_owner(nsec, hashed_owner); @@ -1443,8 +1445,9 @@ ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, sigs = s; } else { /* otherwise get them from the packet */ - sigs = ldns_pkt_rr_list_by_name_and_type(p, o, LDNS_RR_TYPE_RRSIG, - LDNS_SECTION_ANY_NOQUESTION); + sigs = ldns_pkt_rr_list_by_name_and_type(p, o, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANY_NOQUESTION); if (!sigs) { /* no sigs */ return LDNS_STATUS_ERR; @@ -1457,24 +1460,26 @@ ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, */ t_netorder = htons(t); /* rdf are in network order! */ /* a type identifier is a 16-bit number, so the size is 2 bytes */ - rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, - 2, - &t_netorder); - sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); + rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2, &t_netorder); - rrset = ldns_pkt_rr_list_by_name_and_type(p, - o, - t, - LDNS_SECTION_ANY_NOQUESTION); - - if (!rrset) { + sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); + ldns_rdf_free(rdf_t); + if (! sigs_covered) { + if (! s) { + ldns_rr_list_deep_free(sigs); + } return LDNS_STATUS_ERR; } + ldns_rr_list_deep_free(sigs_covered); - if (!sigs_covered) { + rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t, + LDNS_SECTION_ANY_NOQUESTION); + if (!rrset) { + if (! s) { + ldns_rr_list_deep_free(sigs); + } return LDNS_STATUS_ERR; } - return ldns_verify_time(rrset, sigs, k, check_time, good_keys); } diff --git a/usr.sbin/unbound/ldns/dnssec_sign.c b/usr.sbin/unbound/ldns/dnssec_sign.c index 88878bad044..f2f9d9dda87 100644 --- a/usr.sbin/unbound/ldns/dnssec_sign.c +++ b/usr.sbin/unbound/ldns/dnssec_sign.c @@ -260,6 +260,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) ldns_buffer_free(sign_buf); /* ERROR */ ldns_rr_list_deep_free(rrset_clone); + ldns_rr_free(current_sig); + ldns_rr_list_deep_free(signatures); return NULL; } @@ -268,6 +270,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) != LDNS_STATUS_OK) { ldns_buffer_free(sign_buf); ldns_rr_list_deep_free(rrset_clone); + ldns_rr_free(current_sig); + ldns_rr_list_deep_free(signatures); return NULL; } @@ -276,6 +280,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) if (!b64rdf) { /* signing went wrong */ ldns_rr_list_deep_free(rrset_clone); + ldns_rr_free(current_sig); + ldns_rr_list_deep_free(signatures); return NULL; } @@ -481,10 +487,7 @@ ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key) (unsigned char*)ldns_buffer_begin(b64sig), &siglen, key); if (result != 1) { - return NULL; - } - - if (result != 1) { + ldns_buffer_free(b64sig); return NULL; } @@ -859,16 +862,14 @@ ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone, ldns_rbtree_next(current_name_node)); } if (result != LDNS_STATUS_OK) { + ldns_rr_list_free(nsec3_list); return result; } ldns_rr_list_sort_nsec3(nsec3_list); result = ldns_dnssec_chain_nsec3_list(nsec3_list); - if (result != LDNS_STATUS_OK) { - return result; - } - ldns_rr_list_free(nsec3_list); + return result; } @@ -1023,9 +1024,9 @@ ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list) } ldns_status -ldns_dnssec_zone_create_rrsigs_flg( ATTR_UNUSED(ldns_dnssec_zone *zone) - , ATTR_UNUSED(ldns_rr_list *new_rrs) - , ATTR_UNUSED(ldns_key_list *key_list) +ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone + , ldns_rr_list *new_rrs + , ldns_key_list *key_list , int (*func)(ldns_rr *, void*) , void *arg , int flags @@ -1112,9 +1113,11 @@ ldns_dnssec_zone_create_rrsigs_flg( ATTR_UNUSED(ldns_dnssec_zone *zone) cur_rrset->signatures = ldns_dnssec_rrs_new(); cur_rrset->signatures->rr = ldns_rr_list_rr(siglist, i); + } + if (new_rrs) { ldns_rr_list_push_rr(new_rrs, - ldns_rr_list_rr(siglist, - i)); + ldns_rr_list_rr(siglist, + i)); } } ldns_rr_list_free(siglist); @@ -1146,8 +1149,10 @@ ldns_dnssec_zone_create_rrsigs_flg( ATTR_UNUSED(ldns_dnssec_zone *zone) cur_name->nsec_signatures = ldns_dnssec_rrs_new(); cur_name->nsec_signatures->rr = ldns_rr_list_rr(siglist, i); + } + if (new_rrs) { ldns_rr_list_push_rr(new_rrs, - ldns_rr_list_rr(siglist, i)); + ldns_rr_list_rr(siglist, i)); } } diff --git a/usr.sbin/unbound/ldns/dnssec_verify.c b/usr.sbin/unbound/ldns/dnssec_verify.c index 68c70c5e848..d435eedf6af 100644 --- a/usr.sbin/unbound/ldns/dnssec_verify.c +++ b/usr.sbin/unbound/ldns/dnssec_verify.c @@ -285,9 +285,11 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, ldns_rr_class c = 0; bool other_rrset = false; - + ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new(); + assert(pkt != NULL); + if (!ldns_dnssec_pkt_has_rrsigs(pkt)) { /* hmm. no dnssec data in the packet. go up to try and deny * DS? */ @@ -402,15 +404,16 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, if (signatures && ldns_rr_list_rr_count(signatures) > 0) { key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7); } - if (!key_name) { + if (signatures) { + ldns_rr_list_deep_free(signatures); + } return ldns_dnssec_build_data_chain_nokeyname(res, qflags, orig_rr, rrset, new_chain); } - if (type != LDNS_RR_TYPE_DNSKEY) { ldns_dnssec_build_data_chain_dnskey(res, qflags, @@ -419,7 +422,7 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, new_chain, key_name, c - ); + ); } else { ldns_dnssec_build_data_chain_other(res, qflags, @@ -427,13 +430,11 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, key_name, c, dss - - ); + ); } if (signatures) { ldns_rr_list_deep_free(signatures); } - return new_chain; } @@ -826,10 +827,7 @@ ldns_dnssec_derive_trust_tree_normal_rrset_time( /* might contain different names! sort and split */ ldns_rr_list_sort(cur_rrset); - if (tmp_rrset && tmp_rrset != cur_rrset) { - ldns_rr_list_deep_free(tmp_rrset); - tmp_rrset = NULL; - } + assert(tmp_rrset == cur_rrset); tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset); /* with nsecs, this might be the wrong one */ @@ -849,6 +847,12 @@ ldns_dnssec_derive_trust_tree_normal_rrset_time( cur_sig_rr, cur_parent_rr, check_time); + if (tmp_rrset && tmp_rrset != cur_rrset + ) { + ldns_rr_list_deep_free( + tmp_rrset); + tmp_rrset = NULL; + } /* avoid dupes */ for (i = 0; i < new_tree->parent_count; i++) { if (cur_parent_rr == new_tree->parents[i]->rr) { @@ -870,9 +874,6 @@ ldns_dnssec_derive_trust_tree_normal_rrset_time( } } done: - if (tmp_rrset && tmp_rrset != cur_rrset) { - ldns_rr_list_deep_free(tmp_rrset); - } ldns_rr_list_deep_free(cur_rrset); } @@ -1077,7 +1078,8 @@ ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, if (tree->parent_status[i] != LDNS_STATUS_OK) { result = tree->parent_status[i]; } else { - if (ldns_rr_get_type(tree->rr) + if (tree->rr && + ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC && parent_result == LDNS_STATUS_OK ) { @@ -1210,8 +1212,8 @@ ldns_fetch_valid_domain_keys_time(const ldns_resolver *res, *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; parent_domain = ldns_dname_left_chop(domain); - while (ldns_rdf_size(parent_domain) > 0) { - /* Fail if we are at the root */ + while (parent_domain && /* Fail if we are at the root*/ + ldns_rdf_size(parent_domain) > 0) { if ((parent_keys = ldns_fetch_valid_domain_keys_time(res, @@ -1247,7 +1249,9 @@ ldns_fetch_valid_domain_keys_time(const ldns_resolver *res, ldns_rdf_deep_free(prev_parent_domain); } } - ldns_rdf_deep_free(parent_domain); + if (parent_domain) { + ldns_rdf_deep_free(parent_domain); + } } } return trusted_keys; @@ -1519,12 +1523,11 @@ ldns_dnssec_verify_denial(ldns_rr *rr, rr_name = ldns_rr_owner(rr); chopped_dname = ldns_dname_left_chop(rr_name); result = ldns_dname_cat(wildcard_name, chopped_dname); + ldns_rdf_deep_free(chopped_dname); if (result != LDNS_STATUS_OK) { return result; } - ldns_rdf_deep_free(chopped_dname); - for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { cur_nsec = ldns_rr_list_rr(nsecs, i); if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { @@ -1576,7 +1579,6 @@ ldns_dnssec_verify_denial(ldns_rr *rr, return LDNS_STATUS_OK; } -#ifdef HAVE_SSL ldns_status ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr , ldns_rr_list *nsecs @@ -1612,7 +1614,7 @@ ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr ldns_rr_get_type(rr), nsecs); if(!closest_encloser) { - result = LDNS_STATUS_NSEC3_ERR; + result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; goto done; } @@ -1636,16 +1638,14 @@ ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr ldns_rdf_deep_free(hashed_wildcard_name); } - ldns_rdf_deep_free(closest_encloser); - ldns_rdf_deep_free(wildcard); - - if (!wildcard_covered) { + if (! wildcard_covered) { result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; - } else if (closest_encloser && wildcard_covered) { - result = LDNS_STATUS_OK; } else { - result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; + result = LDNS_STATUS_OK; } + ldns_rdf_deep_free(closest_encloser); + ldns_rdf_deep_free(wildcard); + } else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) { /* section 8.5 */ hashed_name = ldns_nsec3_hash_name_frm_nsec3( @@ -1819,9 +1819,6 @@ ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, ); } - -#endif /* HAVE_SSL */ - #ifdef USE_GOST EVP_PKEY* ldns_gost2pkey_raw(unsigned char* key, size_t keylen) diff --git a/usr.sbin/unbound/ldns/dnssec_zone.c b/usr.sbin/unbound/ldns/dnssec_zone.c index 1f7274bbc96..df71a23c7ed 100644 --- a/usr.sbin/unbound/ldns/dnssec_zone.c +++ b/usr.sbin/unbound/ldns/dnssec_zone.c @@ -708,6 +708,7 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/ case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/ + status = LDNS_STATUS_OK; break; case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */ @@ -721,38 +722,42 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, if (ldns_rr_list_rr_count(todo_nsec3s) > 0) { (void) ldns_dnssec_zone_add_empty_nonterminals(newzone); - for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3s); i++) { + for (i = 0; status == LDNS_STATUS_OK && + i < ldns_rr_list_rr_count(todo_nsec3s); i++) { cur_rr = ldns_rr_list_rr(todo_nsec3s, i); status = ldns_dnssec_zone_add_rr(newzone, cur_rr); } - for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){ + for (i = 0; status == LDNS_STATUS_OK && + i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); + i++){ cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); status = ldns_dnssec_zone_add_rr(newzone, cur_rr); } } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) { - for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){ + for (i = 0; status == LDNS_STATUS_OK && + i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); + i++){ cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); status = ldns_dnssec_zone_add_rr(newzone, cur_rr); } } - ldns_rr_list_free(todo_nsec3_rrsigs); - ldns_rr_list_free(todo_nsec3s); - if (z) { *z = newzone; + newzone = NULL; } else { ldns_dnssec_zone_free(newzone); } - return LDNS_STATUS_OK; - error: #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP if (zone) { ldns_zone_free(zone); } #endif + ldns_rr_list_free(todo_nsec3_rrsigs); + ldns_rr_list_free(todo_nsec3s); + if (my_origin) { ldns_rdf_deep_free(my_origin); } @@ -822,7 +827,6 @@ ldns_dname_compare_v(const void *a, const void *b) { return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b); } -#ifdef HAVE_SSL ldns_rbnode_t * ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) { @@ -912,7 +916,6 @@ ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) return result; } -#endif /* HAVE_SSL */ void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, @@ -1009,7 +1012,9 @@ ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone) if (next_node == LDNS_RBTREE_NULL) { next_node = ldns_rbtree_first(zone->names); } - + if (! cur_node->data || ! next_node->data) { + return LDNS_STATUS_ERR; + } cur_name = ((ldns_dnssec_name *)cur_node->data)->name; next_name = ((ldns_dnssec_name *)next_node->data)->name; cur_label_count = ldns_dname_label_count(cur_name); diff --git a/usr.sbin/unbound/ldns/doc/doxyparse.pl b/usr.sbin/unbound/ldns/doc/doxyparse.pl index 526c617101b..96a1732f9ed 100755 --- a/usr.sbin/unbound/ldns/doc/doxyparse.pl +++ b/usr.sbin/unbound/ldns/doc/doxyparse.pl @@ -87,7 +87,7 @@ if (defined $options{'m'}) { # 0 - somewhere in the file # 1 - in a doxygen par -# 2 - after doxygen, except funcion +# 2 - after doxygen, expect function # create our pwd mkdir "doc"; @@ -126,7 +126,14 @@ while($i < $max) { } if ($cur_line =~ /\*\// and $state == 1) { #print "END Comment seen!\n"; - $state = 2; + if ($description =~ /^\\\\file/mg) { + # Doxygen text for the file, do not expect + # a function coming. + # + $state = 0; + } else { + $state = 2; + } $i++; next; } @@ -184,6 +191,14 @@ while($i < $max) { $description =~ s/\\param\[out\][ \t]*([\*\w]+)[ \t]+/.br\n\\fB$1\\fR: /g; $description =~ s/\\return[ \t]*/.br\nReturns /g; + # Delete leading spaces to prevent manpages to be ascii format- + # ted and enable justification of text. + # + $description =~ s/^[ \t]*//mg; + + # Prevent hyphening of all caps and underscore words + $description =~ s/\b([A-Z_]+)\b/\\%$1/g; + $description{$key} = $description; $api{$key} = $api; $return{$key} = $return; diff --git a/usr.sbin/unbound/ldns/doc/function_manpages b/usr.sbin/unbound/ldns/doc/function_manpages index 15706fada57..ce05899b7cf 100644 --- a/usr.sbin/unbound/ldns/doc/function_manpages +++ b/usr.sbin/unbound/ldns/doc/function_manpages @@ -39,6 +39,11 @@ ldns_dname_compare, ldns_dname_interval | ldns_dname_is_subdomain | ldns_dname ldns_dname | ldns_dname_left_chop, ldns_dname_label_count, ldns_dname2canonical, ldns_dname_cat, ldns_dname_cat_clone, ldns_dname_new, ldns_dname_new_frm_str, ldns_dname_new_frm_data, ldns_dname_is_subdomain, ldns_dname_str_absolute, ldns_dname_label, ldns_dname_compare, ldns_dname_interval ### /dname.h +### dane.h +ldns_dane_create_tlsa_owner, ldns_dane_cert2rdf, ldns_dane_select_certificate, ldns_dane_create_tlsa_rr | ldns_dane_verify, ldns_dane_verify_rr +ldns_dane_verify, ldns_dane_verify_rr | ldns_dane_create_tlsa_owner, ldns_dane_cert2rdf, ldns_dane_select_certificate, ldns_dane_create_tlsa_rr +### /dane.h + ### rdata.h ldns_rdf, ldns_rdf_type | ldns_rdf_set_size, ldns_rdf_set_type, ldns_rdf_set_data, ldns_rdf_size, ldns_rdf_get_type, ldns_rdf_data, ldns_rdf_compare, ldns_rdf_new, ldns_rdf_clone, ldns_rdf_new_frm_data, ldns_rdf_new_frm_str, ldns_rdf_new_frm_fp, ldns_rdf_free, ldns_rdf_deep_free, ldns_rdf_print, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t ldns_rdf_set_size, ldns_rdf_set_type, ldns_rdf_set_data | ldns_rdf diff --git a/usr.sbin/unbound/ldns/drill/Makefile.in b/usr.sbin/unbound/ldns/drill/Makefile.in index 5730f0809c7..ac555fa1e57 100644 --- a/usr.sbin/unbound/ldns/drill/Makefile.in +++ b/usr.sbin/unbound/ldns/drill/Makefile.in @@ -9,6 +9,7 @@ exec_prefix = @exec_prefix@ bindir = @bindir@ mandir = @mandir@ includedir = @includedir@ +datarootdir = @datarootdir@ CC = @CC@ CFLAGS = -I. @CFLAGS@ @@ -77,7 +78,6 @@ docclean: distclean: clean docclean rm -f config.h - rm -f drill.h realclean: clean docclean rm -f tags @@ -88,9 +88,9 @@ realclean: clean docclean rm -rf autom4te.cache rm -f config.h rm -f config.h.in - rm -f drill.h rm -f configure rm -f Makefile + rm -f drill.1 rm -f aclocal.m4 doc: @@ -99,7 +99,7 @@ doc: install: all $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) drill $(DESTDIR)$(bindir)/drill - $(INSTALL) -m 644 $(srcdir)/drill.1 $(DESTDIR)$(mandir)/man1/drill.1 + $(INSTALL) -m 644 drill.1 $(DESTDIR)$(mandir)/man1/drill.1 uninstall: @echo @@ -116,4 +116,4 @@ lint: done confclean: clean - rm -rf config.log config.status config.h Makefile + rm -rf config.log config.status config.h Makefile drill.1 diff --git a/usr.sbin/unbound/ldns/drill/chasetrace.c b/usr.sbin/unbound/ldns/drill/chasetrace.c index c2bbfd00901..0a37ff3017e 100644 --- a/usr.sbin/unbound/ldns/drill/chasetrace.c +++ b/usr.sbin/unbound/ldns/drill/chasetrace.c @@ -45,7 +45,15 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, p = ldns_pkt_new(); res = ldns_resolver_new(); - if (!p || !res) { + if (!p) { + if (res) { + ldns_resolver_free(res); + } + error("Memory allocation failed"); + return NULL; + } + if (!res) { + ldns_pkt_free(p); error("Memory allocation failed"); return NULL; } @@ -73,6 +81,8 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status)); ldns_rr_list_print(stdout, global_dns_root); + ldns_resolver_free(res); + ldns_pkt_free(p); return NULL; } @@ -118,7 +128,7 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, drill_pkt_print_footer(stdout, local_res, p); /* remove the old nameserver from the resolver */ - while((pop = ldns_resolver_pop_nameserver(res))) { /* do it */ } + while(ldns_resolver_pop_nameserver(res)) { /* do it */ } /* also check for new_nss emptyness */ diff --git a/usr.sbin/unbound/ldns/drill/config.h.in b/usr.sbin/unbound/ldns/drill/config.h.in index 9b2a282a8e9..75448a07ecc 100644 --- a/usr.sbin/unbound/ldns/drill/config.h.in +++ b/usr.sbin/unbound/ldns/drill/config.h.in @@ -111,6 +111,9 @@ /* Define to 1 if you have the <ws2tcpip.h> header file. */ #undef HAVE_WS2TCPIP_H +/* Default trust anchor file */ +#undef LDNS_TRUST_ANCHOR_FILE + /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT diff --git a/usr.sbin/unbound/ldns/drill/configure b/usr.sbin/unbound/ldns/drill/configure index 95bc4356072..6a4487d9a97 100755 --- a/usr.sbin/unbound/ldns/drill/configure +++ b/usr.sbin/unbound/ldns/drill/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for ldns 1.6.13. +# Generated by GNU Autoconf 2.68 for ldns 1.6.16. # # Report bugs to <libdns@nlnetlabs.nl>. # @@ -560,8 +560,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ldns' PACKAGE_TARNAME='libdns' -PACKAGE_VERSION='1.6.13' -PACKAGE_STRING='ldns 1.6.13' +PACKAGE_VERSION='1.6.16' +PACKAGE_STRING='ldns 1.6.16' PACKAGE_BUGREPORT='libdns@nlnetlabs.nl' PACKAGE_URL='' @@ -604,6 +604,7 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS +LDNS_TRUST_ANCHOR_FILE LDNSDIR LIBS_STC RUNTIME_PATH @@ -664,6 +665,7 @@ enable_option_checking enable_rpath with_ssl with_ldns +with_trust_anchor ' ac_precious_vars='build_alias host_alias @@ -1216,7 +1218,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures ldns 1.6.13 to adapt to many kinds of systems. +\`configure' configures ldns 1.6.16 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1277,7 +1279,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ldns 1.6.13:";; + short | recursive ) echo "Configuration of ldns 1.6.16:";; esac cat <<\_ACEOF @@ -1296,6 +1298,9 @@ Optional Packages: --with-ldns=PATH specify prefix of path of ldns library to use + --with-trust-anchor=KEYFILE + Default location of the trust anchor file. + [default=SYSCONFDIR/unbound/root.key] Some influential environment variables: CC C compiler command @@ -1373,7 +1378,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ldns configure 1.6.13 +ldns configure 1.6.16 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1796,7 +1801,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by ldns $as_me 1.6.13, which was +It was created by ldns $as_me 1.6.16, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -5379,16 +5384,46 @@ else as_fn_error $? "Can't find ldns library" "$LINENO" 5 +fi fi + + + +# Check whether --with-trust-anchor was given. +if test "${with_trust_anchor+set}" = set; then : + withval=$with_trust_anchor; + LDNS_TRUST_ANCHOR_FILE="$withval" + +else + + if test "x$LDNS_TRUST_ANCHOR_FILE" = "x"; then + if test "x$sysconfdir" = 'x${prefix}/etc' ; then + if test "x$prefix" = 'xNONE' ; then + LDNS_TRUST_ANCHOR_FILE="/etc/unbound/root.key" + else + LDNS_TRUST_ANCHOR_FILE="${prefix}/etc/unbound/root.key" + fi + else + LDNS_TRUST_ANCHOR_FILE="${sysconfdir}/unbound/root.key" + fi + fi + fi +cat >>confdefs.h <<_ACEOF +#define LDNS_TRUST_ANCHOR_FILE "$LDNS_TRUST_ANCHOR_FILE" +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: Default trust anchor: $LDNS_TRUST_ANCHOR_FILE" >&5 +$as_echo "$as_me: Default trust anchor: $LDNS_TRUST_ANCHOR_FILE" >&6;} -ac_config_files="$ac_config_files Makefile" +ac_config_files="$ac_config_files Makefile drill.1" ac_config_headers="$ac_config_headers config.h" @@ -5910,7 +5945,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by ldns $as_me 1.6.13, which was +This file was extended by ldns $as_me 1.6.16, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5972,7 +6007,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -ldns config.status 1.6.13 +ldns config.status 1.6.16 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" @@ -6094,6 +6129,7 @@ for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "drill.1") CONFIG_FILES="$CONFIG_FILES drill.1" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; diff --git a/usr.sbin/unbound/ldns/drill/configure.ac b/usr.sbin/unbound/ldns/drill/configure.ac index afd5c63803b..17d7541c027 100644 --- a/usr.sbin/unbound/ldns/drill/configure.ac +++ b/usr.sbin/unbound/ldns/drill/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.56) -AC_INIT(ldns, 1.6.13, libdns@nlnetlabs.nl,libdns) +AC_INIT(ldns, 1.6.16, libdns@nlnetlabs.nl,libdns) AC_CONFIG_SRCDIR([drill.c]) sinclude(../acx_nlnetlabs.m4) @@ -170,13 +170,33 @@ if test -f $ldns_dev_dir/ldns/util.h && \ else AC_MSG_RESULT([no]) AC_CHECK_LIB(ldns, ldns_rr_new, , [ - AC_MSG_ERROR([Can't find ldns library]) + AC_MSG_ERROR([Can't find ldns library])dnl ' ] ) fi AC_SUBST(LDNSDIR) +AC_ARG_WITH(trust-anchor, AC_HELP_STRING([--with-trust-anchor=KEYFILE], +[Default location of the trust anchor file. [default=SYSCONFDIR/unbound/root.key]]), [ + LDNS_TRUST_ANCHOR_FILE="$withval" +],[ + if test "x$LDNS_TRUST_ANCHOR_FILE" = "x"; then + if test "x$sysconfdir" = 'x${prefix}/etc' ; then + if test "x$prefix" = 'xNONE' ; then + LDNS_TRUST_ANCHOR_FILE="/etc/unbound/root.key" + else + LDNS_TRUST_ANCHOR_FILE="${prefix}/etc/unbound/root.key" + fi + else + LDNS_TRUST_ANCHOR_FILE="${sysconfdir}/unbound/root.key" + fi + fi +]) +AC_DEFINE_UNQUOTED([LDNS_TRUST_ANCHOR_FILE], ["$LDNS_TRUST_ANCHOR_FILE"], [Default trust anchor file]) +AC_SUBST(LDNS_TRUST_ANCHOR_FILE) +AC_MSG_NOTICE([Default trust anchor: $LDNS_TRUST_ANCHOR_FILE]) + AH_BOTTOM([ #include <stdio.h> @@ -254,6 +274,6 @@ extern int optind, opterr; #endif ]) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile drill.1]) AC_CONFIG_HEADER([config.h]) AC_OUTPUT diff --git a/usr.sbin/unbound/ldns/drill/dnssec.c b/usr.sbin/unbound/ldns/drill/dnssec.c index b72ffb95dad..b8074be03cc 100644 --- a/usr.sbin/unbound/ldns/drill/dnssec.c +++ b/usr.sbin/unbound/ldns/drill/dnssec.c @@ -22,12 +22,10 @@ get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c) p = ldns_pkt_new(); found = NULL; - if (ldns_resolver_send(&p, res, zname, t, c, 0) != LDNS_STATUS_OK) { - /* oops */ - return NULL; - } else { + if (ldns_resolver_send(&p, res, zname, t, c, 0) == LDNS_STATUS_OK) { found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION); } + ldns_pkt_free(p); return found; } @@ -36,6 +34,7 @@ drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p) { ldns_rr_list *new_nss; ldns_rr_list *hostnames; + char *answerfrom_str; if (verbosity < 5) { return; @@ -46,8 +45,7 @@ drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p) new_nss = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); ldns_rr_list_print(fd, new_nss); - - /* new_nss can be empty.... */ + ldns_rr_list_deep_free(new_nss); fprintf(fd, ";; Received %d bytes from %s#%d(", (int) ldns_pkt_size(p), @@ -59,7 +57,11 @@ drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p) ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0)); ldns_rr_list_deep_free(hostnames); } else { - fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p))); + answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p)); + if (answerfrom_str) { + fprintf(fd, "%s", answerfrom_str); + LDNS_FREE(answerfrom_str); + } } fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p)); } @@ -68,6 +70,7 @@ void drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p) { ldns_rr_list *hostnames; + char *answerfrom_str; if (verbosity < 5) { return; @@ -85,7 +88,11 @@ drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p) ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0)); ldns_rr_list_deep_free(hostnames); } else { - fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p))); + answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p)); + if (answerfrom_str) { + fprintf(fd, "%s", answerfrom_str); + LDNS_FREE(answerfrom_str); + } } fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p)); } @@ -98,7 +105,6 @@ get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t, ldns_rr_list **rrlist, ldns_rr_list **sig) { ldns_pkt_type pt = LDNS_PACKET_UNKNOWN; - ldns_rr_list *rr = NULL; ldns_rr_list *sigs = NULL; size_t i; @@ -111,36 +117,52 @@ get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t, pt = ldns_pkt_reply_type(p); if (name) { - rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_ANSWER); - if (!rr) { - rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_AUTHORITY); + if (rrlist) { + *rrlist = ldns_pkt_rr_list_by_name_and_type(p, name, t, + LDNS_SECTION_ANSWER); + if (!*rrlist) { + *rrlist = ldns_pkt_rr_list_by_name_and_type( + p, name, t, + LDNS_SECTION_AUTHORITY); + } } - sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG, - LDNS_SECTION_ANSWER); - if (!sigs) { - sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG, - LDNS_SECTION_AUTHORITY); + if (sig) { + sigs = ldns_pkt_rr_list_by_name_and_type(p, name, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANSWER); + if (!sigs) { + sigs = ldns_pkt_rr_list_by_name_and_type( + p, name, LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_AUTHORITY); + } } } else { - /* A DS-referral - get the DS records if they are there */ - rr = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_AUTHORITY); - sigs = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG, - LDNS_SECTION_AUTHORITY); + /* A DS-referral - get the DS records if they are there */ + if (rrlist) { + *rrlist = ldns_pkt_rr_list_by_type( + p, t, LDNS_SECTION_AUTHORITY); + } + if (sig) { + sigs = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_AUTHORITY); + } } if (sig) { *sig = ldns_rr_list_new(); for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) { /* only add the sigs that cover this type */ - if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(ldns_rr_list_rr(sigs, i))) == - t) { - ldns_rr_list_push_rr(*sig, ldns_rr_clone(ldns_rr_list_rr(sigs, i))); + if (t == ldns_rdf2rr_type(ldns_rr_rrsig_typecovered( + ldns_rr_list_rr(sigs, i)))) { + + ldns_rr_list_push_rr(*sig, + ldns_rr_clone( + ldns_rr_list_rr( + sigs, i))); } } } ldns_rr_list_deep_free(sigs); - if (rrlist) { - *rrlist = rr; - } if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) { return pt; @@ -153,6 +175,7 @@ get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t, ldns_status ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs) { +#ifdef HAVE_SSL uint16_t nsec_i; ldns_rr_list *nsecs; @@ -216,12 +239,28 @@ ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_lis ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION); ldns_rr* q = ldns_rr_new(); ldns_rr* match = NULL; - if(!sigs) return LDNS_STATUS_MEM_ERR; - if(!q) return LDNS_STATUS_MEM_ERR; + + if(!sigs) { + if (q) { + ldns_rr_free(q); + } + ldns_rr_list_deep_free(nsecs); + return LDNS_STATUS_MEM_ERR; + } + if(!q) { + ldns_rr_list_deep_free(nsecs); + ldns_rr_list_deep_free(sigs); + return LDNS_STATUS_MEM_ERR; + } ldns_rr_set_question(q, 1); ldns_rr_set_ttl(q, 0); ldns_rr_set_owner(q, ldns_rdf_clone(name)); - if(!ldns_rr_owner(q)) return LDNS_STATUS_MEM_ERR; + if(!ldns_rr_owner(q)) { + ldns_rr_free(q); + ldns_rr_list_deep_free(sigs); + ldns_rr_list_deep_free(nsecs); + return LDNS_STATUS_MEM_ERR; + } ldns_rr_set_type(q, type); /* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */ @@ -234,6 +273,14 @@ ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_lis ldns_rr_list_deep_free(sigs); } return result; +#else + (void)pkt; + (void)name; + (void)type; + (void)nsec_rrs; + (void)nsec_rr_sigs; + return LDNS_STATUS_ERR; +#endif /* HAVE_SSL */ } /* NSEC3 draft -07 */ diff --git a/usr.sbin/unbound/ldns/drill/drill.1.in b/usr.sbin/unbound/ldns/drill/drill.1.in new file mode 100644 index 00000000000..15b15a42533 --- /dev/null +++ b/usr.sbin/unbound/ldns/drill/drill.1.in @@ -0,0 +1,242 @@ +.\" @(#)drill.1 1.7.0 14-Jul-2004 OF; +.TH drill 1 "28 May 2006" +.SH NAME +drill \- get (debug) information out of DNS(SEC) +.SH SYNOPSIS +.B drill +[ +.IR OPTIONS +] +.IR name +[ +.IR @server +] +[ +.IR type +] +[ +.IR class +] + +.SH DESCRIPTION +\fBdrill\fR is a tool to designed to get all sorts of information out of the +DNS. It is specificly designed to be used with DNSSEC. +.PP +The name \fBdrill\fR is a pun on \fBdig\fR. With \fBdrill\fR you should be able +get even more information than with \fBdig\fR. +.PP +If no arguments are given class defaults to 'IN' and type to 'A'. The +server(s) specified in /etc/resolv.conf are used to query against. + +.PP +\fIname\fR +Ask for this name. + +.PP +\fI@server\fR +Send to query to this server. If not specified use the nameservers from +\fI/etc/resolv.conf\fR. + +.PP +\fItype\fR +Ask for this RR type. If type is not given on the command line it defaults +to 'A'. Except when doing to reverse lookup when it defaults to 'PTR'. + +.PP +\fIclass\fR +Use this class when querying. + +.SH SAMPLE USAGE +\fBdrill mx miek.nl\fR +Show the MX records of the domain miek.nl + +.TP +\fBdrill -S jelte.nlnetlabs.nl\fR +Chase any signatures in the jelte.nlnetlab.nl domain. This option is +only available when ldns has been compiled with openssl-support. + +.TP +\fBdrill -TD www.example.com\fR +Do a DNSSEC (-D) trace (-T) from the rootservers down to www.example.com. +This option only works when ldns has been compiled with openssl support. + +.TP +\fBdrill -s dnskey jelte.nlnetlabs.nl\fR +Show the DNSKEY record(s) for jelte.nlnetlabs.nl. For each found DNSKEY +record also print the DS record. + +.SH OPTIONS + +.TP +\fB\-D +Enable DNSSEC in the query. When querying for DNSSEC types (DNSKEY, RRSIG, +DS and NSEC) this is \fInot\fR automaticly enabled. + +.TP +\fB\-T +Trace \fIname\fR from the root down. When using this option the @server and +the type arguments are not used. + +.TP +\fB\-S +Chase the signature(s) of 'name' to a known key or as high up in +the tree as possible. + +.TP +\fB\-V \fIlevel\fR +Be more verbose. Set level to 5 to see the actual query that is sent. + +.TP +\fB\-Q +Quiet mode, this overrules -V. + +.TP +\fB\-f \fIfile\fR +Read the query from a file. The query must be dumped with -w. + +.TP +\fB\-i \fIfile\fR +read the answer from the file instead from the network. This aids +in debugging and can be used to check if a query on disk is valid. +If the file contains binary data it is assumed to be a query in +network order. + +.TP +\fB\-w \fIfile\fR +Write an answer packet to file. + +.TP +\fB\-q \fIfile\fR +Write the query packet to file. + +.TP +\fB\-v +Show drill's version. + +.TP +\fB\-h +Show a short help message. + +.SS QUERY OPTIONS + +.TP +\fB\-4 +Stay on ip4. Only send queries to ip4 enabled nameservers. + +.TP +\fB\-6 +Stay on ip6. Only send queries to ip6 enabled nameservers. + +.TP +\fB\-a +Use the resolver structure's fallback mechanism if the answer +is truncated (TC=1). If a truncated packet is received and this +option is set, drill will first send a new query with EDNS0 +buffer size 4096. + +If the EDNS0 buffer size was already set to 512+ bytes, or the +above retry also results in a truncated answer, the resolver +structure will fall back to TCP. + +.TP +\fB\-b \fIsize\fR +Use size as the buffer size in the EDNS0 pseudo RR. + +.TP +\fB\-c \fIfile\fR +Use file instead of /etc/resolv.conf for nameserver configuration. + +.TP +\fB\-d \fIdomain\fR +When tracing (-T), start from this domain instead of the root. + +.TP +\fB\-t +Use TCP/IP when querying a server + +.TP +\fB\-k \fIkeyfile\fR +Use this file to read a (trusted) key from. When this options is +given \fBdrill\fR tries to validate the current answer with this +key. No chasing is done. When \fBdrill\fR is doing a secure trace, this +key will be used as trust anchor. Can contain a DNSKEY or a DS record. + +Alternatively, when DNSSEC enabled tracing (\fB-TD\fR) or signature +chasing (\fB-S\fR), if \fB-k\fR is not specified, and a default trust anchor +(@LDNS_TRUST_ANCHOR_FILE@) exists and contains a valid DNSKEY or DS record, +it will be used as the trust anchor. + +.TP +\fB\-o \fImnemonic\fR +Use this option to set or unset specific header bits. A bit is +set by using the bit mnemonic in CAPITAL letters. A bit is unset when +the mnemonic is given in lowercase. The following mnemonics are +understood by \fBdrill\fR: + + QR, qr: set, unset QueRy (default: on) + AA, aa: set, unset Authoritative Answer (default: off) + TC, tc: set, unset TrunCated (default: off) + RD, rd: set, unset Recursion Desired (default: on) + CD, cd: set, unset Checking Disabled (default: off) + RA, ra: set, unset Recursion Available (default: off) + AD, ad: set, unset Authenticated Data (default: off) + +Thus: \fB-o CD\fR, will enable Checking Disabled, which instructs the +cache to not validate the answers it gives out. + +.TP +\fB\-p \fIport\fR +Use this port instead of the default of 53. + +.TP +\fB\-r \fIfile\fR +When tracing (-T), use file as a root servers hint file. + +.TP +\fB\-s +When encountering a DNSKEY print the equivalent DS also. + +.TP +\fB\-u +Use UDP when querying a server. This is the default. + +.TP +\fB\-w \fIfile\fR +write the answer to a file. The file will contain a hexadecimal dump +of the query. This can be used in conjunction with -f. + +.TP +\fB\-x +Do a reverse loopup. The type argument is not used, it is preset to PTR. + +.TP +\fB\-y \fI<name:key[:algo]>\fR +specify named base64 tsig key, and optional an algorithm (defaults to hmac-md5.sig-alg.reg.int) + +.TP +\fB\-z \fR +don't randomize the nameserver list before sending queries. + +.SH "FILES" +.TP +@LDNS_TRUST_ANCHOR_FILE@ +The file from which trusted keys are loaded when no \fB-k\fR option is given. +.SH "SEE ALSO" +.LP +unbound-anchor(8) + +.SH AUTHOR +Jelte Jansen and Miek Gieben. Both of NLnet Labs. + +.SH REPORTING BUGS +Report bugs to <ldns-team@nlnetlabs.nl>. + +.SH BUGS + +.SH COPYRIGHT +Copyright (c) 2004-2008 NLnet Labs. +Licensed under the revised BSD license. There is NO warranty; not even for MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. + +.SH SEE ALSO +\fBdig\fR(1), \fIRFC403{3,4,5}\fR. diff --git a/usr.sbin/unbound/ldns/drill/drill.c b/usr.sbin/unbound/ldns/drill/drill.c index 2f779634d8e..574c8b98c85 100644 --- a/usr.sbin/unbound/ldns/drill/drill.c +++ b/usr.sbin/unbound/ldns/drill/drill.c @@ -47,19 +47,25 @@ usage(FILE *stream, const char *progname) fprintf(stream, "\t-6\t\tstay on ip6\n"); fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n"); fprintf(stream, "\t-b <bufsize>\tuse <bufsize> as the buffer size (defaults to 512 b)\n"); - fprintf(stream, "\t-c <file>\t\tuse file for rescursive nameserver configuration (/etc/resolv.conf)\n"); - fprintf(stream, "\t-k <file>\tspecify a file that contains a trusted DNSSEC key (DNSKEY|DS) [**]\n"); - fprintf(stream, "\t\t\tused to verify any signatures in the current answer\n"); - fprintf(stream, "\t-o <mnemonic>\tset flags to: [QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n"); + fprintf(stream, "\t-c <file>\tuse file for rescursive nameserver configuration" + "\n\t\t\t(/etc/resolv.conf)\n"); + fprintf(stream, "\t-k <file>\tspecify a file that contains a trusted DNSSEC key [**]\n"); + fprintf(stream, "\t\t\tUsed to verify any signatures in the current answer.\n"); + fprintf(stream, "\t\t\tWhen DNSSEC enabled tracing (-TD) or signature\n" + "\t\t\tchasing (-S) and no key files are given, keys are read\n" + "\t\t\tfrom: %s\n", + LDNS_TRUST_ANCHOR_FILE); + fprintf(stream, "\t-o <mnemonic>\tset flags to:" + "\n\t\t\t[QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n"); fprintf(stream, "\t\t\tlowercase: unset bit, uppercase: set bit\n"); fprintf(stream, "\t-p <port>\tuse <port> as remote port number\n"); fprintf(stream, "\t-s\t\tshow the DS RR for each key in a packet\n"); fprintf(stream, "\t-u\t\tsend the query with udp (the default)\n"); fprintf(stream, "\t-x\t\tdo a reverse lookup\n"); fprintf(stream, "\twhen doing a secure trace:\n"); - fprintf(stream, "\t-r <file>\t\tuse file as root servers hint file\n"); + fprintf(stream, "\t-r <file>\tuse file as root servers hint file\n"); fprintf(stream, "\t-t\t\tsend the query with tcp (connected)\n"); - fprintf(stream, "\t-d <domain>\t\tuse domain as the start point for the trace\n"); + fprintf(stream, "\t-d <domain>\tuse domain as the start point for the trace\n"); fprintf(stream, "\t-y <name:key[:algo]>\tspecify named base64 tsig key, and optional an\n\t\t\talgorithm (defaults to hmac-md5.sig-alg.reg.int)\n"); fprintf(stream, "\t-z\t\tdon't randomize the nameservers before use\n"); fprintf(stream, "\n [*] = enables/implies DNSSEC\n"); @@ -272,7 +278,8 @@ main(int argc, char *argv[]) qusevc = true; break; case 'k': - status = read_key_file(optarg, key_list); + status = read_key_file(optarg, + key_list, false); if (status != LDNS_STATUS_OK) { error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status)); } @@ -397,6 +404,15 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; + if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) && + ldns_rr_list_rr_count(key_list) == 0) { + + (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true); + } + if (ldns_rr_list_rr_count(key_list) > 0) { + printf(";; Number of trusted keys: %d\n", + (int) ldns_rr_list_rr_count(key_list)); + } /* do a secure trace when requested */ if (PURPOSE == DRILL_TRACE && qdnssec) { #ifdef HAVE_SSL diff --git a/usr.sbin/unbound/ldns/drill/drill.h b/usr.sbin/unbound/ldns/drill/drill.h index 69b0396b217..0746fe7bff2 100644 --- a/usr.sbin/unbound/ldns/drill/drill.h +++ b/usr.sbin/unbound/ldns/drill/drill.h @@ -85,7 +85,6 @@ ldns_status ldns_verify_denial(ldns_pkt *pkt, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs); -ldns_status read_key_file(const char *filename, ldns_rr_list *key_list); ldns_pkt *read_hex_pkt(char *filename); ldns_buffer *read_hex_buffer(char *filename); void init_root(void); diff --git a/usr.sbin/unbound/ldns/drill/drill_util.c b/usr.sbin/unbound/ldns/drill/drill_util.c index 98d88e7942d..db0433e77e1 100644 --- a/usr.sbin/unbound/ldns/drill/drill_util.c +++ b/usr.sbin/unbound/ldns/drill/drill_util.c @@ -13,14 +13,14 @@ #include <errno.h> -static size_t +static int read_line(FILE *input, char *line, size_t len) { - size_t i; + int i; char c; - for (i = 0; i < len-1; i++) { - c = getc(input); + for (i = 0; i < (int)len-1; i++) { + c = (char)getc(input); if (c == EOF) { return -1; } else if (c != '\n') { @@ -35,20 +35,22 @@ read_line(FILE *input, char *line, size_t len) /* key_list must be initialized with ldns_rr_list_new() */ ldns_status -read_key_file(const char *filename, ldns_rr_list *key_list) +read_key_file(const char *filename, ldns_rr_list *key_list, bool silently) { int line_len = 0; int line_nr = 0; int key_count = 0; - char line[LDNS_MAX_PACKETLEN]; + char line[LDNS_MAX_LINELEN]; ldns_status status; FILE *input_file; ldns_rr *rr; input_file = fopen(filename, "r"); if (!input_file) { - fprintf(stderr, "Error opening %s: %s\n", - filename, strerror(errno)); + if (! silently) { + fprintf(stderr, "Error opening %s: %s\n", + filename, strerror(errno)); + } return LDNS_STATUS_ERR; } while (line_len >= 0) { @@ -57,10 +59,13 @@ read_key_file(const char *filename, ldns_rr_list *key_list) if (line_len > 0 && line[0] != ';') { status = ldns_rr_new_frm_str(&rr, line, 0, NULL, NULL); if (status != LDNS_STATUS_OK) { - fprintf(stderr, - "Error parsing DNSKEY RR in line %d: %s\n", - line_nr, - ldns_get_errorstr_by_id(status)); + if (! silently) { + fprintf(stderr, + "Error parsing DNSKEY RR " + "in line %d: %s\n", line_nr, + ldns_get_errorstr_by_id(status) + ); + } } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY || ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS) { ldns_rr_list_push_rr(key_list, rr); @@ -70,7 +75,7 @@ read_key_file(const char *filename, ldns_rr_list *key_list) } } } - printf(";; Number of trusted keys: %d\n", key_count); + fclose(input_file); if (key_count > 0) { return LDNS_STATUS_OK; } else { @@ -132,6 +137,7 @@ print_ds_of_keys(ldns_pkt *p) ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA256); local_print_ds(stdout, "; sha256: ", ds); } + ldns_rr_list_deep_free(keys); } } diff --git a/usr.sbin/unbound/ldns/drill/drill_util.h b/usr.sbin/unbound/ldns/drill/drill_util.h index de7844118db..42b3f32b25d 100644 --- a/usr.sbin/unbound/ldns/drill/drill_util.h +++ b/usr.sbin/unbound/ldns/drill/drill_util.h @@ -12,6 +12,13 @@ #define _DRILL_UTIL_H_ #include <ldns/ldns.h> + +/** + * Read keys from filename and append to key_list. + */ +ldns_status read_key_file(const char *filename, ldns_rr_list *key_list, + bool silently); + /** * return a address rdf, either A or AAAA * NULL if anything goes wrong diff --git a/usr.sbin/unbound/ldns/drill/securetrace.c b/usr.sbin/unbound/ldns/drill/securetrace.c index 029ebf51d6f..c6e7e588409 100644 --- a/usr.sbin/unbound/ldns/drill/securetrace.c +++ b/usr.sbin/unbound/ldns/drill/securetrace.c @@ -231,7 +231,8 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, if (status != LDNS_STATUS_OK) { printf("ERRRRR: %s\n", ldns_get_errorstr_by_id(status)); ldns_rr_list_print(stdout, global_dns_root); - return status; + result = status; + goto done; } labels_count = ldns_dname_label_count(name); if (start_name) { @@ -392,7 +393,6 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, printf(";; There is an empty non-terminal here, continue\n"); continue; } - goto done; } if (ldns_resolver_nameserver_count(res) == 0) { diff --git a/usr.sbin/unbound/ldns/drill/work.c b/usr.sbin/unbound/ldns/drill/work.c index 3a9cb5855d7..653145fe522 100644 --- a/usr.sbin/unbound/ldns/drill/work.c +++ b/usr.sbin/unbound/ldns/drill/work.c @@ -122,11 +122,6 @@ packetbuffromfile(char *filename, uint8_t *wire) hexbuf[hexbufpos] = (uint8_t) c; hexbufpos++; break; - default: - warning("unknown state while reading %s", filename); - xfree(hexbuf); - return 0; - break; } c = fgetc(fp); } @@ -178,20 +173,7 @@ read_hex_buffer(char *filename) size_t wiresize; ldns_buffer *result_buffer = NULL; - FILE *fp = NULL; - - if (strncmp(filename, "-", 2) != 0) { - fp = fopen(filename, "r"); - } else { - fp = stdin; - } - - if (fp == NULL) { - perror(""); - warning("Unable to open %s", filename); - return NULL; - } - + wire = xmalloc(LDNS_MAX_PACKETLEN); wiresize = packetbuffromfile(filename, wire); @@ -199,8 +181,8 @@ read_hex_buffer(char *filename) result_buffer = LDNS_MALLOC(ldns_buffer); ldns_buffer_new_frm_data(result_buffer, wire, wiresize); ldns_buffer_set_position(result_buffer, ldns_buffer_capacity(result_buffer)); - xfree(wire); + return result_buffer; } @@ -236,7 +218,7 @@ read_hex_pkt(char *filename) void dump_hex(const ldns_pkt *pkt, const char *filename) { - uint8_t *wire; + uint8_t *wire = NULL; size_t size, i; FILE *fp; ldns_status status; @@ -252,6 +234,7 @@ dump_hex(const ldns_pkt *pkt, const char *filename) if (status != LDNS_STATUS_OK) { error("Unable to convert packet: error code %u", status); + LDNS_FREE(wire); return; } @@ -273,4 +256,5 @@ dump_hex(const ldns_pkt *pkt, const char *filename) } fprintf(fp, "\n"); fclose(fp); + LDNS_FREE(wire); } diff --git a/usr.sbin/unbound/ldns/error.c b/usr.sbin/unbound/ldns/error.c index cf6788ffb36..2fc63e9b099 100644 --- a/usr.sbin/unbound/ldns/error.c +++ b/usr.sbin/unbound/ldns/error.c @@ -95,6 +95,35 @@ ldns_lookup_table ldns_error_str[] = { "DNSSEC signature will expire too soon" }, { LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN, "DNSSEC signature not incepted long enough" }, + { LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE, + "Unknown TLSA Certificate Usage" }, + { LDNS_STATUS_DANE_UNKNOWN_SELECTOR, "Unknown TLSA Selector" }, + { LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE, + "Unknown TLSA Matching Type" }, + { LDNS_STATUS_DANE_UNKNOWN_PROTOCOL, + "Unknown protocol. Only IPv4 and IPv6 are understood" }, + { LDNS_STATUS_DANE_UNKNOWN_TRANSPORT, + "Unknown transport. Should be one of {tcp, udp, sctp}" }, + { LDNS_STATUS_DANE_MISSING_EXTRA_CERTS, /* Trust anchor assertion */ + "More than one certificate should be provided" }, + { LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED, /* Trust anchor assertion */ + "Non of the extra certificates is used to sign the first" }, + { LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE, /* Trust anchor assertion */ + "The offset was out of range" }, + { LDNS_STATUS_DANE_INSECURE, /* Unused by library */ + "The queried resource records were insecure" }, + { LDNS_STATUS_DANE_BOGUS, /* Unused by library */ + "The queried resource records were bogus" }, + { LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH, + "The TLSA record(s) " + "did not match with the server certificate (chain)" }, + { LDNS_STATUS_DANE_NON_CA_CERTIFICATE, + "The certificate was not a CA certificate" }, + { LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE, + "Could not PKIX validate" }, + { LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR, + "The validation path " + "did not end in a self-signed certificate" }, { 0, NULL } }; diff --git a/usr.sbin/unbound/ldns/higher.c b/usr.sbin/unbound/ldns/higher.c index c9eb1731ae2..990fb6afb25 100644 --- a/usr.sbin/unbound/ldns/higher.c +++ b/usr.sbin/unbound/ldns/higher.c @@ -126,6 +126,7 @@ ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class /* add the RD flags, because we want an answer */ pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD); + ldns_rdf_deep_free(name); if (pkt) { /* extract the data we need */ names = ldns_pkt_rr_list_by_type(pkt, diff --git a/usr.sbin/unbound/ldns/host2str.c b/usr.sbin/unbound/ldns/host2str.c index c185e0f04db..521e2468ecd 100644 --- a/usr.sbin/unbound/ldns/host2str.c +++ b/usr.sbin/unbound/ldns/host2str.c @@ -123,6 +123,7 @@ const ldns_output_format *ldns_output_format_onlykeyids = &ldns_output_format_onlykeyids_record; const ldns_output_format *ldns_output_format_default = &ldns_output_format_onlykeyids_record; + const ldns_output_format ldns_output_format_bubblebabble_record = { LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL }; @@ -195,7 +196,7 @@ ldns_pkt_opcode2str(ldns_pkt_opcode opcode) str = NULL; if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -215,7 +216,7 @@ ldns_pkt_rcode2str(ldns_pkt_rcode rcode) str = NULL; if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -236,7 +237,7 @@ ldns_pkt_algorithm2str(ldns_algorithm algorithm) str = NULL; if (ldns_algorithm2buffer_str(buf, algorithm) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -257,7 +258,7 @@ ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm) str = NULL; if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -567,7 +568,7 @@ ldns_rr_type2str(const ldns_rr_type type) str = NULL; if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -603,7 +604,7 @@ ldns_rr_class2str(const ldns_rr_class klass) str = NULL; if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); return str; @@ -1149,8 +1150,9 @@ ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf) break; } } else { + /** This will write mangled RRs */ ldns_buffer_printf(buffer, "(null) "); - res = ldns_buffer_status(buffer); + res = LDNS_STATUS_ERR; } return res; } @@ -1230,7 +1232,33 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output, for (i = 0; i < ldns_rr_rd_count(rr); i++) { /* ldns_rdf2buffer_str handles NULL input fine! */ - status = ldns_rdf2buffer_str(output, ldns_rr_rdf(rr, i)); + if ((fmt->flags & LDNS_FMT_ZEROIZE_RRSIGS) && + (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) && + ((/* inception */ i == 4 && + ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) == + LDNS_RDF_TYPE_TIME) || + (/* expiration */ i == 5 && + ldns_rdf_get_type(ldns_rr_rdf(rr, 5)) == + LDNS_RDF_TYPE_TIME) || + (/* signature */ i == 8 && + ldns_rdf_get_type(ldns_rr_rdf(rr, 8)) == + LDNS_RDF_TYPE_B64))) { + + ldns_buffer_printf(output, "(null)"); + status = ldns_buffer_status(output); + } else if ((fmt->flags & LDNS_FMT_PAD_SOA_SERIAL) && + (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) && + /* serial */ i == 2 && + ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) == + LDNS_RDF_TYPE_INT32) { + ldns_buffer_printf(output, "%10lu", + (unsigned long) ldns_read_uint32( + ldns_rdf_data(ldns_rr_rdf(rr, 2)))); + status = ldns_buffer_status(output); + } else { + status = ldns_rdf2buffer_str(output, + ldns_rr_rdf(rr, i)); + } if(status != LDNS_STATUS_OK) return status; if (i < ldns_rr_rd_count(rr) - 1) { @@ -1633,12 +1661,12 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) { ldns_status status = LDNS_STATUS_OK; unsigned char *bignum; -#ifndef S_SPLINT_S - uint16_t i; -#endif - #ifdef HAVE_SSL +# ifndef S_SPLINT_S + uint16_t i; +# endif /* not used when ssl is not defined */ + /*@unused@*/ ldns_rdf *b64_bignum = NULL; RSA *rsa; @@ -1716,6 +1744,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1727,6 +1756,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1740,6 +1770,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1756,6 +1787,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1772,6 +1804,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1788,6 +1821,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1804,6 +1838,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1820,6 +1855,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1853,6 +1889,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1869,6 +1906,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1885,6 +1923,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1901,6 +1940,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1917,6 +1957,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1960,6 +2001,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1993,9 +2035,6 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } #endif /* HAVE_SSL */ } else { -#ifdef HAVE_SSL - LDNS_FREE(b64_bignum); -#endif LDNS_FREE(bignum); return ldns_buffer_status(output); } @@ -2012,12 +2051,11 @@ error: } /* - * Zero terminate the buffer and fix it to the size of the string. + * Zero terminate the buffer and copy data. */ char * ldns_buffer2str(ldns_buffer *buffer) { - char *tmp_str; char *str; /* check if buffer ends with \0, if not, and @@ -2032,16 +2070,30 @@ ldns_buffer2str(ldns_buffer *buffer) } } - tmp_str = ldns_buffer_export(buffer); - str = LDNS_XMALLOC(char, strlen(tmp_str) + 1); + str = strdup((const char *)ldns_buffer_begin(buffer)); if(!str) { return NULL; } - memcpy(str, tmp_str, strlen(tmp_str) + 1); - return str; } +/* + * Zero terminate the buffer and export data. + */ +char * +ldns_buffer_export2str(ldns_buffer *buffer) +{ + /* Append '\0' as string terminator */ + if (! ldns_buffer_reserve(buffer, 1)) { + return NULL; + } + ldns_buffer_write_u8(buffer, 0); + + /* reallocate memory to the size of the string and export */ + ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer)); + return ldns_buffer_export(buffer); +} + char * ldns_rdf2str(const ldns_rdf *rdf) { @@ -2053,7 +2105,7 @@ ldns_rdf2str(const ldns_rdf *rdf) } if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); } ldns_buffer_free(tmp_buffer); return result; @@ -2071,7 +2123,7 @@ ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr) if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); } ldns_buffer_free(tmp_buffer); return result; @@ -2095,7 +2147,7 @@ ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt) if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); } ldns_buffer_free(tmp_buffer); @@ -2119,7 +2171,7 @@ ldns_key2str(const ldns_key *k) } if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); } ldns_buffer_free(tmp_buffer); return result; @@ -2149,7 +2201,7 @@ ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list) } /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); ldns_buffer_free(tmp_buffer); return result; } @@ -2167,20 +2219,20 @@ ldns_rdf_print(FILE *output, const ldns_rdf *rdf) if (str) { fprintf(output, "%s", str); } else { - fprintf(output, "Unable to convert rdf to string\n"); + fprintf(output, ";Unable to convert rdf to string\n"); } LDNS_FREE(str); } void -ldns_rr_print_fmt(FILE *output, +ldns_rr_print_fmt(FILE *output, const ldns_output_format *fmt, const ldns_rr *rr) { char *str = ldns_rr2str_fmt(fmt, rr); if (str) { fprintf(output, "%s", str); } else { - fprintf(output, "Unable to convert rr to string\n"); + fprintf(output, ";Unable to convert rr to string\n"); } LDNS_FREE(str); } @@ -2199,7 +2251,7 @@ ldns_pkt_print_fmt(FILE *output, if (str) { fprintf(output, "%s", str); } else { - fprintf(output, "Unable to convert packet to string\n"); + fprintf(output, ";Unable to convert packet to string\n"); } LDNS_FREE(str); } diff --git a/usr.sbin/unbound/ldns/host2wire.c b/usr.sbin/unbound/ldns/host2wire.c index b5b0ba8ff20..de1e01e9ba3 100644 --- a/usr.sbin/unbound/ldns/host2wire.c +++ b/usr.sbin/unbound/ldns/host2wire.c @@ -341,7 +341,6 @@ ldns_status ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size) { ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); - uint8_t *result = NULL; ldns_status status; *result_size = 0; *dest = NULL; @@ -350,21 +349,8 @@ ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size) status = ldns_rdf2buffer_wire(buffer, rdf); if (status == LDNS_STATUS_OK) { *result_size = ldns_buffer_position(buffer); - result = (uint8_t *) ldns_buffer_export(buffer); - } else { - ldns_buffer_free(buffer); - return status; - } - - if (result) { - *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); - if(!*dest) { - ldns_buffer_free(buffer); - return LDNS_STATUS_MEM_ERR; - } - memcpy(*dest, result, ldns_buffer_position(buffer)); + *dest = (uint8_t *) ldns_buffer_export(buffer); } - ldns_buffer_free(buffer); return status; } @@ -373,7 +359,6 @@ ldns_status ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size) { ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); - uint8_t *result = NULL; ldns_status status; *result_size = 0; *dest = NULL; @@ -382,21 +367,8 @@ ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size status = ldns_rr2buffer_wire(buffer, rr, section); if (status == LDNS_STATUS_OK) { *result_size = ldns_buffer_position(buffer); - result = (uint8_t *) ldns_buffer_export(buffer); - } else { - ldns_buffer_free(buffer); - return status; + *dest = (uint8_t *) ldns_buffer_export(buffer); } - - if (result) { - *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); - if(!*dest) { - ldns_buffer_free(buffer); - return LDNS_STATUS_MEM_ERR; - } - memcpy(*dest, result, ldns_buffer_position(buffer)); - } - ldns_buffer_free(buffer); return status; } @@ -405,7 +377,6 @@ ldns_status ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size) { ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); - uint8_t *result = NULL; ldns_status status; *result_size = 0; *dest = NULL; @@ -414,21 +385,8 @@ ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size) status = ldns_pkt2buffer_wire(buffer, packet); if (status == LDNS_STATUS_OK) { *result_size = ldns_buffer_position(buffer); - result = (uint8_t *) ldns_buffer_export(buffer); - } else { - ldns_buffer_free(buffer); - return status; + *dest = (uint8_t *) ldns_buffer_export(buffer); } - - if (result) { - *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); - if(!*dest) { - ldns_buffer_free(buffer); - return LDNS_STATUS_MEM_ERR; - } - memcpy(*dest, result, ldns_buffer_position(buffer)); - } - ldns_buffer_free(buffer); return status; } diff --git a/usr.sbin/unbound/ldns/keys.c b/usr.sbin/unbound/ldns/keys.c index 54f26681494..de7c94610d8 100644 --- a/usr.sbin/unbound/ldns/keys.c +++ b/usr.sbin/unbound/ldns/keys.c @@ -431,8 +431,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) ldns_key_free(k); return LDNS_STATUS_ERR; } - ldns_key_set_rsa_key(k, rsa); - RSA_free(rsa); + ldns_key_assign_rsa_key(k, rsa); #endif /* HAVE_SSL */ break; case LDNS_SIGN_DSA: @@ -444,8 +443,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) ldns_key_free(k); return LDNS_STATUS_ERR; } - ldns_key_set_dsa_key(k, dsa); - DSA_free(dsa); + ldns_key_assign_dsa_key(k, dsa); #endif /* HAVE_SSL */ break; case LDNS_SIGN_HMACMD5: @@ -505,6 +503,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) *key = k; return LDNS_STATUS_OK; } + ldns_key_free(k); return LDNS_STATUS_ERR; } @@ -751,28 +750,21 @@ ldns_key_new_frm_fp_hmac_l( FILE *f , size_t *hmac_size ) { - size_t i; - char *d; - unsigned char *buf; - - d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); - buf = LDNS_XMALLOC(unsigned char, LDNS_MAX_LINELEN); - if(!d || !buf) { - goto error; - } + size_t i, bufsz; + char d[LDNS_MAX_LINELEN]; + unsigned char *buf = NULL; if (ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } - i = (size_t) ldns_b64_pton((const char*)d, - buf, - ldns_b64_ntop_calculate_size(strlen(d))); + bufsz = ldns_b64_ntop_calculate_size(strlen(d)); + buf = LDNS_XMALLOC(unsigned char, bufsz); + i = (size_t) ldns_b64_pton((const char*)d, buf, bufsz); *hmac_size = i; return buf; error: - LDNS_FREE(d); LDNS_FREE(buf); *hmac_size = 0; return NULL; @@ -850,6 +842,7 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) return NULL; } ldns_key_set_rsa_key(k, r); + RSA_free(r); #endif /* HAVE_SSL */ break; case LDNS_SIGN_DSA: @@ -865,6 +858,7 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) return NULL; } ldns_key_set_dsa_key(k, d); + DSA_free(d); #endif /* HAVE_SSL */ break; case LDNS_SIGN_HMACMD5: @@ -1005,6 +999,22 @@ ldns_key_set_dsa_key(ldns_key *k, DSA *d) EVP_PKEY_set1_DSA(key, d); k->_key.key = key; } + +void +ldns_key_assign_rsa_key(ldns_key *k, RSA *r) +{ + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(key, r); + k->_key.key = key; +} + +void +ldns_key_assign_dsa_key(ldns_key *k, DSA *d) +{ + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_assign_DSA(key, d); + k->_key.key = key; +} #endif /* splint */ #endif /* HAVE_SSL */ @@ -1302,7 +1312,7 @@ ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size) } /* See RFC2536 */ - *size = (uint16_t)BN_num_bytes(k->g); + *size = (uint16_t)BN_num_bytes(k->p); T = (*size - 64) / 8; memcpy(data, &T, 1); @@ -1365,10 +1375,10 @@ ldns_key2rr(const ldns_key *k) #endif int internal_data = 0; - pubkey = ldns_rr_new(); if (!k) { return NULL; } + pubkey = ldns_rr_new(); switch (ldns_key_algorithm(k)) { case LDNS_SIGN_HMACMD5: @@ -1638,7 +1648,7 @@ ldns_key_get_file_base_name(ldns_key *key) "+%03u+%05u", ldns_key_algorithm(key), ldns_key_keytag(key)); - file_base_name = strdup(ldns_buffer_export(buffer)); + file_base_name = ldns_buffer_export(buffer); ldns_buffer_free(buffer); return file_base_name; } diff --git a/usr.sbin/unbound/ldns/ldns/buffer.h b/usr.sbin/unbound/ldns/ldns/buffer.h index 03df14c9915..3b64198d8d5 100644 --- a/usr.sbin/unbound/ldns/ldns/buffer.h +++ b/usr.sbin/unbound/ldns/ldns/buffer.h @@ -630,8 +630,9 @@ void ldns_buffer_free(ldns_buffer *buffer); void *ldns_buffer_export(ldns_buffer *buffer); /** - * Copy contents of the other buffer to this buffer. Silently truncated - * if this buffer is too small. + * Copy contents of the from buffer to the result buffer and then flips + * the result buffer. Data will be silently truncated if the result buffer is + * too small. * \param[out] *result resulting buffer which is copied to. * \param[in] *from what to copy to result. */ diff --git a/usr.sbin/unbound/ldns/ldns/common.h.in b/usr.sbin/unbound/ldns/ldns/common.h.in index 5d6254752a5..aedfc96da7f 100644 --- a/usr.sbin/unbound/ldns/ldns/common.h.in +++ b/usr.sbin/unbound/ldns/ldns/common.h.in @@ -23,6 +23,7 @@ #define LDNS_BUILD_CONFIG_HAVE_INTTYPES_H @ldns_build_config_have_inttypes_h@ #define LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT @ldns_build_config_have_attr_format@ #define LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED @ldns_build_config_have_attr_unused@ +#define LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T @ldns_build_config_have_socklen_t@ /* * HAVE_STDBOOL_H is not available when distributed as a library, but no build @@ -65,4 +66,8 @@ typedef bool _Bool; #define ATTR_UNUSED(x) x #endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */ +#if !LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + #endif /* LDNS_COMMON_H */ diff --git a/usr.sbin/unbound/ldns/ldns/config.h.in b/usr.sbin/unbound/ldns/ldns/config.h.in index 3393e99767e..98cf357074b 100644 --- a/usr.sbin/unbound/ldns/ldns/config.h.in +++ b/usr.sbin/unbound/ldns/ldns/config.h.in @@ -33,6 +33,12 @@ /* Define to 1 if you have the `ctime_r' function. */ #undef HAVE_CTIME_R +/* Is a CAFILE given at configure time */ +#undef HAVE_DANE_CA_FILE + +/* Is a CAPATH given at configure time */ +#undef HAVE_DANE_CA_PATH + /* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you don't. */ #undef HAVE_DECL_NID_SECP384R1 @@ -250,6 +256,15 @@ /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL +/* Is a CAFILE given at configure time */ +#undef LDNS_DANE_CA_FILE + +/* Is a CAPATH given at configure time */ +#undef LDNS_DANE_CA_PATH + +/* Default trust anchor file */ +#undef LDNS_TRUST_ANCHOR_FILE + /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR diff --git a/usr.sbin/unbound/ldns/ldns/dane.h b/usr.sbin/unbound/ldns/ldns/dane.h new file mode 100644 index 00000000000..c1c4e2d75ca --- /dev/null +++ b/usr.sbin/unbound/ldns/ldns/dane.h @@ -0,0 +1,244 @@ +/* + * dane.h -- defines for the DNS-Based Authentication of Named Entities (DANE) + * Transport Layer Security (TLS) Protocol: TLSA + * + * Copyright (c) 2012, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + */ + +/** + * \file + * + * This module contains base functions for creating and verifying TLSA RR's + * with PKIX certificates, certificate chains and validation stores. + * (See RFC6394 and RFC6698). + * + * Since those functions heavily rely op cryptographic operations, + * this module is dependent on openssl. + */ + + +#ifndef LDNS_DANE_H +#define LDNS_DANE_H + +#include <ldns/common.h> +#include <ldns/rdata.h> +#include <ldns/rr.h> +#if LDNS_BUILD_CONFIG_HAVE_SSL +#include <openssl/ssl.h> +#include <openssl/err.h> +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The different "Certificate usage" rdata field values for a TLSA RR. + */ +enum ldns_enum_tlsa_certificate_usage +{ + /** CA constraint */ + LDNS_TLSA_USAGE_CA_CONSTRAINT = 0, + /** Sevice certificate constraint */ + LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT = 1, + /** Trust anchor assertion */ + LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION = 2, + /** Domain issued certificate */ + LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE = 3 +}; +typedef enum ldns_enum_tlsa_certificate_usage ldns_tlsa_certificate_usage; + +/** + * The different "Selector" rdata field values for a TLSA RR. + */ +enum ldns_enum_tlsa_selector +{ + /** + * Full certificate: the Certificate binary structure + * as defined in [RFC5280] + */ + LDNS_TLSA_SELECTOR_FULL_CERTIFICATE = 0, + + /** + * SubjectPublicKeyInfo: DER-encoded binary structure + * as defined in [RFC5280] + */ + LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO = 1 +}; +typedef enum ldns_enum_tlsa_selector ldns_tlsa_selector; + +/** + * The different "Matching type" rdata field values for a TLSA RR. + */ +enum ldns_enum_tlsa_matching_type +{ + /** Exact match on selected content */ + LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED = 0, + /** SHA-256 hash of selected content [RFC6234] */ + LDNS_TLSA_MATCHING_TYPE_SHA256 = 1, + /** SHA-512 hash of selected content [RFC6234] */ + LDNS_TLSA_MATCHING_TYPE_SHA512 = 2 +}; +typedef enum ldns_enum_tlsa_matching_type ldns_tlsa_matching_type; + +/** + * Known transports to use with TLSA owner names. + */ +enum ldns_enum_dane_transport +{ + /** TCP */ + LDNS_DANE_TRANSPORT_TCP = 0, + /** UDP */ + LDNS_DANE_TRANSPORT_UDP = 1, + /** SCTP */ + LDNS_DANE_TRANSPORT_SCTP = 2 +}; +typedef enum ldns_enum_dane_transport ldns_dane_transport; + + +/** + * Creates a dname consisting of the given name, prefixed by the service port + * and type of transport: _<EM>port</EM>._<EM>transport</EM>.<EM>name</EM>. + * + * \param[out] tlsa_owner The created dname. + * \param[in] name The dname that should be prefixed. + * \param[in] port The service port number for wich the name should be created. + * \param[in] transport The transport for wich the name should be created. + * \return LDNS_STATUS_OK on success or an error code otherwise. + */ +ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, + const ldns_rdf* name, uint16_t port, + ldns_dane_transport transport); + + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * Creates a LDNS_RDF_TYPE_HEX type rdf based on the binary data choosen by + * the selector and encoded using matching_type. + * + * \param[out] rdf The created created rdf of type LDNS_RDF_TYPE_HEX. + * \param[in] cert The certificate from which the data is selected + * \param[in] selector The full certificate or the public key + * \param[in] matching_type The full data or the SHA256 or SHA512 hash + * of the selected data + * \return LDNS_STATUS_OK on success or an error code otherwise. + */ +ldns_status ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type); + + +/** + * Selects the certificate from cert, extra_certs or the pkix_validation_store + * based on the value of cert_usage and index. + * + * \param[out] selected_cert The selected cert. + * \param[in] cert The certificate to validate (or not) + * \param[in] extra_certs Intermediate certificates that might be necessary + * during validation. May be NULL, except when the certificate + * usage is "Trust Anchor Assertion" because the trust anchor has + * to be provided.(otherwise choose a "Domain issued certificate!" + * \param[in] pkix_validation_store Used when the certificate usage is + * "CA constraint" or "Service Certificate Constraint" to + * validate the certificate and, in case of "CA constraint", + * select the CA. + * When pkix_validation_store is NULL, validation is explicitely + * turned off and the behaviour is then the same as for "Trust + * anchor assertion" and "Domain issued certificate" respectively. + * \param[in] cert_usage Which certificate to use and how to validate. + * \param[in] index Used to select the trust anchor when certificate usage + * is "Trust Anchor Assertion". 0 is the last certificate in the + * validation chain. 1 the one but last, etc. When index is -1, + * the last certificate is used that MUST be self-signed. + * This can help to make sure that the intended (self signed) + * trust anchor is actually present in extra_certs (which is a + * DANE requirement). + * + * \return LDNS_STATUS_OK on success or an error code otherwise. + */ +ldns_status ldns_dane_select_certificate(X509** selected_cert, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store, + ldns_tlsa_certificate_usage cert_usage, int index); + +/** + * Creates a TLSA resource record from the certificate. + * No PKIX validation is performed! The given certificate is used as data + * regardless the value of certificate_usage. + * + * \param[out] tlsa The created TLSA resource record. + * \param[in] certificate_usage The value for the Certificate Usage field + * \param[in] selector The value for the Selector field + * \param[in] matching_type The value for the Matching Type field + * \param[in] cert The certificate which data will be represented + * + * \return LDNS_STATUS_OK on success or an error code otherwise. + */ +ldns_status ldns_dane_create_tlsa_rr(ldns_rr** tlsa, + ldns_tlsa_certificate_usage certificate_usage, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type, + X509* cert); + +/** + * Verify if the given TLSA resource record matches the given certificate. + * Reporting on a TLSA rr mismatch (LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) + * is preferred over PKIX failure (LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE). + * So when PKIX validation is required by the TLSA Certificate usage, + * but the TLSA data does not match, LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH + * is returned whether the PKIX validated or not. + * + * \param[in] tlsa_rr The resource record that specifies what and how to + * match the certificate. With tlsa_rr == NULL, regular PKIX + * validation is performed. + * \param[in] cert The certificate to match (and validate) + * \param[in] extra_certs Intermediate certificates that might be necessary + * creating the validation chain. + * \param[in] pkix_validation_store Used when the certificate usage is + * "CA constraint" or "Service Certificate Constraint" to + * validate the certificate. + * + * \return LDNS_STATUS_OK on success, + * LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH on TLSA data mismatch, + * LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when TLSA matched, + * but the PKIX validation failed, or other ldns_status errors. + */ +ldns_status ldns_dane_verify_rr(const ldns_rr* tlsa_rr, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store); + +/** + * Verify if any of the given TLSA resource records matches the given + * certificate. + * + * \param[in] tlsas The resource records that specify what and how to + * match the certificate. One must match for this function + * to succeed. With tlsas == NULL or the number of TLSA records + * in tlsas == 0, regular PKIX validation is performed. + * \param[in] cert The certificate to match (and validate) + * \param[in] extra_certs Intermediate certificates that might be necessary + * creating the validation chain. + * \param[in] pkix_validation_store Used when the certificate usage is + * "CA constraint" or "Service Certificate Constraint" to + * validate the certificate. + * + * \return LDNS_STATUS_OK on success, + * LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when one of the TLSA's + * matched but the PKIX validation failed, + * LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH when none of the TLSA's matched, + * or other ldns_status errors. + */ +ldns_status ldns_dane_verify(ldns_rr_list* tlsas, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_DANE_H */ + diff --git a/usr.sbin/unbound/ldns/ldns/dname.h b/usr.sbin/unbound/ldns/ldns/dname.h index a91f075257c..16b45429fb2 100644 --- a/usr.sbin/unbound/ldns/ldns/dname.h +++ b/usr.sbin/unbound/ldns/ldns/dname.h @@ -111,6 +111,7 @@ ldns_rdf *ldns_dname_new_frm_str(const char *str); * Create a new dname rdf from a string * \param[in] s the size of the new dname * \param[in] *data pointer to the actual data + * * \return ldns_rdf* */ ldns_rdf *ldns_dname_new(uint16_t s, void *data); @@ -119,6 +120,7 @@ ldns_rdf *ldns_dname_new(uint16_t s, void *data); * Create a new dname rdf from data (the data is copied) * \param[in] size the size of the data * \param[in] *data pointer to the actual data + * * \return ldns_rdf* */ ldns_rdf *ldns_dname_new_frm_data(uint16_t size, const void *data); @@ -178,6 +180,13 @@ int ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, const ldns bool ldns_dname_str_absolute(const char *dname_str); /** + * Checks whether the given dname is absolute (i.e. ends with a '.') + * \param[in] *dname a rdf representing the dname + * \return true or false + */ +bool ldns_dname_absolute(const ldns_rdf *dname); + +/** * look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME * try and retrieve a specific label. The labels are numbered * starting from 0 (left most). diff --git a/usr.sbin/unbound/ldns/ldns/dnssec.h b/usr.sbin/unbound/ldns/ldns/dnssec.h index 9e602b5bc1d..34f63714c34 100644 --- a/usr.sbin/unbound/ldns/ldns/dnssec.h +++ b/usr.sbin/unbound/ldns/ldns/dnssec.h @@ -198,6 +198,7 @@ RSA *ldns_key_buf2rsa_raw(unsigned char* key, size_t len); * * \param[in] *key the key to convert * \param[in] h the hash to use LDNS_SHA1/LDNS_SHA256 + * * \return ldns_rr* a new rr pointer to a DS */ ldns_rr *ldns_key_rr2ds(const ldns_rr *key, ldns_hash h); diff --git a/usr.sbin/unbound/ldns/ldns/dnssec_verify.h b/usr.sbin/unbound/ldns/ldns/dnssec_verify.h index 32036a8c0b0..b6bdeca539b 100644 --- a/usr.sbin/unbound/ldns/ldns/dnssec_verify.h +++ b/usr.sbin/unbound/ldns/ldns/dnssec_verify.h @@ -367,6 +367,7 @@ void ldns_dnssec_derive_trust_tree_no_sig_time( * * \param *tree The trust tree so search * \param *keys A ldns_rr_list of DNSKEY and DS rrs to look for + * * \return LDNS_STATUS_OK if there is a trusted path to one of * the keys, or the *first* error encountered * if there were no paths diff --git a/usr.sbin/unbound/ldns/ldns/dnssec_zone.h b/usr.sbin/unbound/ldns/ldns/dnssec_zone.h index 4d2642fd1b4..70c81b04793 100644 --- a/usr.sbin/unbound/ldns/ldns/dnssec_zone.h +++ b/usr.sbin/unbound/ldns/ldns/dnssec_zone.h @@ -8,7 +8,6 @@ #ifndef LDNS_DNSSEC_ZONE_H #define LDNS_DNSSEC_ZONE_H -#include <ldns/ldns.h> #include <ldns/rbtree.h> #include <ldns/host2str.h> diff --git a/usr.sbin/unbound/ldns/ldns/error.h b/usr.sbin/unbound/ldns/ldns/error.h index 6396a934664..bac38ff8714 100644 --- a/usr.sbin/unbound/ldns/ldns/error.h +++ b/usr.sbin/unbound/ldns/ldns/error.h @@ -102,7 +102,22 @@ enum ldns_enum_status { LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG, LDNS_STATUS_MISSING_RDATA_FIELDS_KEY, LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN, - LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN + LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN, + LDNS_STATUS_DANE_STATUS_MESSAGES, + LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE, + LDNS_STATUS_DANE_UNKNOWN_SELECTOR, + LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE, + LDNS_STATUS_DANE_UNKNOWN_PROTOCOL, + LDNS_STATUS_DANE_UNKNOWN_TRANSPORT, + LDNS_STATUS_DANE_MISSING_EXTRA_CERTS, + LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED, + LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE, + LDNS_STATUS_DANE_INSECURE, + LDNS_STATUS_DANE_BOGUS, + LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH, + LDNS_STATUS_DANE_NON_CA_CERTIFICATE, + LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE, + LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR }; typedef enum ldns_enum_status ldns_status; diff --git a/usr.sbin/unbound/ldns/ldns/host2str.h b/usr.sbin/unbound/ldns/ldns/host2str.h index f0a14a4304a..bbf932767b3 100644 --- a/usr.sbin/unbound/ldns/ldns/host2str.h +++ b/usr.sbin/unbound/ldns/ldns/host2str.h @@ -64,6 +64,8 @@ extern "C" { #define LDNS_COMMENT_LAYOUT 0x0080 /** Also comment KEY_ID with RRSIGS **/ #define LDNS_COMMENT_RRSIGS 0x0100 +#define LDNS_FMT_ZEROIZE_RRSIGS 0x0200 +#define LDNS_FMT_PAD_SOA_SERIAL 0x0400 /** * Output format specifier @@ -601,8 +603,9 @@ char *ldns_rr_list2str_fmt( const ldns_output_format *fmt, const ldns_rr_list *rr_list); /** - * Returns the data in the buffer as a null terminated char * string - * Buffer data must be char * type, and must be freed by the caller + * Returns a copy of the data in the buffer as a null terminated + * char * string. The returned string must be freed by the caller. + * The buffer must be in write modus and may thus not have been flipped. * * \param[in] buffer buffer containing char * data * \return null terminated char * data, or NULL on error @@ -610,6 +613,17 @@ char *ldns_rr_list2str_fmt( char *ldns_buffer2str(ldns_buffer *buffer); /** + * Exports and returns the data in the buffer as a null terminated + * char * string. The returned string must be freed by the caller. + * The buffer must be in write modus and may thus not have been flipped. + * The buffer is fixed after this function returns. + * + * \param[in] buffer buffer containing char * data + * \return null terminated char * data, or NULL on error + */ +char *ldns_buffer_export2str(ldns_buffer *buffer); + +/** * Prints the data in the rdata field to the given file stream * (in presentation format) * diff --git a/usr.sbin/unbound/ldns/ldns/keys.h b/usr.sbin/unbound/ldns/ldns/keys.h index c4bf536911f..3e156233ba2 100644 --- a/usr.sbin/unbound/ldns/ldns/keys.h +++ b/usr.sbin/unbound/ldns/ldns/keys.h @@ -25,7 +25,6 @@ #if LDNS_BUILD_CONFIG_HAVE_SSL #include <openssl/ssl.h> #endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ -#include <ldns/dnssec.h> #include <ldns/util.h> #include <errno.h> @@ -299,18 +298,37 @@ void ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l); void ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e); /** - * Set the key's rsa data + * Set the key's rsa data. + * The rsa data should be freed by the user. * \param[in] k the key * \param[in] r the rsa data */ void ldns_key_set_rsa_key(ldns_key *k, RSA *r); + /** * Set the key's dsa data + * The dsa data should be freed by the user. * \param[in] k the key * \param[in] d the dsa data */ void ldns_key_set_dsa_key(ldns_key *k, DSA *d); +/** + * Assign the key's rsa data + * The rsa data will be freed automatically when the key is freed. + * \param[in] k the key + * \param[in] r the rsa data + */ +void ldns_key_assign_rsa_key(ldns_key *k, RSA *r); + +/** + * Assign the key's dsa data + * The dsa data will be freed automatically when the key is freed. + * \param[in] k the key + * \param[in] d the dsa data + */ +void ldns_key_assign_dsa_key(ldns_key *k, DSA *d); + /** * Get the PKEY id for GOST, loads GOST into openssl as a side effect. * Only available if GOST is compiled into the library and openssl. diff --git a/usr.sbin/unbound/ldns/ldns/ldns.h b/usr.sbin/unbound/ldns/ldns/ldns.h index 79152543348..a41e0325d67 100644 --- a/usr.sbin/unbound/ldns/ldns/ldns.h +++ b/usr.sbin/unbound/ldns/ldns/ldns.h @@ -95,6 +95,7 @@ Or you can just use the menu above to browse through the API docs. #include <ldns/util.h> #include <ldns/buffer.h> #include <ldns/common.h> +#include <ldns/dane.h> #include <ldns/dname.h> #include <ldns/dnssec.h> #include <ldns/dnssec_verify.h> diff --git a/usr.sbin/unbound/ldns/ldns/rdata.h b/usr.sbin/unbound/ldns/ldns/rdata.h index 90dcbf13818..229a4d4c5b5 100644 --- a/usr.sbin/unbound/ldns/ldns/rdata.h +++ b/usr.sbin/unbound/ldns/ldns/rdata.h @@ -194,6 +194,7 @@ ldns_rdf_type ldns_rdf_get_type(const ldns_rdf *rd); /** * returns the data of the rdf. * \param[in] *rd the rdf to read from + * * \return uint8_t* pointer to the rdf's data */ uint8_t *ldns_rdf_data(const ldns_rdf *rd); @@ -303,6 +304,7 @@ ldns_rdf *ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value); * The memory is copied, and an LDNS_RDF_TYPE_INT16DATA is returned * \param[in] size the size of the data * \param[in] *data pointer to the actual data + * * \return ldns_rd* the rdf with the data */ ldns_rdf *ldns_native2rdf_int16_data(size_t size, uint8_t *data); diff --git a/usr.sbin/unbound/ldns/ldns/resolver.h b/usr.sbin/unbound/ldns/ldns/resolver.h index f887aaf676e..7af5d401e65 100644 --- a/usr.sbin/unbound/ldns/ldns/resolver.h +++ b/usr.sbin/unbound/ldns/ldns/resolver.h @@ -578,6 +578,7 @@ ldns_status ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list * \param[in] t query for this type (may be 0, defaults to A) * \param[in] c query for this class (may be 0, default to IN) * \param[in] flags the query flags + * * \return ldns_pkt* a packet with the reply from the nameserver */ ldns_pkt* ldns_resolver_search(const ldns_resolver *r, const ldns_rdf *rdf, ldns_rr_type t, ldns_rr_class c, uint16_t flags); @@ -590,6 +591,7 @@ ldns_pkt* ldns_resolver_search(const ldns_resolver *r, const ldns_rdf *rdf, ldns * \param[in] t query for this type (may be 0, defaults to A) * \param[in] c query for this class (may be 0, default to IN) * \param[in] f the query flags + * * \return ldns_pkt* a packet with the reply from the nameserver */ 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); @@ -602,6 +604,7 @@ ldns_status ldns_resolver_prepare_query_pkt(ldns_pkt **q, ldns_resolver *r, cons * \param[in] t query for this type (may be 0, defaults to A) * \param[in] c query for this class (may be 0, default to IN) * \param[in] flags the query flags + * * \return ldns_pkt* a packet with the reply from the nameserver */ ldns_status ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags); @@ -621,6 +624,7 @@ ldns_status ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, ldns_pkt * \param[in] *t query for this type (may be 0, defaults to A) * \param[in] *c query for this class (may be 0, default to IN) * \param[in] flags the query flags + * * \return ldns_pkt* a packet with the reply from the nameserver * if _defnames is true the default domain will be added */ diff --git a/usr.sbin/unbound/ldns/ldns/rr.h b/usr.sbin/unbound/ldns/ldns/rr.h index 9882931b488..0520dcfe102 100644 --- a/usr.sbin/unbound/ldns/ldns/rr.h +++ b/usr.sbin/unbound/ldns/ldns/rr.h @@ -37,7 +37,7 @@ extern "C" { #define LDNS_RR_OVERHEAD 10 /* The first fields are 'common' and can be referenced instantly */ -#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 52 +#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 53 @@ -179,6 +179,8 @@ enum ldns_enum_rr_type LDNS_RR_TYPE_NSEC3 = 50, /* RFC 5155 */ LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */ LDNS_RR_TYPE_NSEC3PARAMS = 51, + /** draft-ietf-dane-protocol */ + LDNS_RR_TYPE_TLSA = 52, /** draft-ietf-dnsop-trust-history */ LDNS_RR_TYPE_TALINK = 58, diff --git a/usr.sbin/unbound/ldns/ldns/util.h.in b/usr.sbin/unbound/ldns/ldns/util.h.in index f9fb10420cc..fe4ff3720b0 100644 --- a/usr.sbin/unbound/ldns/ldns/util.h.in +++ b/usr.sbin/unbound/ldns/ldns/util.h.in @@ -268,6 +268,8 @@ const char * ldns_version(void); * \param[in] tm a struct tm* with the date * \return the seconds since epoch */ +time_t ldns_mktime_from_utc(const struct tm *tm); + time_t mktime_from_utc(const struct tm *tm); /** diff --git a/usr.sbin/unbound/ldns/libdns.doxygen b/usr.sbin/unbound/ldns/libdns.doxygen index 3325db94af4..0f84b73435e 100644 --- a/usr.sbin/unbound/ldns/libdns.doxygen +++ b/usr.sbin/unbound/ldns/libdns.doxygen @@ -1,4 +1,4 @@ -# Doxyfile 1.7.3 +# Doxyfile 1.7.6.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -22,8 +22,9 @@ DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. PROJECT_NAME = ldns @@ -33,7 +34,9 @@ PROJECT_NAME = ldns PROJECT_NUMBER = 1.6.7 -# Using the PROJECT_BRIEF tag one can provide an optional one line description for a project that appears at the top of each page and should give viewer a quick idea about the purpose of the project. Keep the description short. +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = @@ -192,6 +195,13 @@ TAB_SIZE = 8 ALIASES = +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list @@ -274,6 +284,22 @@ DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct @@ -296,10 +322,21 @@ TYPEDEF_HIDES_STRUCT = NO # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols +# corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -449,8 +486,11 @@ SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even if there is only one candidate or it is obvious which candidate to choose by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO @@ -538,6 +578,16 @@ FILE_VERSION_FILTER = LAYOUT_FILE = +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- @@ -629,13 +679,15 @@ FILE_PATTERNS = RECURSIVE = NO -# The EXCLUDE tag can be used to specify files and/or directories that should +# The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. EXCLUDE = -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. @@ -821,7 +873,14 @@ HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a -# standard header. +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = doc/header.html @@ -836,12 +895,21 @@ HTML_FOOTER = # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! +# style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images +# Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, @@ -871,12 +939,6 @@ HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = YES -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports @@ -1036,18 +1098,14 @@ GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.doxygen.Project -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [0,1..20]) -# that doxygen will group on one line in the generated HTML documentation. -# Note that a value of 0 will completely suppress the enum values from appearing in the overview section. - -ENUM_VALUES_PER_LINE = 4 - # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated @@ -1055,13 +1113,17 @@ ENUM_VALUES_PER_LINE = 4 # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. -USE_INLINE_TREES = NO +ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree @@ -1103,12 +1165,18 @@ USE_MATHJAX = NO # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the mathjax.org site, so you can quickly see the result without installing +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing # MathJax, but it is strongly recommended to install a local copy of MathJax # before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using @@ -1182,6 +1250,13 @@ EXTRA_PACKAGES = LATEX_HEADER = +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references @@ -1215,6 +1290,12 @@ LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- @@ -1246,7 +1327,7 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's +# Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. @@ -1391,7 +1472,7 @@ MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. +# pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES @@ -1399,7 +1480,7 @@ SEARCH_INCLUDES = YES # contain include files that are not input files but should be processed by # the preprocessor. -INCLUDE_PATH = +INCLUDE_PATH = . # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -1421,7 +1502,8 @@ PREDEFINED = HAVE_SSL # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition that overrules the definition found in the source code. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. EXPAND_AS_DEFINED = @@ -1519,13 +1601,12 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# By default doxygen will write a font called Helvetica to the output -# directory and reference it in all dot files that doxygen generates. -# When you want a differently looking font you can specify the font name -# using DOT_FONTNAME. You need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. DOT_FONTNAME = Helvetica @@ -1534,17 +1615,16 @@ DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. +# CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES @@ -1614,11 +1694,22 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, svg, gif or svg. -# If left blank png will be used. +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. diff --git a/usr.sbin/unbound/ldns/net.c b/usr.sbin/unbound/ldns/net.c index 870511a75b2..6b444da677b 100644 --- a/usr.sbin/unbound/ldns/net.c +++ b/usr.sbin/unbound/ldns/net.c @@ -110,12 +110,14 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf if ((ns->ss_family == AF_INET) && (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) { /* not reachable */ + LDNS_FREE(ns); continue; } if ((ns->ss_family == AF_INET6) && (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) { /* not reachable */ + LDNS_FREE(ns); continue; } #endif @@ -182,7 +184,8 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf ldns_pkt_set_querytime(reply, (uint32_t) ((tv_e.tv_sec - tv_s.tv_sec) * 1000) + (tv_e.tv_usec - tv_s.tv_usec) / 1000); - ldns_pkt_set_answerfrom(reply, ns_array[i]); + ldns_pkt_set_answerfrom(reply, + ldns_rdf_clone(ns_array[i])); ldns_pkt_set_timestamp(reply, tv_s); ldns_pkt_set_size(reply, reply_size); break; @@ -203,7 +206,7 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf return LDNS_STATUS_RES_NO_NS; } #ifdef HAVE_SSL - if (tsig_mac && reply_bytes) { + if (tsig_mac && reply && reply_bytes) { if (!ldns_pkt_tsig_verify(reply, reply_bytes, reply_size, @@ -470,7 +473,7 @@ ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, 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)); + memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin)); bytes = sendto(sockfd, (void*)sendbuf, ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen); @@ -669,7 +672,7 @@ ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storag } /* resize accordingly */ - *result = (uint8_t*)LDNS_XREALLOC(answer, uint8_t *, (size_t)*answer_size); + *result = LDNS_XREALLOC(answer, uint8_t, (size_t)*answer_size); if(!*result) { LDNS_FREE(answer); return LDNS_STATUS_MEM_ERR; @@ -807,6 +810,9 @@ ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) ns_i < ldns_resolver_nameserver_count(resolver) && resolver->_socket == 0; ns_i++) { + if (ns != NULL) { + LDNS_FREE(ns); + } ns = ldns_rdf2native_sockaddr_storage( resolver->_nameservers[ns_i], ldns_resolver_port(resolver), &ns_len); @@ -837,6 +843,9 @@ ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) #endif resolver->_socket = 0; + ldns_pkt_free(query); + LDNS_FREE(ns); + return LDNS_STATUS_CRYPTO_TSIG_ERR; } } diff --git a/usr.sbin/unbound/ldns/packet.c b/usr.sbin/unbound/ldns/packet.c index 0ac5ca8ba31..b44c0add645 100644 --- a/usr.sbin/unbound/ldns/packet.c +++ b/usr.sbin/unbound/ldns/packet.c @@ -255,7 +255,6 @@ ldns_pkt_rr_list_by_name(ldns_pkt *packet, ldns_pkt_section sec) { ldns_rr_list *rrs; - ldns_rr_list *new; ldns_rr_list *ret; uint16_t i; @@ -264,7 +263,6 @@ ldns_pkt_rr_list_by_name(ldns_pkt *packet, } rrs = ldns_pkt_get_section_clone(packet, sec); - new = ldns_rr_list_new(); ret = NULL; for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { @@ -272,8 +270,10 @@ ldns_pkt_rr_list_by_name(ldns_pkt *packet, ldns_rr_list_rr(rrs, i)), ownername) == 0) { /* owner names match */ - ldns_rr_list_push_rr(new, ldns_rr_list_rr(rrs, i)); - ret = new; + if (ret == NULL) { + ret = ldns_rr_list_new(); + } + ldns_rr_list_push_rr(ret, ldns_rr_list_rr(rrs, i)); } } return ret; @@ -649,19 +649,27 @@ ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr) { switch(section) { case LDNS_SECTION_QUESTION: - ldns_rr_list_push_rr(ldns_pkt_question(packet), rr); + if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) { + return false; + } ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1); break; case LDNS_SECTION_ANSWER: - ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr); + if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) { + return false; + } ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1); break; case LDNS_SECTION_AUTHORITY: - ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr); + if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) { + return false; + } ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1); break; case LDNS_SECTION_ADDITIONAL: - ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr); + if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) { + return false; + } ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1); break; case LDNS_SECTION_ANY: @@ -783,6 +791,7 @@ ldns_pkt_free(ldns_pkt *packet) ldns_rr_list_deep_free(packet->_additional); ldns_rr_free(packet->_tsig_rr); ldns_rdf_deep_free(packet->_edns_data); + ldns_rdf_deep_free(packet->_answerfrom); LDNS_FREE(packet); } } @@ -817,6 +826,86 @@ ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags) return true; } + +static ldns_status +ldns_pkt_add_authsoa(ldns_pkt* packet, ldns_rdf* rr_name, ldns_rr_class rr_class) +{ + ldns_rr* soa_rr = ldns_rr_new(); + ldns_rdf *owner_rdf; + ldns_rdf *mname_rdf; + ldns_rdf *rname_rdf; + ldns_rdf *serial_rdf; + ldns_rdf *refresh_rdf; + ldns_rdf *retry_rdf; + ldns_rdf *expire_rdf; + ldns_rdf *minimum_rdf; + + if (!soa_rr) { + return LDNS_STATUS_MEM_ERR; + } + owner_rdf = ldns_rdf_clone(rr_name); + if (!owner_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } + + ldns_rr_set_owner(soa_rr, owner_rdf); + ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA); + ldns_rr_set_class(soa_rr, rr_class); + ldns_rr_set_question(soa_rr, false); + + if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, mname_rdf); + } + if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, rname_rdf); + } + serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!serial_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, serial_rdf); + } + refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!refresh_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, refresh_rdf); + } + retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!retry_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, retry_rdf); + } + expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!expire_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, expire_rdf); + } + minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!minimum_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, minimum_rdf); + } + ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, soa_rr); + return LDNS_STATUS_OK; +} + + ldns_status ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags) @@ -851,21 +940,29 @@ ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, ldns_rr_type rr_type, ldns_rr_set_type(question_rr, rr_type); ldns_rr_set_class(question_rr, rr_class); ldns_rr_set_question(question_rr, true); - + ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); } else { ldns_rr_free(question_rr); ldns_pkt_free(packet); return LDNS_STATUS_ERR; } - + + /** IXFR? */ + if (rr_type == LDNS_RR_TYPE_IXFR) { + if (ldns_pkt_add_authsoa(packet, name_rdf, rr_class) != LDNS_STATUS_OK) { + ldns_pkt_free(packet); + return LDNS_STATUS_ERR; + } + } + packet->_tsig_rr = NULL; - ldns_pkt_set_answerfrom(packet, NULL); if (p) { *p = packet; return LDNS_STATUS_OK; } else { + ldns_pkt_free(packet); return LDNS_STATUS_NULL; } } @@ -888,6 +985,7 @@ ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_cla question_rr = ldns_rr_new(); if (!question_rr) { + ldns_pkt_free(packet); return NULL; } @@ -902,11 +1000,17 @@ ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_cla ldns_rr_set_type(question_rr, rr_type); ldns_rr_set_class(question_rr, rr_class); ldns_rr_set_question(question_rr, true); - - packet->_tsig_rr = NULL; - ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); + /** IXFR? */ + if (rr_type == LDNS_RR_TYPE_IXFR) { + if (ldns_pkt_add_authsoa(packet, rr_name, rr_class) != LDNS_STATUS_OK) { + ldns_pkt_free(packet); + return NULL; + } + } + + packet->_tsig_rr = NULL; return packet; } @@ -980,7 +1084,9 @@ ldns_pkt_clone(ldns_pkt *pkt) ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt)); ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt)); ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt)); - ldns_pkt_set_answerfrom(new_pkt, ldns_pkt_answerfrom(pkt)); + if (ldns_pkt_answerfrom(pkt)) + ldns_pkt_set_answerfrom(new_pkt, + ldns_rdf_clone(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_rr_clone(ldns_pkt_tsig(pkt))); diff --git a/usr.sbin/unbound/ldns/parse.c b/usr.sbin/unbound/ldns/parse.c index ac9bdbdd556..ea5ffad026f 100644 --- a/usr.sbin/unbound/ldns/parse.c +++ b/usr.sbin/unbound/ldns/parse.c @@ -161,7 +161,7 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li return (ssize_t)i; tokenread: - ldns_fskipcs_l(f, delim, line_nr); + ldns_fskipcs_l(f, del, line_nr); *t = '\0'; if (p != 0) { return -1; @@ -331,7 +331,7 @@ ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) return (ssize_t)i; tokenread: - ldns_bskipcs(b, delim); + ldns_bskipcs(b, del); *t = '\0'; if (p != 0) { diff --git a/usr.sbin/unbound/ldns/resolver.c b/usr.sbin/unbound/ldns/resolver.c index 1a788a363fe..2cee9fff194 100644 --- a/usr.sbin/unbound/ldns/resolver.c +++ b/usr.sbin/unbound/ldns/resolver.c @@ -253,13 +253,20 @@ ldns_resolver_pop_nameserver(ldns_resolver *r) pop = nameservers[ns_count - 1]; - nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count - 1)); - rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1)); + if (ns_count == 1) { + LDNS_FREE(nameservers); + LDNS_FREE(rtt); + + ldns_resolver_set_nameservers(r, NULL); + ldns_resolver_set_rtt(r, NULL); + } else { + nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, + (ns_count - 1)); + rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1)); - if(nameservers) ldns_resolver_set_nameservers(r, nameservers); - if(rtt) ldns_resolver_set_rtt(r, rtt); + } /* decr the count */ ldns_resolver_dec_nameserver_count(r); return pop; @@ -385,7 +392,9 @@ ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr) { ldns_rr_list * trust_anchors; - if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY)) { + if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY && + ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) { + return LDNS_STATUS_ERR; } @@ -800,8 +809,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) gtr -= bgtr; if(word[0] == '#') { expect = LDNS_RESOLV_KEYWORD; - ldns_buffer_free(b); - continue; + break; } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); if (!tmp) { @@ -817,8 +825,10 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) (size_t) gtr + 1); } ldns_buffer_free(b); - gtr = 1; - expect = LDNS_RESOLV_KEYWORD; + if (expect != LDNS_RESOLV_KEYWORD) { + gtr = 1; + expect = LDNS_RESOLV_KEYWORD; + } break; case LDNS_RESOLV_SORTLIST: gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); @@ -885,6 +895,7 @@ ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename) *res = r; return LDNS_STATUS_OK; } else { + ldns_resolver_free(r); return LDNS_STATUS_NULL; } } @@ -947,15 +958,12 @@ ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags) { - char *str_dname; ldns_rdf *new_name; ldns_rdf **search_list; size_t i; ldns_pkt *p; - str_dname = ldns_rdf2str(name); - - if (ldns_dname_str_absolute(str_dname)) { + if (ldns_dname_absolute(name)) { /* query as-is */ return ldns_resolver_query(r, name, t, c, flags); } else if (ldns_resolver_dnsrch(r)) { @@ -1017,9 +1025,6 @@ ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r)); if (!newname) { - if (pkt) { - ldns_pkt_free(pkt); - } return NULL; } @@ -1212,9 +1217,11 @@ ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, ldns_resolver_tsig_keydata(r), 300, ldns_resolver_tsig_algorithm(r), NULL); if (status != LDNS_STATUS_OK) { + ldns_pkt_free(query_pkt); return LDNS_STATUS_CRYPTO_TSIG_ERR; } #else + ldns_pkt_free(query_pkt); return LDNS_STATUS_CRYPTO_TSIG_ERR; #endif /* HAVE_SSL */ } @@ -1294,7 +1301,14 @@ ldns_axfr_next(ldns_resolver *resolver) 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); + if (rcode) { + fprintf(stderr, "Error in AXFR: %s\n", + rcode->name); + } else { + fprintf(stderr, "Error in AXFR: %d\n", + (int) ldns_pkt_get_rcode( + resolver->_cur_axfr_pkt)); + } /* 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 @@ -1333,17 +1347,22 @@ void ldns_resolver_nameservers_randomize(ldns_resolver *r) { uint16_t i, j; - ldns_rdf **ns, *tmp; + ldns_rdf **ns, *tmpns; + size_t *rtt, tmprtt; /* should I check for ldns_resolver_random?? */ assert(r != NULL); ns = ldns_resolver_nameservers(r); + rtt = ldns_resolver_rtt(r); for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { j = ldns_get_random() % ldns_resolver_nameserver_count(r); - tmp = ns[i]; + tmpns = ns[i]; ns[i] = ns[j]; - ns[j] = tmp; + ns[j] = tmpns; + tmprtt = rtt[i]; + rtt[i] = rtt[j]; + rtt[j] = tmprtt; } ldns_resolver_set_nameservers(r, ns); } diff --git a/usr.sbin/unbound/ldns/rr.c b/usr.sbin/unbound/ldns/rr.c index 8f4ce85c7eb..72076d40c58 100644 --- a/usr.sbin/unbound/ldns/rr.c +++ b/usr.sbin/unbound/ldns/rr.c @@ -119,7 +119,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, char *type = NULL; char *rdata = NULL; char *rd = NULL; - char *b64 = NULL; + char * b64 = NULL; size_t rd_strlen; const char *delimiters; ssize_t c; @@ -477,6 +477,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, ldns_buffer_free(rr_buf); LDNS_FREE(rdata); ldns_rr_free(new); + LDNS_FREE(hex_data); return s; } LDNS_FREE(hex_data); @@ -600,6 +601,9 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, if (newrr) { *newrr = new; + } else { + /* Maybe the caller just wanted to see if it would parse? */ + ldns_rr_free(new); } return LDNS_STATUS_OK; @@ -724,8 +728,13 @@ ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf } } LDNS_FREE(line); - if (newrr && s == LDNS_STATUS_OK) { - *newrr = rr; + if (s == LDNS_STATUS_OK) { + if (newrr) { + *newrr = rr; + } else { + /* Just testing if it would parse? */ + ldns_rr_free(rr); + } } return s; } @@ -1156,7 +1165,8 @@ ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t howmany) i--; } - if (i == howmany) { + if (i == howmany) { /* so i <= 0 */ + ldns_rr_list_free(popped); return NULL; } else { return popped; @@ -1480,6 +1490,7 @@ ldns_rr_list_sort(ldns_rr_list *unsorted) LDNS_FREE(sortables[i]); } /* no way to return error */ + LDNS_FREE(sortables); return; } sortables[i]->original_object = ldns_rr_list_rr(unsorted, i); @@ -1941,6 +1952,12 @@ static const ldns_rdf_type type_tsig_wireformat[] = { LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16_DATA }; +static const ldns_rdf_type type_tlsa_wireformat[] = { + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_HEX +}; /** \endcond */ /** \cond */ @@ -2048,13 +2065,14 @@ static ldns_rr_descriptor rdata_field_descriptors[] = { /* 48 */ {LDNS_RR_TYPE_DNSKEY, "DNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 49 */ -{LDNS_RR_TYPE_DHCID, "DHCID", 1, 1, type_dhcid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_DHCID, "DHCID", 1, 1, type_dhcid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 50 */ {LDNS_RR_TYPE_NSEC3, "NSEC3", 5, 6, type_nsec3_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 51 */ -{LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 52 */ -{LDNS_RR_TYPE_NULL, "TYPE52", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE55", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, diff --git a/usr.sbin/unbound/ldns/str2host.c b/usr.sbin/unbound/ldns/str2host.c index 2783f0805a4..51357cc3176 100644 --- a/usr.sbin/unbound/ldns/str2host.c +++ b/usr.sbin/unbound/ldns/str2host.c @@ -96,7 +96,7 @@ ldns_str2rdf_time(ldns_rdf **rd, const char *time) goto bad_format; } - l = htonl(mktime_from_utc(&tm)); + l = htonl(ldns_mktime_from_utc(&tm)); memcpy(r, &l, sizeof(uint32_t)); *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r); @@ -534,6 +534,7 @@ ldns_str2rdf_apl(ldns_rdf **rd, const char *str) data = LDNS_XMALLOC(uint8_t, 4 + afdlength); if(!data) { + LDNS_FREE(afdpart); LDNS_FREE(my_ip_str); return LDNS_STATUS_INVALID_STR; } @@ -1104,8 +1105,6 @@ ldns_str2rdf_wks(ldns_rdf **rd, const char *str) data[0] = (uint8_t) proto->p_proto; } else if (proto_str) { data[0] = (uint8_t) atoi(proto_str); - } else { - data[0] = 0; } memcpy(data + 1, bitmap, (size_t) bm_len); diff --git a/usr.sbin/unbound/ldns/tsig.c b/usr.sbin/unbound/ldns/tsig.c index 90c20a03ea0..41693463df3 100644 --- a/usr.sbin/unbound/ldns/tsig.c +++ b/usr.sbin/unbound/ldns/tsig.c @@ -179,10 +179,12 @@ ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, return LDNS_STATUS_NULL; } canonical_key_name_rdf = ldns_rdf_clone(key_name_rdf); + if (canonical_key_name_rdf == NULL) { + return LDNS_STATUS_MEM_ERR; + } canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf); - - if (canonical_key_name_rdf == NULL - || canonical_algorithm_rdf == NULL) { + if (canonical_algorithm_rdf == NULL) { + ldns_rdf_deep_free(canonical_key_name_rdf); return LDNS_STATUS_MEM_ERR; } /* @@ -266,8 +268,8 @@ ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, LDNS_FREE(key_bytes); LDNS_FREE(algorithm_name); ldns_buffer_free(data_buffer); - ldns_rdf_free(canonical_algorithm_rdf); - ldns_rdf_free(canonical_key_name_rdf); + ldns_rdf_deep_free(canonical_algorithm_rdf); + ldns_rdf_deep_free(canonical_key_name_rdf); return status; } #endif /* HAVE_SSL */ diff --git a/usr.sbin/unbound/ldns/util.c b/usr.sbin/unbound/ldns/util.c index a7ab96080ce..f5462c4b08f 100644 --- a/usr.sbin/unbound/ldns/util.c +++ b/usr.sbin/unbound/ldns/util.c @@ -227,7 +227,7 @@ leap_days(int y1, int y2) * Code adapted from Python 2.4.1 sources (Lib/calendar.py). */ time_t -mktime_from_utc(const struct tm *tm) +ldns_mktime_from_utc(const struct tm *tm) { int year = 1900 + tm->tm_year; time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year); @@ -251,6 +251,12 @@ mktime_from_utc(const struct tm *tm) return seconds; } +time_t +mktime_from_utc(const struct tm *tm) +{ + return ldns_mktime_from_utc(tm); +} + #if SIZEOF_TIME_T <= 4 static void @@ -398,6 +404,7 @@ ldns_init_random(FILE *fd, unsigned int size) if (read < size) { LDNS_FREE(seed); + if (!fd) fclose(rand_f); return 1; } else { #ifdef HAVE_SSL |