Schedule timeout when collecting for dnssec chain

This commit is contained in:
Willem Toorop 2017-04-06 11:20:08 +02:00
parent f8c7d8b5d5
commit e08d3592a0
9 changed files with 102 additions and 7 deletions

View File

@ -691,8 +691,10 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
while (upstream->finished_dnsreqs) {
dnsreq = upstream->finished_dnsreqs;
upstream->finished_dnsreqs = dnsreq->finished_next;
debug_req("Destroy ", *dnsreq->netreqs);
_getdns_context_cancel_request(dnsreq);
if (!dnsreq->internal_cb) { /* Not part of chain */
debug_req("Destroy ", *dnsreq->netreqs);
_getdns_context_cancel_request(dnsreq);
}
}
if (upstream->tls_session != NULL)
SSL_SESSION_free(upstream->tls_session);
@ -3088,7 +3090,10 @@ getdns_cancel_callback(getdns_context *context,
NULL, dnsreq->user_pointer, dnsreq->trans_id);
dnsreq->context->processing = 0;
}
_getdns_context_cancel_request(dnsreq);
if (!dnsreq->internal_cb) { /* Not part of chain */
debug_req("Destroy ", *dnsreq->netreqs);
_getdns_context_cancel_request(dnsreq);
}
return GETDNS_RETURN_GOOD;
} /* getdns_cancel_callback */

View File

@ -3113,6 +3113,43 @@ static void check_chain_complete(chain_head *chain)
_getdns_call_user_callback(dnsreq, response_dict);
}
void _getdns_validation_chain_timeout(getdns_dns_req *dnsreq)
{
chain_head *head = dnsreq->chain, *next;
chain_node *node;
size_t node_count;
while (head) {
next = head->next;
for ( node_count = head->node_count, node = head->parent
; node_count
; node_count--, node = node->parent ) {
if (!_getdns_netreq_finished(node->dnskey_req)) {
_getdns_context_cancel_request(
node->dnskey_req->owner);
node->dnskey_req = NULL;
}
if (!_getdns_netreq_finished(node->ds_req)) {
_getdns_context_cancel_request(
node->ds_req->owner);
node->ds_req = NULL;
}
if (!_getdns_netreq_finished(node->soa_req)) {
_getdns_context_cancel_request(
node->soa_req->owner);
node->soa_req = NULL;
}
}
head = next;
}
dnsreq->request_timed_out = 1;
check_chain_complete(dnsreq->chain);
}
void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
{
chain_head *head = dnsreq->chain, *next;

View File

@ -47,6 +47,7 @@
/* Do some additional requests to fetch the complete validation chain */
void _getdns_get_validation_chain(getdns_dns_req *dns_req);
void _getdns_cancel_validation_chain(getdns_dns_req *dns_req);
void _getdns_validation_chain_timeout(getdns_dns_req *dns_req);
uint16_t _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf);

View File

@ -61,8 +61,9 @@ void _getdns_call_user_callback(getdns_dns_req *dnsreq, getdns_dict *response)
if (dnsreq->user_callback) {
dnsreq->context->processing = 1;
dnsreq->user_callback(dnsreq->context,
(response ? GETDNS_CALLBACK_COMPLETE
: GETDNS_CALLBACK_ERROR),
( ! response ? GETDNS_CALLBACK_ERROR
: dnsreq->request_timed_out ? GETDNS_CALLBACK_TIMEOUT
: GETDNS_CALLBACK_COMPLETE ),
response, dnsreq->user_pointer, dnsreq->trans_id);
dnsreq->context->processing = 0;
}
@ -214,9 +215,22 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
dns_req->dnssec_return_all_statuses
))
#endif
))
)) {
/* Reschedule timeout for this DNS request
*/
dns_req->timeout.userarg = dns_req;
dns_req->timeout.read_cb = NULL;
dns_req->timeout.write_cb = NULL;
dns_req->timeout.timeout_cb =
(getdns_eventloop_callback)
_getdns_validation_chain_timeout;
dns_req->timeout.ev = NULL;
(void) dns_req->loop->vmt->schedule(dns_req->loop, -1,
_getdns_ms_until_expiry2(dns_req->expires, &now_ms),
&dns_req->timeout);
_getdns_get_validation_chain(dns_req);
else
} else
_getdns_call_user_callback(
dns_req, _getdns_create_getdns_response(dns_req));
}

View File

@ -944,6 +944,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
result->freed = NULL;
result->validating = 0;
result->is_dns_request = 1;
result->request_timed_out = 0;
result->chain = NULL;
network_req_init(result->netreqs[0], result,

View File

@ -32,6 +32,12 @@
*/
#include "config.h"
/* Intercept and do not sent out COM DS queries with TLS
* For debugging purposes only. Never commit with this turned on.
*/
#define INTERCEPT_COM_DS 0
#ifdef USE_POLL_DEFAULT_EVENTLOOP
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
@ -1306,6 +1312,22 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
/* TODO[TLS]: Handle error cases, partial writes, renegotiation etc. */
ERR_clear_error();
#if INTERCEPT_COM_DS
/* Intercept and do not sent out COM DS queries. For debugging
* purposes only. Never commit with this turned on.
*/
if (netreq->request_type == GETDNS_RRTYPE_DS &&
netreq->owner->name_len == 5 &&
netreq->owner->name[0] == 3 &&
(netreq->owner->name[1] & 0xDF) == 'C' &&
(netreq->owner->name[2] & 0xDF) == 'O' &&
(netreq->owner->name[3] & 0xDF) == 'M' &&
netreq->owner->name[4] == 0) {
debug_req("Intercepting", netreq);
written = pkt_len + 2;
} else
#endif
written = SSL_write(tls_obj, netreq->query - 2, pkt_len + 2);
if (written <= 0)
return STUB_TCP_ERROR;

View File

@ -33,6 +33,19 @@ rm -f report.txt
echo ""
fi
) >> report.txt
(
cd ${SRCROOT}/src
if [ `grep '^#define[ ]*INTERCEPT_COM_DS[ ]*1' stub.c | wc -l` -gt 0 ]
then
echo "*** "
echo "*** The repo contained the COM DS queries interception"
echo "*** with TLS transports turned on, this should be off"
echo "*** "
grep -n '^#define[ ]INTERCEPT_COM_DS[ ]*1' stub.c
echo ""
fi
) >> report.txt
if [ -s report.txt ]
then

View File

@ -314,6 +314,7 @@ typedef struct getdns_dns_req {
unsigned dnssec_ok_checking_disabled : 1;
unsigned is_sync_request : 1;
unsigned is_dns_request : 1;
unsigned request_timed_out : 1;
/* The validating and freed variables are used to make sure a single
* code path is followed while processing a DNS request, even when

View File

@ -1263,6 +1263,7 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
GETDNS_FREE(context->mf, srvs.rrs);
}
if (getdns_dict_set_int(result, GETDNS_STR_KEY_STATUS,
completed_request->request_timed_out ||
nreplies == 0 ? GETDNS_RESPSTATUS_ALL_TIMEOUT :
completed_request->dnssec_return_only_secure && nsecure == 0 && ninsecure > 0
? GETDNS_RESPSTATUS_NO_SECURE_ANSWERS :