dnssec_return_validation_chain with stub resolving

This commit is contained in:
Willem Toorop 2015-03-18 23:45:26 +01:00
parent f1a9c1a464
commit d2345285a6
8 changed files with 101 additions and 66 deletions

View File

@ -49,6 +49,7 @@
#include "rr-dict.h" #include "rr-dict.h"
#include "gldns/str2wire.h" #include "gldns/str2wire.h"
#include "gldns/wire2str.h" #include "gldns/wire2str.h"
#include "general.h"
void priv_getdns_call_user_callback(getdns_dns_req *, struct getdns_dict *); void priv_getdns_call_user_callback(getdns_dns_req *, struct getdns_dict *);
@ -66,7 +67,7 @@ struct chain_response {
int sec; int sec;
char *bogus; char *bogus;
struct validation_chain *chain; struct validation_chain *chain;
int unbound_id; getdns_transaction_t transaction_id;
}; };
struct chain_link { struct chain_link {
@ -181,10 +182,12 @@ static void callback_on_complete_chain(struct validation_chain *chain)
static void static void
ub_chain_response_callback(void *arg, int err, struct ub_result* ub_res) chain_response_callback(struct getdns_dns_req *dns_req)
{ {
struct chain_response *response = (struct chain_response *) arg; struct chain_response *response =
getdns_context *context = response->chain->dns_req->context; (struct chain_response *) dns_req->user_pointer;
getdns_context *context = dns_req->context;
getdns_network_req **netreq_p, *netreq;
priv_getdns_rr_iter rr_iter_storage, *rr_iter; priv_getdns_rr_iter rr_iter_storage, *rr_iter;
priv_getdns_rdf_iter rdf_storage, *rdf; priv_getdns_rdf_iter rdf_storage, *rdf;
gldns_pkt_section section; gldns_pkt_section section;
@ -193,52 +196,54 @@ ub_chain_response_callback(void *arg, int err, struct ub_result* ub_res)
getdns_list *keys; getdns_list *keys;
size_t nkeys; size_t nkeys;
response->err = err; if (dns_req == NULL ||
response->sec = ub_res ? ub_res->secure : 0;
response->bogus = ub_res ? ub_res->why_bogus : NULL;
if (ub_res == NULL || ub_res->answer_packet == NULL ||
!(keys = getdns_list_create_with_context(context))) !(keys = getdns_list_create_with_context(context)))
goto done; goto done;
for ( rr_iter = priv_getdns_rr_iter_init(&rr_iter_storage for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++) {
, ub_res->answer_packet for ( rr_iter = priv_getdns_rr_iter_init(&rr_iter_storage
, ub_res->answer_len) , netreq->response
; rr_iter , netreq->response_len)
; rr_iter = priv_getdns_rr_iter_next(rr_iter) ; rr_iter
) { ; rr_iter = priv_getdns_rr_iter_next(rr_iter)
section = priv_getdns_rr_iter_section(rr_iter); ) {
if (section != GLDNS_SECTION_ANSWER) section = priv_getdns_rr_iter_section(rr_iter);
continue; if (section != GLDNS_SECTION_ANSWER)
continue;
rr_type = gldns_read_uint16(rr_iter->rr_type); rr_type = gldns_read_uint16(rr_iter->rr_type);
if (rr_type == GETDNS_RRTYPE_DS || if (rr_type == GETDNS_RRTYPE_DS ||
rr_type == GETDNS_RRTYPE_DNSKEY) { rr_type == GETDNS_RRTYPE_DNSKEY) {
if (!(rr_dict = priv_getdns_rr_iter2rr_dict(context, rr_iter))) if (!(rr_dict = priv_getdns_rr_iter2rr_dict(
context, rr_iter)))
continue;
if (getdns_list_append_dict(keys, rr_dict))
break;
}
if (rr_type != GETDNS_RRTYPE_RRSIG)
continue;
if (!(rdf = priv_getdns_rdf_iter_init(
&rdf_storage, rr_iter)))
continue;
type_covered = gldns_read_uint16(rdf->pos);
if (type_covered == GETDNS_RRTYPE_DS) {
if ((rdf = priv_getdns_rdf_iter_init_at(
&rdf_storage, rr_iter, 7)))
launch_chain_link_lookup(
response->chain, rdf);
} else if (type_covered != GETDNS_RRTYPE_DNSKEY)
continue;
if (!(rr_dict = priv_getdns_rr_iter2rr_dict(
context, rr_iter)))
continue; continue;
if (getdns_list_append_dict(keys, rr_dict)) if (getdns_list_append_dict(keys, rr_dict))
break; break;
} }
if (rr_type != GETDNS_RRTYPE_RRSIG)
continue;
if (!(rdf = priv_getdns_rdf_iter_init(&rdf_storage, rr_iter)))
continue;
type_covered = gldns_read_uint16(rdf->pos);
if (type_covered == GETDNS_RRTYPE_DS) {
if ((rdf = priv_getdns_rdf_iter_init_at(
&rdf_storage, rr_iter, 7)))
launch_chain_link_lookup(response->chain, rdf);
} else if (type_covered != GETDNS_RRTYPE_DNSKEY)
continue;
if (!(rr_dict = priv_getdns_rr_iter2rr_dict(context, rr_iter)))
continue;
if (getdns_list_append_dict(keys, rr_dict))
break;
} }
if (getdns_list_get_length(keys, &nkeys)) if (getdns_list_get_length(keys, &nkeys))
getdns_list_destroy(keys); getdns_list_destroy(keys);
@ -248,32 +253,47 @@ ub_chain_response_callback(void *arg, int err, struct ub_result* ub_res)
else else
response->result = keys; response->result = keys;
ub_resolve_free(ub_res);
done: if (response->err == 0 && response->result == NULL) done: if (response->err == 0 && response->result == NULL)
response->err = -1; response->err = -1;
if (dns_req) {
getdns_context_clear_outbound_request(dns_req);
dns_req_free(dns_req);
}
callback_on_complete_chain(response->chain); callback_on_complete_chain(response->chain);
} }
static void chain_response_init( static void chain_response_init(
struct validation_chain *chain, struct chain_response *response) struct validation_chain *chain, struct chain_response *response)
{ {
response->err = 0; response->err = 0;
response->result = NULL; response->result = NULL;
response->sec = 0; response->sec = 0;
response->bogus = NULL; response->bogus = NULL;
response->chain = chain; response->chain = chain;
response->unbound_id = -1; response->transaction_id = -1;
} }
static int static int
resolve(char* name, int rrtype, struct chain_response *response) resolve(char* name, int rrtype, struct chain_response *response)
{ {
return ub_resolve_async( getdns_return_t r;
response->chain->dns_req->context->unbound_ctx, getdns_dict *extensions;
name, rrtype, GETDNS_RRCLASS_IN, response,
ub_chain_response_callback, &response->unbound_id); if (!(extensions = getdns_dict_create_with_context(
response->chain->dns_req->context)))
return GETDNS_RETURN_MEMORY_ERROR;
if (!(r = getdns_dict_set_int(extensions,
"dnssec_ok_checking_disabled", GETDNS_EXTENSION_TRUE)))
r = priv_getdns_general_loop(response->chain->dns_req->context,
response->chain->dns_req->loop, name, rrtype, extensions,
response, &response->transaction_id, NULL,
chain_response_callback);
getdns_dict_destroy(extensions);
return r;
} }
static void static void

View File

@ -91,7 +91,9 @@ priv_getdns_check_dns_req_complete(getdns_dns_req *dns_req)
else if (netreq->response_len > 0) else if (netreq->response_len > 0)
results_found = 1; results_found = 1;
if (! results_found) if (dns_req->internal_cb)
dns_req->internal_cb(dns_req);
else if (! results_found)
priv_getdns_call_user_callback(dns_req, NULL); priv_getdns_call_user_callback(dns_req, NULL);
else if (dns_req->dnssec_return_validation_chain else if (dns_req->dnssec_return_validation_chain
#ifdef STUB_NATIVE_DNSSEC #ifdef STUB_NATIVE_DNSSEC
@ -172,7 +174,7 @@ static getdns_return_t
getdns_general_ns(getdns_context *context, getdns_eventloop *loop, getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions, const char *name, uint16_t request_type, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id, void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn, int usenamespaces) getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces)
{ {
getdns_return_t r = GETDNS_RETURN_GOOD; getdns_return_t r = GETDNS_RETURN_GOOD;
getdns_network_req *netreq, **netreq_p; getdns_network_req *netreq, **netreq_p;
@ -180,7 +182,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
getdns_dict *localnames_response; getdns_dict *localnames_response;
size_t i; size_t i;
if (!context || !name || !callbackfn) if (!context || !name || (!callbackfn && !internal_cb))
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
if ((r = validate_dname(name))) if ((r = validate_dname(name)))
@ -200,6 +202,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
req->user_pointer = userarg; req->user_pointer = userarg;
req->user_callback = callbackfn; req->user_callback = callbackfn;
req->internal_cb = internal_cb;
if (transaction_id) if (transaction_id)
*transaction_id = req->trans_id; *transaction_id = req->trans_id;
@ -252,11 +255,11 @@ getdns_return_t
priv_getdns_general_loop(getdns_context *context, getdns_eventloop *loop, priv_getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions, const char *name, uint16_t request_type, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id, void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callback) getdns_callback_t callback, internal_cb_t internal_cb)
{ {
return getdns_general_ns(context, loop, return getdns_general_ns(context, loop,
name, request_type, extensions, name, request_type, extensions,
userarg, transaction_id, callback, 0); userarg, transaction_id, callback, internal_cb, 0);
} /* getdns_general_loop */ } /* getdns_general_loop */
@ -279,7 +282,7 @@ priv_getdns_address_loop(getdns_context *context, getdns_eventloop *loop,
r = getdns_general_ns(context, loop, r = getdns_general_ns(context, loop,
name, GETDNS_RRTYPE_A, extensions, name, GETDNS_RRTYPE_A, extensions,
userarg, transaction_id, callback, 1); userarg, transaction_id, callback, NULL, 1);
if (cleanup_extensions) if (cleanup_extensions)
getdns_dict_destroy(extensions); getdns_dict_destroy(extensions);
@ -370,7 +373,7 @@ priv_getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
} }
retval = priv_getdns_general_loop(context, loop, name, req_type, retval = priv_getdns_general_loop(context, loop, name, req_type,
extensions, userarg, transaction_id, callback); extensions, userarg, transaction_id, callback, NULL);
return retval; return retval;
} /* getdns_hostname_loop */ } /* getdns_hostname_loop */
@ -380,7 +383,7 @@ priv_getdns_service_loop(getdns_context *context, getdns_eventloop *loop,
getdns_transaction_t * transaction_id, getdns_callback_t callback) getdns_transaction_t * transaction_id, getdns_callback_t callback)
{ {
return getdns_general_ns(context, loop, name, GETDNS_RRTYPE_SRV, return getdns_general_ns(context, loop, name, GETDNS_RRTYPE_SRV,
extensions, userarg, transaction_id, callback, 1); extensions, userarg, transaction_id, callback, NULL, 1);
} /* getdns_service_loop */ } /* getdns_service_loop */
/** /**
@ -395,7 +398,7 @@ getdns_general(getdns_context *context,
if (!context) return GETDNS_RETURN_INVALID_PARAMETER; if (!context) return GETDNS_RETURN_INVALID_PARAMETER;
return priv_getdns_general_loop(context, context->extension, return priv_getdns_general_loop(context, context->extension,
name, request_type, extensions, name, request_type, extensions,
userarg, transaction_id, callback); userarg, transaction_id, callback, NULL);
} /* getdns_general */ } /* getdns_general */

