summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/unwind/libunbound/config.h21
-rw-r--r--sbin/unwind/libunbound/iterator/iter_utils.c13
-rw-r--r--sbin/unwind/libunbound/iterator/iter_utils.h7
-rw-r--r--sbin/unwind/libunbound/iterator/iterator.c11
-rw-r--r--sbin/unwind/libunbound/services/authzone.c253
-rw-r--r--sbin/unwind/libunbound/services/authzone.h7
-rw-r--r--sbin/unwind/libunbound/services/cache/dns.c6
-rw-r--r--sbin/unwind/libunbound/services/listen_dnsport.c29
-rw-r--r--sbin/unwind/libunbound/services/mesh.c35
-rw-r--r--sbin/unwind/libunbound/services/outside_network.c104
-rw-r--r--sbin/unwind/libunbound/services/outside_network.h4
-rw-r--r--sbin/unwind/libunbound/util/alloc.c8
-rw-r--r--sbin/unwind/libunbound/util/data/msgreply.h2
-rw-r--r--sbin/unwind/libunbound/util/fptr_wlist.c1
-rw-r--r--sbin/unwind/libunbound/util/iana_ports.inc2
-rw-r--r--sbin/unwind/libunbound/util/net_help.c17
-rw-r--r--sbin/unwind/libunbound/util/netevent.c98
-rw-r--r--sbin/unwind/libunbound/util/storage/lookup3.c8
-rw-r--r--sbin/unwind/libunbound/util/ub_event.c14
19 files changed, 508 insertions, 132 deletions
diff --git a/sbin/unwind/libunbound/config.h b/sbin/unwind/libunbound/config.h
index 7b0ba84679b..8c7028b6ab9 100644
--- a/sbin/unwind/libunbound/config.h
+++ b/sbin/unwind/libunbound/config.h
@@ -87,6 +87,10 @@
if you don't. */
#define HAVE_DECL_ARC4RANDOM_UNIFORM 1
+/* Define to 1 if you have the declaration of `evsignal_assign', and to 0 if
+ you don't. */
+#define HAVE_DECL_EVSIGNAL_ASSIGN 0
+
/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
don't. */
#define HAVE_DECL_INET_NTOP 1
@@ -167,6 +171,9 @@
/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
#define HAVE_ERR_LOAD_CRYPTO_STRINGS 1
+/* Define to 1 if you have the `event_assign' function. */
+/* #undef HAVE_EVENT_ASSIGN */
+
/* Define to 1 if you have the `event_base_free' function. */
#define HAVE_EVENT_BASE_FREE 1
@@ -407,7 +414,7 @@
/* Define to 1 if you have the `RAND_cleanup' function. */
#define HAVE_RAND_CLEANUP 1
-/* Define to 1 if you have the `reallocarray' function. */
+/* If we have reallocarray(3) */
#define HAVE_REALLOCARRAY 1
/* Define to 1 if you have the `recvmsg' function. */
@@ -664,7 +671,7 @@
#define PACKAGE_NAME "unbound"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "unbound 1.9.1"
+#define PACKAGE_STRING "unbound 1.9.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@@ -673,7 +680,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.9.1"
+#define PACKAGE_VERSION "1.9.2"
/* default pidfile location */
#define PIDFILE ""
@@ -695,7 +702,7 @@
#define ROOT_CERT_FILE "/var/unbound/etc/icannbundle.pem"
/* version number for resource files */
-#define RSRC_PACKAGE_VERSION 1,9,1,0
+#define RSRC_PACKAGE_VERSION 1,9,2,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound/etc"
@@ -966,8 +973,14 @@
+#ifndef _OPENBSD_SOURCE
+#define _OPENBSD_SOURCE 1
+#endif
+
#ifndef UNBOUND_DEBUG
+# ifndef NDEBUG
# define NDEBUG
+# endif
#endif
/** Use small-ldns codebase */
diff --git a/sbin/unwind/libunbound/iterator/iter_utils.c b/sbin/unwind/libunbound/iterator/iter_utils.c
index be7965a60e3..2ab55ceb497 100644
--- a/sbin/unwind/libunbound/iterator/iter_utils.c
+++ b/sbin/unwind/libunbound/iterator/iter_utils.c
@@ -1211,6 +1211,19 @@ iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z)
}
}
+void
+iter_scrub_nxdomain(struct dns_msg* msg)
+{
+ if(msg->rep->an_numrrsets == 0)
+ return;
+
+ memmove(msg->rep->rrsets, msg->rep->rrsets+msg->rep->an_numrrsets,
+ sizeof(struct ub_packed_rrset_key*) *
+ (msg->rep->rrset_count-msg->rep->an_numrrsets));
+ msg->rep->rrset_count -= msg->rep->an_numrrsets;
+ msg->rep->an_numrrsets = 0;
+}
+
void iter_dec_attempts(struct delegpt* dp, int d)
{
struct delegpt_addr* a;
diff --git a/sbin/unwind/libunbound/iterator/iter_utils.h b/sbin/unwind/libunbound/iterator/iter_utils.h
index ccfb280224b..f771930bba2 100644
--- a/sbin/unwind/libunbound/iterator/iter_utils.h
+++ b/sbin/unwind/libunbound/iterator/iter_utils.h
@@ -335,6 +335,13 @@ void iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns,
uint8_t* z);
/**
+ * Prepare an NXDOMAIN message to be used for a subdomain answer by removing all
+ * RRs from the ANSWER section.
+ * @param msg: the response to scrub.
+ */
+void iter_scrub_nxdomain(struct dns_msg* msg);
+
+/**
* Remove query attempts from all available ips. For 0x20.
* @param dp: delegpt.
* @param d: decrease.
diff --git a/sbin/unwind/libunbound/iterator/iterator.c b/sbin/unwind/libunbound/iterator/iterator.c
index c73fb517748..c906c271448 100644
--- a/sbin/unwind/libunbound/iterator/iterator.c
+++ b/sbin/unwind/libunbound/iterator/iterator.c
@@ -2718,8 +2718,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
&& !(iq->chase_flags & BIT_RD)) {
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
LDNS_RCODE_NOERROR) {
- if(qstate->env->cfg->qname_minimisation_strict)
- return final_state(iq);
+ if(qstate->env->cfg->qname_minimisation_strict) {
+ if(FLAGS_GET_RCODE(iq->response->rep->flags) ==
+ LDNS_RCODE_NXDOMAIN) {
+ iter_scrub_nxdomain(iq->response);
+ return final_state(iq);
+ }
+ return error_response(qstate, id,
+ LDNS_RCODE_SERVFAIL);
+ }
/* Best effort qname-minimisation.
* Stop minimising and send full query when
* RCODE is not NOERROR. */
diff --git a/sbin/unwind/libunbound/services/authzone.c b/sbin/unwind/libunbound/services/authzone.c
index a87c2274fb9..1426f423a1b 100644
--- a/sbin/unwind/libunbound/services/authzone.c
+++ b/sbin/unwind/libunbound/services/authzone.c
@@ -2042,11 +2042,13 @@ auth_xfer_delete(struct auth_xfer* xfr)
if(xfr->task_probe) {
auth_free_masters(xfr->task_probe->masters);
comm_point_delete(xfr->task_probe->cp);
+ comm_timer_delete(xfr->task_probe->timer);
free(xfr->task_probe);
}
if(xfr->task_transfer) {
auth_free_masters(xfr->task_transfer->masters);
comm_point_delete(xfr->task_transfer->cp);
+ comm_timer_delete(xfr->task_transfer->timer);
if(xfr->task_transfer->chunks_first) {
auth_chunks_delete(xfr->task_transfer);
}
@@ -2746,6 +2748,7 @@ az_nsec3_insert(struct auth_zone* z, struct regional* region,
* that is an exact match that should exist for it.
* If that does not exist, a higher exact match + nxproof is enabled
* (for some sort of opt-out empty nonterminal cases).
+ * nodataproof: search for exact match and include that instead.
* ceproof: include ce proof NSEC3 (omitted for wildcard replies).
* nxproof: include denial of the qname.
* wcproof: include denial of wildcard (wildcard.ce).
@@ -2753,7 +2756,8 @@ az_nsec3_insert(struct auth_zone* z, struct regional* region,
static int
az_add_nsec3_proof(struct auth_zone* z, struct regional* region,
struct dns_msg* msg, uint8_t* cenm, size_t cenmlen, uint8_t* qname,
- size_t qname_len, int ceproof, int nxproof, int wcproof)
+ size_t qname_len, int nodataproof, int ceproof, int nxproof,
+ int wcproof)
{
int algo;
size_t iter, saltlen;
@@ -2764,6 +2768,19 @@ az_add_nsec3_proof(struct auth_zone* z, struct regional* region,
/* find parameters of nsec3 proof */
if(!az_nsec3_param(z, &algo, &iter, &salt, &saltlen))
return 1; /* no nsec3 */
+ if(nodataproof) {
+ /* see if the node has a hash of itself for the nodata
+ * proof nsec3, this has to be an exact match nsec3. */
+ struct auth_data* match;
+ match = az_nsec3_find_exact(z, qname, qname_len, algo,
+ iter, salt, saltlen);
+ if(match) {
+ if(!az_nsec3_insert(z, region, msg, match))
+ return 0;
+ /* only nodata NSEC3 needed, no CE or others. */
+ return 1;
+ }
+ }
/* find ce that has an NSEC3 */
if(ceproof) {
node = az_nsec3_find_ce(z, &cenm, &cenmlen, &no_exact_ce,
@@ -2916,7 +2933,7 @@ az_generate_notype_answer(struct auth_zone* z, struct regional* region,
/* DNSSEC denial NSEC3 */
if(!az_add_nsec3_proof(z, region, msg, node->name,
node->namelen, msg->qinfo.qname,
- msg->qinfo.qname_len, 1, 0, 0))
+ msg->qinfo.qname_len, 1, 1, 0, 0))
return 0;
}
return 1;
@@ -2943,7 +2960,7 @@ az_generate_referral_answer(struct auth_zone* z, struct regional* region,
} else {
if(!az_add_nsec3_proof(z, region, msg, ce->name,
ce->namelen, msg->qinfo.qname,
- msg->qinfo.qname_len, 1, 0, 0))
+ msg->qinfo.qname_len, 1, 1, 0, 0))
return 0;
}
}
@@ -2982,6 +2999,7 @@ az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo,
struct auth_data* wildcard, struct auth_data* node)
{
struct auth_rrset* rrset, *nsec;
+ int insert_ce = 0;
if((rrset=az_domain_rrset(wildcard, qinfo->qtype)) != NULL) {
/* wildcard has type, add it */
if(!msg_add_rrset_an(z, region, msg, wildcard, rrset))
@@ -3008,6 +3026,10 @@ az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo,
/* call other notype routine for dnssec notype denials */
if(!az_generate_notype_answer(z, region, msg, wildcard))
return 0;
+ /* because the notype, there is no positive data with an
+ * RRSIG that indicates the wildcard position. Thus the
+ * wildcard qname denial needs to have a CE nsec3. */
+ insert_ce = 1;
}
/* ce and node for dnssec denial of wildcard original name */
@@ -3019,7 +3041,7 @@ az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo,
dname_remove_label(&wildup, &wilduplen);
if(!az_add_nsec3_proof(z, region, msg, wildup,
wilduplen, msg->qinfo.qname,
- msg->qinfo.qname_len, 0, 1, 0))
+ msg->qinfo.qname_len, 0, insert_ce, 1, 0))
return 0;
}
@@ -3045,7 +3067,7 @@ az_generate_nxdomain_answer(struct auth_zone* z, struct regional* region,
} else if(ce) {
if(!az_add_nsec3_proof(z, region, msg, ce->name,
ce->namelen, msg->qinfo.qname,
- msg->qinfo.qname_len, 1, 1, 1))
+ msg->qinfo.qname_len, 0, 1, 1, 1))
return 0;
}
return 1;
@@ -4953,6 +4975,9 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
static void
xfr_transfer_disown(struct auth_xfer* xfr)
{
+ /* remove timer (from this worker's event base) */
+ comm_timer_delete(xfr->task_transfer->timer);
+ xfr->task_transfer->timer = NULL;
/* remove the commpoint */
comm_point_delete(xfr->task_transfer->cp);
xfr->task_transfer->cp = NULL;
@@ -5034,6 +5059,9 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
struct sockaddr_storage addr;
socklen_t addrlen = 0;
struct auth_master* master = xfr->task_transfer->master;
+ char *auth_name = NULL;
+ struct timeval t;
+ int timeout;
if(!master) return 0;
if(master->allow_notify) return 0; /* only for notify */
@@ -5042,7 +5070,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
addrlen = xfr->task_transfer->scan_addr->addrlen;
memmove(&addr, &xfr->task_transfer->scan_addr->addr, addrlen);
} else {
- if(!extstrtoaddr(master->host, &addr, &addrlen)) {
+ if(!authextstrtoaddr(master->host, &addr, &addrlen, &auth_name)) {
/* the ones that are not in addr format are supposed
* to be looked up. The lookup has failed however,
* so skip them */
@@ -5059,25 +5087,46 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
comm_point_delete(xfr->task_transfer->cp);
xfr->task_transfer->cp = NULL;
}
+ if(!xfr->task_transfer->timer) {
+ xfr->task_transfer->timer = comm_timer_create(env->worker_base,
+ auth_xfer_transfer_timer_callback, xfr);
+ if(!xfr->task_transfer->timer) {
+ log_err("malloc failure");
+ return 0;
+ }
+ }
+ timeout = AUTH_TRANSFER_TIMEOUT;
+#ifndef S_SPLINT_S
+ t.tv_sec = timeout/1000;
+ t.tv_usec = (timeout%1000)*1000;
+#endif
if(master->http) {
/* perform http fetch */
/* store http port number into sockaddr,
* unless someone used unbound's host@port notation */
+ xfr->task_transfer->on_ixfr = 0;
if(strchr(master->host, '@') == NULL)
sockaddr_store_port(&addr, addrlen, master->port);
xfr->task_transfer->cp = outnet_comm_point_for_http(
env->outnet, auth_xfer_transfer_http_callback, xfr,
- &addr, addrlen, AUTH_TRANSFER_TIMEOUT, master->ssl,
- master->host, master->file);
+ &addr, addrlen, -1, master->ssl, master->host,
+ master->file);
if(!xfr->task_transfer->cp) {
- char zname[255+1];
+ char zname[255+1], as[256];
dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create http cp "
- "connection for %s to %s", zname,
- master->host);
+ "connection for %s to %s", zname, as);
return 0;
}
+ comm_timer_set(xfr->task_transfer->timer, &t);
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1], as[256];
+ dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
+ verbose(VERB_ALGO, "auth zone %s transfer next HTTP fetch from %s started", zname, as);
+ }
return 1;
}
@@ -5091,14 +5140,24 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
/* connect on fd */
xfr->task_transfer->cp = outnet_comm_point_for_tcp(env->outnet,
auth_xfer_transfer_tcp_callback, xfr, &addr, addrlen,
- env->scratch_buffer, AUTH_TRANSFER_TIMEOUT);
+ env->scratch_buffer, -1,
+ auth_name != NULL, auth_name);
if(!xfr->task_transfer->cp) {
- char zname[255+1];
- dname_str(xfr->name, zname);
+ char zname[255+1], as[256];
+ dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create tcp cp connection for "
- "xfr %s to %s", zname, master->host);
+ "xfr %s to %s", zname, as);
return 0;
}
+ comm_timer_set(xfr->task_transfer->timer, &t);
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1], as[256];
+ dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
+ verbose(VERB_ALGO, "auth zone %s transfer next %s fetch from %s started", zname,
+ (xfr->task_transfer->on_ixfr?"IXFR":"AXFR"), as);
+ }
return 1;
}
@@ -5116,6 +5175,11 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
* and we may then get an instant cache response,
* and that calls the callback just like a full
* lookup and lookup failures also call callback */
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s transfer next target lookup", zname);
+ }
lock_basic_unlock(&xfr->lock);
return;
}
@@ -5134,6 +5198,11 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
/* failed to fetch, next master */
xfr_transfer_nextmaster(xfr);
}
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s transfer failed, wait", zname);
+ }
/* we failed to fetch the zone, move to wait task
* use the shorter retry timeout */
@@ -5231,8 +5300,26 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
if(answer) {
xfr_master_add_addrs(xfr->task_transfer->
lookup_target, answer, wanted_qtype);
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has nodata", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
+ }
+ }
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has no answer", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
}
}
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup failed", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
+ }
}
if(xfr->task_transfer->lookup_target->list &&
xfr->task_transfer->lookup_target == xfr_transfer_current_master(xfr))
@@ -5616,6 +5703,46 @@ process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env)
xfr_transfer_nexttarget_or_end(xfr, env);
}
+/** callback for the task_transfer timer */
+void
+auth_xfer_transfer_timer_callback(void* arg)
+{
+ struct auth_xfer* xfr = (struct auth_xfer*)arg;
+ struct module_env* env;
+ int gonextonfail = 1;
+ log_assert(xfr->task_transfer);
+ lock_basic_lock(&xfr->lock);
+ env = xfr->task_transfer->env;
+ if(env->outnet->want_to_quit) {
+ lock_basic_unlock(&xfr->lock);
+ return; /* stop on quit */
+ }
+
+ verbose(VERB_ALGO, "xfr stopped, connection timeout to %s",
+ xfr->task_transfer->master->host);
+
+ /* see if IXFR caused the failure, if so, try AXFR */
+ if(xfr->task_transfer->on_ixfr) {
+ xfr->task_transfer->ixfr_possible_timeout_count++;
+ if(xfr->task_transfer->ixfr_possible_timeout_count >=
+ NUM_TIMEOUTS_FALLBACK_IXFR) {
+ verbose(VERB_ALGO, "xfr to %s, fallback "
+ "from IXFR to AXFR (because of timeouts)",
+ xfr->task_transfer->master->host);
+ xfr->task_transfer->ixfr_fail = 1;
+ gonextonfail = 0;
+ }
+ }
+
+ /* delete transferred data from list */
+ auth_chunks_delete(xfr->task_transfer);
+ comm_point_delete(xfr->task_transfer->cp);
+ xfr->task_transfer->cp = NULL;
+ if(gonextonfail)
+ xfr_transfer_nextmaster(xfr);
+ xfr_transfer_nexttarget_or_end(xfr, env);
+}
+
/** callback for task_transfer tcp connections */
int
auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
@@ -5632,6 +5759,8 @@ auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
lock_basic_unlock(&xfr->lock);
return 0; /* stop on quit */
}
+ /* stop the timer */
+ comm_timer_disable(xfr->task_transfer->timer);
if(err != NETEVENT_NOERROR) {
/* connection failed, closed, or timeout */
@@ -5712,6 +5841,8 @@ auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
return 0; /* stop on quit */
}
verbose(VERB_ALGO, "auth zone transfer http callback");
+ /* stop the timer */
+ comm_timer_disable(xfr->task_transfer->timer);
if(err != NETEVENT_NOERROR && err != NETEVENT_DONE) {
/* connection failed, closed, or timeout */
@@ -5809,6 +5940,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
struct timeval t;
/* pick master */
struct auth_master* master = xfr_probe_current_master(xfr);
+ char *auth_name = NULL;
if(!master) return 0;
if(master->allow_notify) return 0; /* only for notify */
if(master->http) return 0; /* only masters get SOA UDP probe,
@@ -5819,7 +5951,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
addrlen = xfr->task_probe->scan_addr->addrlen;
memmove(&addr, &xfr->task_probe->scan_addr->addr, addrlen);
} else {
- if(!extstrtoaddr(master->host, &addr, &addrlen)) {
+ if(!authextstrtoaddr(master->host, &addr, &addrlen, &auth_name)) {
/* the ones that are not in addr format are supposed
* to be looked up. The lookup has failed however,
* so skip them */
@@ -5829,6 +5961,18 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
zname, master->host);
return 0;
}
+ if (auth_name != NULL) {
+ if (addr.ss_family == AF_INET
+ && ntohs(((struct sockaddr_in *)&addr)->sin_port)
+ == env->cfg->ssl_port)
+ ((struct sockaddr_in *)&addr)->sin_port
+ = htons(env->cfg->port);
+ else if (addr.ss_family == AF_INET6
+ && ntohs(((struct sockaddr_in6 *)&addr)->sin6_port)
+ == env->cfg->ssl_port)
+ ((struct sockaddr_in6 *)&addr)->sin6_port
+ = htons(env->cfg->port);
+ }
}
/* create packet */
@@ -5838,14 +5982,26 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
xfr->task_probe->id = (uint16_t)(ub_random(env->rnd)&0xffff);
xfr_create_soa_probe_packet(xfr, env->scratch_buffer,
xfr->task_probe->id);
+ /* we need to remove the cp if we have a different ip4/ip6 type now */
+ if(xfr->task_probe->cp &&
+ ((xfr->task_probe->cp_is_ip6 && !addr_is_ip6(&addr, addrlen)) ||
+ (!xfr->task_probe->cp_is_ip6 && addr_is_ip6(&addr, addrlen)))
+ ) {
+ comm_point_delete(xfr->task_probe->cp);
+ xfr->task_probe->cp = NULL;
+ }
if(!xfr->task_probe->cp) {
+ if(addr_is_ip6(&addr, addrlen))
+ xfr->task_probe->cp_is_ip6 = 1;
+ else xfr->task_probe->cp_is_ip6 = 0;
xfr->task_probe->cp = outnet_comm_point_for_udp(env->outnet,
auth_xfer_probe_udp_callback, xfr, &addr, addrlen);
if(!xfr->task_probe->cp) {
- char zname[255+1];
+ char zname[255+1], as[256];
dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create udp cp for "
- "probe %s to %s", zname, master->host);
+ "probe %s to %s", zname, as);
return 0;
}
}
@@ -5861,12 +6017,20 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
/* send udp packet */
if(!comm_point_send_udp_msg(xfr->task_probe->cp, env->scratch_buffer,
(struct sockaddr*)&addr, addrlen)) {
- char zname[255+1];
+ char zname[255+1], as[256];
dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "failed to send soa probe for %s to %s",
- zname, master->host);
+ zname, as);
return 0;
}
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1], as[256];
+ dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
+ verbose(VERB_ALGO, "auth zone %s soa probe sent to %s", zname,
+ as);
+ }
xfr->task_probe->timeout = timeout;
#ifndef S_SPLINT_S
t.tv_sec = timeout/1000;
@@ -5891,6 +6055,11 @@ auth_xfer_probe_timer_callback(void* arg)
return; /* stop on quit */
}
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s soa probe timeout", zname);
+ }
if(xfr->task_probe->timeout <= AUTH_PROBE_TIMEOUT_STOP) {
/* try again with bigger timeout */
if(xfr_probe_send_probe(xfr, env, xfr->task_probe->timeout*2)) {
@@ -6078,6 +6247,11 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
* and we may then get an instant cache response,
* and that calls the callback just like a full
* lookup and lookup failures also call callback */
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s probe next target lookup", zname);
+ }
lock_basic_unlock(&xfr->lock);
return;
}
@@ -6086,9 +6260,19 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
/* probe of list has ended. Create or refresh the list of of
* allow_notify addrs */
probe_copy_masters_for_allow_notify(xfr);
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s probe: notify addrs updated", zname);
+ }
if(xfr->task_probe->only_lookup) {
/* only wanted lookups for copy, stop probe and start wait */
xfr->task_probe->only_lookup = 0;
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s probe: finished only_lookup", zname);
+ }
xfr_probe_disown(xfr);
if(xfr->task_nextprobe->worker == NULL)
xfr_set_timeout(xfr, env, 0, 0);
@@ -6110,13 +6294,22 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
/* done with probe sequence, wait */
if(xfr->task_probe->have_new_lease) {
/* if zone not updated, start the wait timer again */
- verbose(VERB_ALGO, "auth_zone unchanged, new lease, wait");
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth_zone %s unchanged, new lease, wait", zname);
+ }
xfr_probe_disown(xfr);
if(xfr->have_zone)
xfr->lease_time = *env->now;
if(xfr->task_nextprobe->worker == NULL)
xfr_set_timeout(xfr, env, 0, 0);
} else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s soa probe failed, wait to retry", zname);
+ }
/* we failed to send this as well, move to the wait task,
* use the shorter retry timeout */
xfr_probe_disown(xfr);
@@ -6161,7 +6354,25 @@ void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
if(answer) {
xfr_master_add_addrs(xfr->task_probe->
lookup_target, answer, wanted_qtype);
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has nodata", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
+ }
}
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has no address", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
+ }
+ }
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup failed", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
}
}
if(xfr->task_probe->lookup_target->list &&
diff --git a/sbin/unwind/libunbound/services/authzone.h b/sbin/unwind/libunbound/services/authzone.h
index 4706803a86b..a695bd029b5 100644
--- a/sbin/unwind/libunbound/services/authzone.h
+++ b/sbin/unwind/libunbound/services/authzone.h
@@ -327,6 +327,8 @@ struct auth_probe {
/** the SOA probe udp event.
* on the workers event base. */
struct comm_point* cp;
+ /** is the cp for ip6 or ip4 */
+ int cp_is_ip6;
/** timeout for packets.
* on the workers event base. */
struct comm_timer* timer;
@@ -398,6 +400,9 @@ struct auth_transfer {
/** the transfer (TCP) to the master.
* on the workers event base. */
struct comm_point* cp;
+ /** timeout for the transfer.
+ * on the workers event base. */
+ struct comm_timer* timer;
};
/** list of addresses */
@@ -647,6 +652,8 @@ int auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
struct comm_reply* repinfo);
/** xfer probe timeout callback, part of task_probe */
void auth_xfer_probe_timer_callback(void* arg);
+/** xfer transfer timeout callback, part of task_transfer */
+void auth_xfer_transfer_timer_callback(void* arg);
/** mesh callback for task_probe on lookup of host names */
void auth_xfer_probe_lookup_callback(void* arg, int rcode,
struct sldns_buffer* buf, enum sec_status sec, char* why_bogus,
diff --git a/sbin/unwind/libunbound/services/cache/dns.c b/sbin/unwind/libunbound/services/cache/dns.c
index 47611ac5aef..aa4efec73f4 100644
--- a/sbin/unwind/libunbound/services/cache/dns.c
+++ b/sbin/unwind/libunbound/services/cache/dns.c
@@ -40,6 +40,7 @@
*/
#include "config.h"
#include "iterator/iter_delegpt.h"
+#include "iterator/iter_utils.h"
#include "validator/val_nsec.h"
#include "validator/val_utils.h"
#include "services/cache/dns.h"
@@ -728,6 +729,8 @@ fill_any(struct module_env* env,
if(!msg) {
return NULL;
}
+ /* set NOTIMPL for RFC 8482 */
+ msg->rep->flags |= LDNS_RCODE_NOTIMPL;
msg->rep->security = sec_status_indeterminate;
return msg;
}
@@ -912,12 +915,15 @@ dns_cache_lookup(struct module_env* env,
struct dns_msg* msg;
if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
&& data->security == sec_status_secure
+ && (data->an_numrrsets == 0 ||
+ ntohs(data->rrsets[0]->rk.type) != LDNS_RR_TYPE_CNAME)
&& (msg=tomsg(env, &k, data, region, now, scratch))){
lock_rw_unlock(&e->lock);
msg->qinfo.qname=qname;
msg->qinfo.qname_len=qnamelen;
/* check that DNSSEC really works out */
msg->rep->security = sec_status_unchecked;
+ iter_scrub_nxdomain(msg);
return msg;
}
lock_rw_unlock(&e->lock);
diff --git a/sbin/unwind/libunbound/services/listen_dnsport.c b/sbin/unwind/libunbound/services/listen_dnsport.c
index e74d1abcffc..7e2afd843be 100644
--- a/sbin/unwind/libunbound/services/listen_dnsport.c
+++ b/sbin/unwind/libunbound/services/listen_dnsport.c
@@ -851,13 +851,16 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
#ifdef ENOPROTOOPT
/* squelch ENOPROTOOPT: freebsd server mode with kernel support
disabled, except when verbosity enabled for debugging */
- if(errno != ENOPROTOOPT || verbosity >= 3)
+ if(errno != ENOPROTOOPT || verbosity >= 3) {
#endif
if(errno == EPERM) {
log_warn("Setting TCP Fast Open as server failed: %s ; this could likely be because sysctl net.inet.tcp.fastopen.enabled, net.inet.tcp.fastopen.server_enable, or net.ipv4.tcp_fastopen is disabled", strerror(errno));
} else {
log_err("Setting TCP Fast Open as server failed: %s", strerror(errno));
}
+#ifdef ENOPROTOOPT
+ }
+#endif
}
#endif
return s;
@@ -1749,6 +1752,7 @@ tcp_req_info_handle_readdone(struct tcp_req_info* req)
req->is_drop = 0;
req->is_reply = 0;
req->in_worker_handle = 1;
+ sldns_buffer_set_limit(req->spool_buffer, 0);
/* handle the current request */
/* this calls the worker handle request routine that could give
* a cache response, or localdata response, or drop the reply,
@@ -1771,24 +1775,12 @@ tcp_req_info_handle_readdone(struct tcp_req_info* req)
* If mesh failed to add a new entry and called commpoint_drop_reply.
* Then the mesh state has been cleared. */
if(req->is_drop) {
- /* we can now call drop_reply without recursing into ourselves
- * whilst in the callback */
- /* we have to close the stream because there is no reply,
- * no servfail to send, but the query needs an action, for
- * a stream that is close the connection */
- sldns_buffer_clear(c->buffer);
- comm_point_drop_reply(&c->repinfo);
+ /* the reply has been dropped, stream has been closed. */
return;
}
/* If mesh failed(mallocfail) and called commpoint_send_reply with
* something like servfail then we pick up that reply below. */
if(req->is_reply) {
- /* reply from mesh is in the spool_buffer */
- sldns_buffer_clear(c->buffer);
- sldns_buffer_write(c->buffer,
- sldns_buffer_begin(req->spool_buffer),
- sldns_buffer_limit(req->spool_buffer));
- sldns_buffer_flip(c->buffer);
goto send_it;
}
@@ -1867,7 +1859,14 @@ void
tcp_req_info_send_reply(struct tcp_req_info* req)
{
if(req->in_worker_handle) {
- /* It is in the right buffer to answer straight away */
+ /* reply from mesh is in the spool_buffer */
+ /* copy now, so that the spool buffer is free for other tasks
+ * before the callback is done */
+ sldns_buffer_clear(req->cp->buffer);
+ sldns_buffer_write(req->cp->buffer,
+ sldns_buffer_begin(req->spool_buffer),
+ sldns_buffer_limit(req->spool_buffer));
+ sldns_buffer_flip(req->cp->buffer);
req->is_reply = 1;
return;
}
diff --git a/sbin/unwind/libunbound/services/mesh.c b/sbin/unwind/libunbound/services/mesh.c
index bee0f76a4ad..59ee9a08ec0 100644
--- a/sbin/unwind/libunbound/services/mesh.c
+++ b/sbin/unwind/libunbound/services/mesh.c
@@ -354,6 +354,10 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
int was_detached = 0;
int was_noreply = 0;
int added = 0;
+ struct sldns_buffer* r_buffer = rep->c->buffer;
+ if(rep->c->tcp_req_info) {
+ r_buffer = rep->c->tcp_req_info->spool_buffer;
+ }
if(!unique)
s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
/* does this create a new reply state? */
@@ -389,7 +393,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
edns->opt_list = NULL;
- error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
+ error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
return;
@@ -405,7 +409,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
edns->opt_list = NULL;
- error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
+ error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
return;
@@ -434,7 +438,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
edns->opt_list = NULL;
- error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
+ error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
if(added)
@@ -1192,12 +1196,16 @@ void mesh_query_done(struct mesh_state* mstate)
comm_point_drop_reply(&r->query_reply);
else {
struct sldns_buffer* r_buffer = r->query_reply.c->buffer;
- if(r->query_reply.c->tcp_req_info)
+ if(r->query_reply.c->tcp_req_info) {
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
+ prev_buffer = NULL;
+ }
mesh_send_reply(mstate, mstate->s.return_rcode, rep,
r, r_buffer, prev, prev_buffer);
- if(r->query_reply.c->tcp_req_info)
+ if(r->query_reply.c->tcp_req_info) {
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
+ r_buffer = NULL;
+ }
prev = r;
prev_buffer = r_buffer;
}
@@ -1341,21 +1349,14 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
log_assert(qinfo->local_alias->rrset->rk.dname ==
sldns_buffer_at(rep->c->buffer, LDNS_HEADER_SIZE));
- d = regional_alloc_init(s->s.region, dsrc,
- sizeof(struct packed_rrset_data)
- + sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t));
+ /* the rrset is not packed, like in the cache, but it is
+ * individualy allocated with an allocator from localzone. */
+ d = regional_alloc_zero(s->s.region, sizeof(*d));
if(!d)
return 0;
r->local_alias->rrset->entry.data = d;
- d->rr_len = (size_t*)((uint8_t*)d +
- sizeof(struct packed_rrset_data));
- d->rr_data = (uint8_t**)&(d->rr_len[1]);
- d->rr_ttl = (time_t*)&(d->rr_data[1]);
- d->rr_len[0] = dsrc->rr_len[0];
- d->rr_ttl[0] = dsrc->rr_ttl[0];
- d->rr_data[0] = regional_alloc_init(s->s.region,
- dsrc->rr_data[0], d->rr_len[0]);
- if(!d->rr_data[0])
+ if(!rrset_insert_rr(s->s.region, d, dsrc->rr_data[0],
+ dsrc->rr_len[0], dsrc->rr_ttl[0], "CNAME local alias"))
return 0;
} else
r->local_alias = NULL;
diff --git a/sbin/unwind/libunbound/services/outside_network.c b/sbin/unwind/libunbound/services/outside_network.c
index 16d63df4395..0323f1b30c9 100644
--- a/sbin/unwind/libunbound/services/outside_network.c
+++ b/sbin/unwind/libunbound/services/outside_network.c
@@ -364,6 +364,8 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
comm_point_close(pend->c);
return 0;
}
+ verbose(VERB_ALGO, "the query is using TLS encryption, for %s",
+ (w->tls_auth_name?w->tls_auth_name:"an unauthenticated connection"));
#ifdef USE_WINSOCK
comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
#endif
@@ -404,6 +406,8 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
}
SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL);
}
+#else
+ verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
#endif /* HAVE_SSL_SET1_HOST */
}
w->pkt = NULL;
@@ -2277,11 +2281,60 @@ outnet_comm_point_for_udp(struct outside_network* outnet,
return cp;
}
+/** setup SSL for comm point */
+static int
+setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet,
+ int fd, char* host)
+{
+ cp->ssl = outgoing_ssl_fd(outnet->sslctx, fd);
+ if(!cp->ssl) {
+ log_err("cannot create SSL object");
+ return 0;
+ }
+#ifdef USE_WINSOCK
+ comm_point_tcp_win_bio_cb(cp, cp->ssl);
+#endif
+ cp->ssl_shake_state = comm_ssl_shake_write;
+ /* https verification */
+#ifdef HAVE_SSL_SET1_HOST
+ if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
+ /* because we set SSL_VERIFY_PEER, in netevent in
+ * ssl_handshake, it'll check if the certificate
+ * verification has succeeded */
+ /* SSL_VERIFY_PEER is set on the sslctx */
+ /* and the certificates to verify with are loaded into
+ * it with SSL_load_verify_locations or
+ * SSL_CTX_set_default_verify_paths */
+ /* setting the hostname makes openssl verify the
+ * host name in the x509 certificate in the
+ * SSL connection*/
+ if(!SSL_set1_host(cp->ssl, host)) {
+ log_err("SSL_set1_host failed");
+ return 0;
+ }
+ }
+#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+ /* openssl 1.0.2 has this function that can be used for
+ * set1_host like verification */
+ if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
+ X509_VERIFY_PARAM* param = SSL_get0_param(cp->ssl);
+ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ if(!X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) {
+ log_err("X509_VERIFY_PARAM_set1_host failed");
+ return 0;
+ }
+ }
+#else
+ (void)host;
+#endif /* HAVE_SSL_SET1_HOST */
+ return 1;
+}
+
struct comm_point*
outnet_comm_point_for_tcp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
- sldns_buffer* query, int timeout)
+ sldns_buffer* query, int timeout, int ssl, char* host)
{
struct comm_point* cp;
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
@@ -2301,6 +2354,16 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
}
cp->repinfo.addrlen = to_addrlen;
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
+
+ /* setup for SSL (if needed) */
+ if(ssl) {
+ if(!setup_comm_ssl(cp, outnet, fd, host)) {
+ log_err("cannot setup XoT");
+ comm_point_delete(cp);
+ return NULL;
+ }
+ }
+
/* set timeout on TCP connection */
comm_point_start_listening(cp, fd, timeout);
/* copy scratch buffer to cp->buffer */
@@ -2357,48 +2420,11 @@ outnet_comm_point_for_http(struct outside_network* outnet,
/* setup for SSL (if needed) */
if(ssl) {
- cp->ssl = outgoing_ssl_fd(outnet->sslctx, fd);
- if(!cp->ssl) {
+ if(!setup_comm_ssl(cp, outnet, fd, host)) {
log_err("cannot setup https");
comm_point_delete(cp);
return NULL;
}
-#ifdef USE_WINSOCK
- comm_point_tcp_win_bio_cb(cp, cp->ssl);
-#endif
- cp->ssl_shake_state = comm_ssl_shake_write;
- /* https verification */
-#ifdef HAVE_SSL_SET1_HOST
- if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
- /* because we set SSL_VERIFY_PEER, in netevent in
- * ssl_handshake, it'll check if the certificate
- * verification has succeeded */
- /* SSL_VERIFY_PEER is set on the sslctx */
- /* and the certificates to verify with are loaded into
- * it with SSL_load_verify_locations or
- * SSL_CTX_set_default_verify_paths */
- /* setting the hostname makes openssl verify the
- * host name in the x509 certificate in the
- * SSL connection*/
- if(!SSL_set1_host(cp->ssl, host)) {
- log_err("SSL_set1_host failed");
- comm_point_delete(cp);
- return NULL;
- }
- }
-#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
- /* openssl 1.0.2 has this function that can be used for
- * set1_host like verification */
- if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
- X509_VERIFY_PARAM* param = SSL_get0_param(cp->ssl);
- X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
- if(!X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) {
- log_err("X509_VERIFY_PARAM_set1_host failed");
- comm_point_delete(cp);
- return NULL;
- }
- }
-#endif /* HAVE_SSL_SET1_HOST */
}
/* set timeout on TCP connection */
diff --git a/sbin/unwind/libunbound/services/outside_network.h b/sbin/unwind/libunbound/services/outside_network.h
index 48ef03edba7..3456a3da38b 100644
--- a/sbin/unwind/libunbound/services/outside_network.h
+++ b/sbin/unwind/libunbound/services/outside_network.h
@@ -570,12 +570,14 @@ struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
* @param timeout: timeout for the TCP connection.
* timeout in milliseconds, or -1 for no (change to the) timeout.
* So seconds*1000.
+ * @param ssl: set to true for TLS.
+ * @param host: hostname for host name verification of TLS (or NULL if no TLS).
* @return tcp_out commpoint, or NULL.
*/
struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
- struct sldns_buffer* query, int timeout);
+ struct sldns_buffer* query, int timeout, int ssl, char* host);
/**
* Create http commpoint suitable for communication to the destination.
diff --git a/sbin/unwind/libunbound/util/alloc.c b/sbin/unwind/libunbound/util/alloc.c
index 908b1f42361..7e9618931ca 100644
--- a/sbin/unwind/libunbound/util/alloc.c
+++ b/sbin/unwind/libunbound/util/alloc.c
@@ -376,6 +376,7 @@ void *unbound_stat_malloc(size_t size)
{
void* res;
if(size == 0) size = 1;
+ log_assert(size <= SIZE_MAX-16);
res = malloc(size+16);
if(!res) return NULL;
unbound_mem_alloc += size;
@@ -398,6 +399,7 @@ void *unbound_stat_calloc(size_t nmemb, size_t size)
if(nmemb != 0 && INT_MAX/nmemb < size)
return NULL; /* integer overflow check */
s = (nmemb*size==0)?(size_t)1:nmemb*size;
+ log_assert(s <= SIZE_MAX-16);
res = calloc(1, s+16);
if(!res) return NULL;
log_info("stat %p=calloc(%u, %u)", res+16, (unsigned)nmemb, (unsigned)size);
@@ -447,6 +449,7 @@ void *unbound_stat_realloc(void *ptr, size_t size)
/* nothing changes */
return ptr;
}
+ log_assert(size <= SIZE_MAX-16);
res = malloc(size+16);
if(!res) return NULL;
unbound_mem_alloc += size;
@@ -521,7 +524,9 @@ void *unbound_stat_malloc_lite(size_t size, const char* file, int line,
const char* func)
{
/* [prefix .. len .. actual data .. suffix] */
- void* res = malloc(size+lite_pad*2+sizeof(size_t));
+ void* res;
+ log_assert(size <= SIZE_MAX-(lite_pad*2+sizeof(size_t)));
+ res = malloc(size+lite_pad*2+sizeof(size_t));
if(!res) return NULL;
memmove(res, lite_pre, lite_pad);
memmove(res+lite_pad, &size, sizeof(size_t));
@@ -538,6 +543,7 @@ void *unbound_stat_calloc_lite(size_t nmemb, size_t size, const char* file,
if(nmemb != 0 && INT_MAX/nmemb < size)
return NULL; /* integer overflow check */
req = nmemb * size;
+ log_assert(req <= SIZE_MAX-(lite_pad*2+sizeof(size_t)));
res = malloc(req+lite_pad*2+sizeof(size_t));
if(!res) return NULL;
memmove(res, lite_pre, lite_pad);
diff --git a/sbin/unwind/libunbound/util/data/msgreply.h b/sbin/unwind/libunbound/util/data/msgreply.h
index a455c4d2b37..8d75f9b12f3 100644
--- a/sbin/unwind/libunbound/util/data/msgreply.h
+++ b/sbin/unwind/libunbound/util/data/msgreply.h
@@ -157,7 +157,7 @@ struct reply_info {
time_t prefetch_ttl;
/**
- * Reply TTL extended with serve exipred TTL, to limit time to serve
+ * Reply TTL extended with serve expired TTL, to limit time to serve
* expired message.
*/
time_t serve_expired_ttl;
diff --git a/sbin/unwind/libunbound/util/fptr_wlist.c b/sbin/unwind/libunbound/util/fptr_wlist.c
index 02f85e8dc4a..94d23fa3a32 100644
--- a/sbin/unwind/libunbound/util/fptr_wlist.c
+++ b/sbin/unwind/libunbound/util/fptr_wlist.c
@@ -127,6 +127,7 @@ fptr_whitelist_comm_timer(void (*fptr)(void*))
#endif
else if(fptr == &auth_xfer_timer) return 1;
else if(fptr == &auth_xfer_probe_timer_callback) return 1;
+ else if(fptr == &auth_xfer_transfer_timer_callback) return 1;
return 0;
}
diff --git a/sbin/unwind/libunbound/util/iana_ports.inc b/sbin/unwind/libunbound/util/iana_ports.inc
index 5ead47f0f66..aa972a67bd5 100644
--- a/sbin/unwind/libunbound/util/iana_ports.inc
+++ b/sbin/unwind/libunbound/util/iana_ports.inc
@@ -4768,6 +4768,7 @@
8088,
8097,
8100,
+8111,
8115,
8116,
8118,
@@ -4864,6 +4865,7 @@
8805,
8807,
8808,
+8809,
8873,
8880,
8883,
diff --git a/sbin/unwind/libunbound/util/net_help.c b/sbin/unwind/libunbound/util/net_help.c
index 2b1be92460b..13bcdf8085b 100644
--- a/sbin/unwind/libunbound/util/net_help.c
+++ b/sbin/unwind/libunbound/util/net_help.c
@@ -802,6 +802,16 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem)
log_crypto_err("could not SSL_CTX_new");
return NULL;
}
+ if(!key || key[0] == 0) {
+ log_err("error: no tls-service-key file specified");
+ SSL_CTX_free(ctx);
+ return NULL;
+ }
+ if(!pem || pem[0] == 0) {
+ log_err("error: no tls-service-pem file specified");
+ SSL_CTX_free(ctx);
+ return NULL;
+ }
if(!listen_sslctx_setup(ctx)) {
SSL_CTX_free(ctx);
return NULL;
@@ -1235,7 +1245,12 @@ listen_sslctx_delete_ticket_keys(void)
struct tls_session_ticket_key *key;
if(!ticket_keys) return;
for(key = ticket_keys; key->key_name != NULL; key++) {
- memset(key->key_name, 0xdd, 80); /* wipe key data from memory*/
+ /* wipe key data from memory*/
+#ifdef HAVE_EXPLICIT_BZERO
+ explicit_bzero(key->key_name, 80);
+#else
+ memset(key->key_name, 0xdd, 80);
+#endif
free(key->key_name);
}
free(ticket_keys);
diff --git a/sbin/unwind/libunbound/util/netevent.c b/sbin/unwind/libunbound/util/netevent.c
index f33e44058b1..9e2ba92b5fd 100644
--- a/sbin/unwind/libunbound/util/netevent.c
+++ b/sbin/unwind/libunbound/util/netevent.c
@@ -178,7 +178,7 @@ comm_base_create(int sigs)
}
ub_comm_base_now(b);
ub_get_event_sys(b->eb->base, &evnm, &evsys, &evmethod);
- verbose(VERB_ALGO, "%s %s user %s method.", evnm, evsys, evmethod);
+ verbose(VERB_ALGO, "%s %s uses %s method.", evnm, evsys, evmethod);
return b;
}
@@ -926,6 +926,14 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
}
/* accept incoming connection. */
c_hdl = c->tcp_free;
+ /* clear leftover flags from previous use, and then set the
+ * correct event base for the event structure for libevent */
+ ub_event_free(c_hdl->ev->ev);
+ c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, comm_point_tcp_handle_callback, c_hdl);
+ if(!c_hdl->ev->ev) {
+ log_warn("could not ub_event_new, dropped tcp");
+ return;
+ }
log_assert(fd != -1);
(void)fd;
new_fd = comm_point_perform_accept(c, &c_hdl->repinfo.addr,
@@ -1184,6 +1192,10 @@ ssl_handle_read(struct comm_point* c)
comm_point_listen_for_rw(c, 0, 1);
return 1;
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
if(errno != 0)
log_err("SSL_read syscall: %s",
strerror(errno));
@@ -1228,6 +1240,10 @@ ssl_handle_read(struct comm_point* c)
comm_point_listen_for_rw(c, 0, 1);
return 1;
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
if(errno != 0)
log_err("SSL_read syscall: %s",
strerror(errno));
@@ -1288,13 +1304,17 @@ ssl_handle_write(struct comm_point* c)
if(want == SSL_ERROR_ZERO_RETURN) {
return 0; /* closed */
} else if(want == SSL_ERROR_WANT_READ) {
- c->ssl_shake_state = comm_ssl_shake_read;
+ c->ssl_shake_state = comm_ssl_shake_hs_read;
comm_point_listen_for_rw(c, 1, 0);
return 1; /* wait for read condition */
} else if(want == SSL_ERROR_WANT_WRITE) {
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1; /* write more later */
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ return 0; /* silence 'broken pipe' */
+#endif
if(errno != 0)
log_err("SSL_write syscall: %s",
strerror(errno));
@@ -1322,13 +1342,17 @@ ssl_handle_write(struct comm_point* c)
if(want == SSL_ERROR_ZERO_RETURN) {
return 0; /* closed */
} else if(want == SSL_ERROR_WANT_READ) {
- c->ssl_shake_state = comm_ssl_shake_read;
+ c->ssl_shake_state = comm_ssl_shake_hs_read;
comm_point_listen_for_rw(c, 1, 0);
return 1; /* wait for read condition */
} else if(want == SSL_ERROR_WANT_WRITE) {
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1; /* write more later */
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ return 0; /* silence 'broken pipe' */
+#endif
if(errno != 0)
log_err("SSL_write syscall: %s",
strerror(errno));
@@ -1543,7 +1567,6 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
iov[1].iov_base = sldns_buffer_begin(buffer);
iov[1].iov_len = sldns_buffer_limit(buffer);
log_assert(iov[0].iov_len > 0);
- log_assert(iov[1].iov_len > 0);
msg.msg_name = &c->repinfo.addr;
msg.msg_namelen = c->repinfo.addrlen;
msg.msg_iov = iov;
@@ -1610,7 +1633,6 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
iov[1].iov_base = sldns_buffer_begin(buffer);
iov[1].iov_len = sldns_buffer_limit(buffer);
log_assert(iov[0].iov_len > 0);
- log_assert(iov[1].iov_len > 0);
r = writev(fd, iov, 2);
#else /* HAVE_WRITEV */
r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_byte_count),
@@ -1624,6 +1646,10 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
#endif
if(errno == EINTR || errno == EAGAIN)
return 1;
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
# ifdef HAVE_WRITEV
log_err_addr("tcp writev", strerror(errno),
&c->repinfo.addr, c->repinfo.addrlen);
@@ -1641,6 +1667,8 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
UB_EV_WRITE);
return 1;
}
+ if(WSAGetLastError() == WSAECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
log_err_addr("tcp send s",
wsa_strerror(WSAGetLastError()),
&c->repinfo.addr, c->repinfo.addrlen);
@@ -1664,6 +1692,10 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return 1;
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
log_err_addr("tcp send r", strerror(errno),
&c->repinfo.addr, c->repinfo.addrlen);
#else
@@ -1673,6 +1705,8 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1;
}
+ if(WSAGetLastError() == WSAECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
log_err_addr("tcp send r", wsa_strerror(WSAGetLastError()),
&c->repinfo.addr, c->repinfo.addrlen);
#endif
@@ -1738,6 +1772,16 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
}
#endif
+ if(event&UB_EV_TIMEOUT) {
+ verbose(VERB_QUERY, "tcp took too long, dropped");
+ reclaim_tcp_handler(c);
+ if(!c->tcp_do_close) {
+ fptr_ok(fptr_whitelist_comm_point(c->callback));
+ (void)(*c->callback)(c, c->cb_arg,
+ NETEVENT_TIMEOUT, NULL);
+ }
+ return;
+ }
if(event&UB_EV_READ) {
int has_tcpq = (c->tcp_req_info != NULL);
if(!comm_point_tcp_handle_read(fd, c, 0)) {
@@ -1768,16 +1812,6 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
tcp_req_info_read_again(fd, c);
return;
}
- if(event&UB_EV_TIMEOUT) {
- verbose(VERB_QUERY, "tcp took too long, dropped");
- reclaim_tcp_handler(c);
- if(!c->tcp_do_close) {
- fptr_ok(fptr_whitelist_comm_point(c->callback));
- (void)(*c->callback)(c, c->cb_arg,
- NETEVENT_TIMEOUT, NULL);
- }
- return;
- }
log_err("Ignored event %d for tcphdl.", event);
}
@@ -1826,6 +1860,10 @@ ssl_http_read_more(struct comm_point* c)
comm_point_listen_for_rw(c, 0, 1);
return 1;
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
if(errno != 0)
log_err("SSL_read syscall: %s",
strerror(errno));
@@ -2268,12 +2306,16 @@ ssl_http_write_more(struct comm_point* c)
if(want == SSL_ERROR_ZERO_RETURN) {
return 0; /* closed */
} else if(want == SSL_ERROR_WANT_READ) {
- c->ssl_shake_state = comm_ssl_shake_read;
+ c->ssl_shake_state = comm_ssl_shake_hs_read;
comm_point_listen_for_rw(c, 1, 0);
return 1; /* wait for read condition */
} else if(want == SSL_ERROR_WANT_WRITE) {
return 1; /* write more later */
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ return 0; /* silence 'broken pipe' */
+#endif
if(errno != 0)
log_err("SSL_write syscall: %s",
strerror(errno));
@@ -2382,6 +2424,16 @@ comm_point_http_handle_callback(int fd, short event, void* arg)
log_assert(c->type == comm_http);
ub_comm_base_now(c->ev->base);
+ if(event&UB_EV_TIMEOUT) {
+ verbose(VERB_QUERY, "http took too long, dropped");
+ reclaim_http_handler(c);
+ if(!c->tcp_do_close) {
+ fptr_ok(fptr_whitelist_comm_point(c->callback));
+ (void)(*c->callback)(c, c->cb_arg,
+ NETEVENT_TIMEOUT, NULL);
+ }
+ return;
+ }
if(event&UB_EV_READ) {
if(!comm_point_http_handle_read(fd, c)) {
reclaim_http_handler(c);
@@ -2406,16 +2458,6 @@ comm_point_http_handle_callback(int fd, short event, void* arg)
}
return;
}
- if(event&UB_EV_TIMEOUT) {
- verbose(VERB_QUERY, "http took too long, dropped");
- reclaim_http_handler(c);
- if(!c->tcp_do_close) {
- fptr_ok(fptr_whitelist_comm_point(c->callback));
- (void)(*c->callback)(c, c->cb_arg,
- NETEVENT_TIMEOUT, NULL);
- }
- return;
- }
log_err("Ignored event %d for httphdl.", event);
}
@@ -3138,8 +3180,8 @@ comm_point_stop_listening(struct comm_point* c)
void
comm_point_start_listening(struct comm_point* c, int newfd, int msec)
{
- verbose(VERB_ALGO, "comm point start listening %d",
- c->fd==-1?newfd:c->fd);
+ verbose(VERB_ALGO, "comm point start listening %d (%d msec)",
+ c->fd==-1?newfd:c->fd, msec);
if(c->type == comm_tcp_accept && !c->tcp_free) {
/* no use to start listening no free slots. */
return;
diff --git a/sbin/unwind/libunbound/util/storage/lookup3.c b/sbin/unwind/libunbound/util/storage/lookup3.c
index cc110748156..bb25eb433c9 100644
--- a/sbin/unwind/libunbound/util/storage/lookup3.c
+++ b/sbin/unwind/libunbound/util/storage/lookup3.c
@@ -1,4 +1,7 @@
/*
+ May 2019(Wouter) patch to enable the valgrind clean implementation all the
+ time. This enables better security audit and checks, which is better
+ than the speedup. Git issue #30. Renamed the define ARRAY_CLEAN_ACCESS.
February 2013(Wouter) patch defines for BSD endianness, from Brad Smith.
January 2012(Wouter) added randomised initial value, fallout from 28c3.
March 2007(Wouter) adapted from lookup3.c original, add config.h include.
@@ -44,6 +47,7 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy.
-------------------------------------------------------------------------------
*/
/*#define SELF_TEST 1*/
+#define ARRAY_CLEAN_ACCESS 1
#include "config.h"
#include "util/storage/lookup3.h"
@@ -336,7 +340,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
-#ifdef VALGRIND
+#ifdef ARRAY_CLEAN_ACCESS
const uint8_t *k8;
#endif
@@ -361,7 +365,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#ifndef ARRAY_CLEAN_ACCESS
switch(length)
{
diff --git a/sbin/unwind/libunbound/util/ub_event.c b/sbin/unwind/libunbound/util/ub_event.c
index 78481a98205..e097fbc4015 100644
--- a/sbin/unwind/libunbound/util/ub_event.c
+++ b/sbin/unwind/libunbound/util/ub_event.c
@@ -295,11 +295,18 @@ ub_event_new(struct ub_event_base* base, int fd, short bits,
if (!ev)
return NULL;
+#ifndef HAVE_EVENT_ASSIGN
event_set(ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
free(ev);
return NULL;
}
+#else
+ if (event_assign(ev, AS_EVENT_BASE(base), fd, bits, cb, arg) != 0) {
+ free(ev);
+ return NULL;
+ }
+#endif
return AS_UB_EVENT(ev);
}
@@ -312,11 +319,18 @@ ub_signal_new(struct ub_event_base* base, int fd,
if (!ev)
return NULL;
+#if !HAVE_DECL_EVSIGNAL_ASSIGN
signal_set(ev, fd, NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
free(ev);
return NULL;
}
+#else
+ if (evsignal_assign(ev, AS_EVENT_BASE(base), fd, cb, arg) != 0) {
+ free(ev);
+ return NULL;
+ }
+#endif
return AS_UB_EVENT(ev);
}