View File

@ -49,7 +49,7 @@ getdns_return_t
priv_getdns_general_loop(getdns_context *context, getdns_eventloop *loop, priv_getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions, const char *name, uint16_t request_type, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id, void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn); getdns_callback_t callbackfn, internal_cb_t internal_cb);
getdns_return_t getdns_return_t
priv_getdns_address_loop(getdns_context *context, getdns_eventloop *loop, priv_getdns_address_loop(getdns_context *context, getdns_eventloop *loop,

View File

@ -207,8 +207,12 @@ dns_req_new(getdns_context *context, getdns_eventloop *loop,
= is_extension_set(extensions, "dnssec_return_only_secure"); = is_extension_set(extensions, "dnssec_return_only_secure");
int dnssec_return_validation_chain int dnssec_return_validation_chain
= is_extension_set(extensions, "dnssec_return_validation_chain"); = is_extension_set(extensions, "dnssec_return_validation_chain");
int dnssec_ok_checking_disabled
= is_extension_set(extensions, "dnssec_ok_checking_disabled");
int dnssec_extension_set = dnssec_return_status int dnssec_extension_set = dnssec_return_status
|| dnssec_return_only_secure || dnssec_return_validation_chain; || dnssec_return_only_secure || dnssec_return_validation_chain
|| dnssec_ok_checking_disabled;;
uint32_t edns_do_bit; uint32_t edns_do_bit;
int edns_maximum_udp_payload_size; int edns_maximum_udp_payload_size;

View File

@ -86,7 +86,7 @@ priv_getdns_rr_iter_init(priv_getdns_rr_iter *i, uint8_t *pkt, size_t pkt_len)
{ {
assert(i); assert(i);
if (pkt_len < GLDNS_HEADER_SIZE + 5) { if (!pkt || pkt_len < GLDNS_HEADER_SIZE + 5) {
i->pos = NULL; i->pos = NULL;
return NULL; return NULL;
} }

View File

@ -123,7 +123,7 @@ getdns_general_sync(getdns_context *context, const char *name,
return r; return r;
if ((r = priv_getdns_general_loop(context, &loop.loop.loop, name, if ((r = priv_getdns_general_loop(context, &loop.loop.loop, name,
request_type, extensions, &loop, NULL, getdns_sync_cb))) { request_type, extensions, &loop, NULL, getdns_sync_cb, NULL))) {
getdns_sync_loop_cleanup(&loop); getdns_sync_loop_cleanup(&loop);
return r; return r;

View File

@ -108,6 +108,7 @@ struct getdns_upstream;
struct getdns_dns_req; struct getdns_dns_req;
struct getdns_network_req; struct getdns_network_req;
typedef void (*internal_cb_t)(struct getdns_dns_req *dns_req);
#define MF_PLAIN ((void *)&plain_mem_funcs_user_arg) #define MF_PLAIN ((void *)&plain_mem_funcs_user_arg)
extern void *plain_mem_funcs_user_arg; extern void *plain_mem_funcs_user_arg;
@ -238,6 +239,12 @@ typedef struct getdns_dns_req {
int dnssec_return_only_secure; int dnssec_return_only_secure;
int dnssec_return_validation_chain; int dnssec_return_validation_chain;
/* Internally used by return_validation_chain */
int dnssec_ok_checking_disabled;
/* internally scheduled request */
internal_cb_t internal_cb;
/* event loop */ /* event loop */
getdns_eventloop *loop; getdns_eventloop *loop;

View File

@ -60,6 +60,7 @@
static getdns_extension_format extformats[] = { static getdns_extension_format extformats[] = {
{"add_opt_parameters", t_dict}, {"add_opt_parameters", t_dict},
{"add_warning_for_bad_dns", t_int}, {"add_warning_for_bad_dns", t_int},
{"dnssec_ok_checking_disabled", t_int},
{"dnssec_return_only_secure", t_int}, {"dnssec_return_only_secure", t_int},
{"dnssec_return_status", t_int}, {"dnssec_return_status", t_int},
{"dnssec_return_validation_chain", t_int}, {"dnssec_return_validation_chain", t_int},