[ldns-users] ldns_dnssec_verify_denial() usage
Willem Toorop
willem at nlnetlabs.nl
Mon Jun 18 16:00:12 UTC 2018
Op 18-06-18 om 17:01 schreef Vladimir Levijev:
> On Mon, Jun 18, 2018 at 5:52 PM Willem Toorop <willem at nlnetlabs.nl> wrote:
>> Op 18-06-18 om 16:08 schreef Vladimir Levijev:
>>> On Mon, Jun 18, 2018 at 3:34 PM Willem Toorop <willem at nlnetlabs.nl> wrote:
>>>> Op 15-06-18 om 15:31 schreef Jurijs Klopovskis:
>>>>
>>>>> I have a question about using ldns_dnssec_verify_denial() and
>>>>> ldns_dnssec_verify_denial_nsec3() functions.
>>>>>
>>>>> Right now in out code we perform denial of existence checks with these
>>>>> functions only if ldns_verify() function has failed with
>>>>> LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY.
>>>>>
>>>>> Is this sane?
>>>>
>>>> Did you start out with a ldns_pkt?
>>>>
>>>> If there were no RRsets for qname and qtype in the pkt, you can skip
>>>> ldns_verify() and start looking for NSECs (for
>>>> ldns_dnssec_verify_denial() ) or NSEC3s (for
>>>> ldns_dnssec_verify_denial_nsec3() ) right away.
>>>>
>>>> But even when you did found RRsets for qname and qtype and ldns_verify()
>>>> returned LDNS_STATUS_OK, you still have to check whether it validated a
>>>> wildcard match, in which case you have to verify that a more specific
>>>> qname/qtype did not exist.
>>>>
>>>> Note that getdns has a more convenient higher level function for this:
>>>>
>>>> https://getdnsapi.net/functions/getdns_validate_dnssec.html
>>>> https://getdnsapi.net/functions/getdns_validate_dnssec2.html
>>>>
>>>> Which can take a whole DNS message/packet as input and return the DNSSEC
>>>> status, regardless of whether the reply is for a NOERROR, NXDOMAIN or
>>>> NODATA response. Also wildcard responses are validated correctly
>>>> automatically with that function. (and you don't have to handle NSECs
>>>> and NSEC3s differently either).
>>>
>>> Did I understand correctly that in case of getdns I do not have a way
>>> to specify the Name Server I want to query?
>>
>> The default is full recursive, but you can configure getdns for stub
>> resolution mode in which case it will target the configured upstreams.
>> The below example will send A and AAAA queries (simultaneously) for
>> nlnetlabs.nl to 9.9.9.9.
>>
>> #include <getdns/getdns_extra.h>
>>
>> int main(int argc, char **argv)
>> {
>> getdns_context *context = NULL;
>> getdns_list *upstreams = NULL;
>> getdns_dict *response = NULL;
>> char *response_str = NULL;
>> getdns_return_t r;
>>
>> if ((r = getdns_context_create(&context, 0)))
>> fprintf(stderr, "Could not create context");
>>
>> else if ((r = getdns_context_set_resolution_type(
>> context, GETDNS_RESOLUTION_STUB)))
>> fprintf(stderr, "Could not set resolution type");
>>
>> else if ((r = getdns_str2list("[9.9.9.9]", &upstreams)))
>> fprintf(stderr, "Error converting upstreams list");
>>
>> else if ((r = getdns_context_set_upstream_recursive_servers(
>> context, upstreams)))
>> fprintf(stderr, "Could not set upstreams");
>>
>> else if ((r = getdns_address_sync(
>> context, "nlnetlabs.nl", NULL, &response)))
>> fprintf(stderr, "Could not query");
>>
>> else if (!(response_str = getdns_pretty_print_dict(response)))
>> fprintf(stderr, "Could not print response dict\n");
>> else
>> printf("%s\n", response_str);
>>
>> if (response_str)
>> free(response_str);
>> if (response)
>> getdns_dict_destroy(response);
>> if (upstreams)
>> getdns_list_destroy(upstreams);
>> if (context)
>> getdns_context_destroy(context);
>> if (r)
>> fprintf(stderr, ": %s\n", getdns_get_errorstr_by_id(r));
>>
>> return r ? EXIT_FAILURE : EXIT_SUCCESS;
>> }
>
> Thank you for the example!
>
> I'm afraid though our case is completely vice versa-ish, we would like
> to send the same query to specified list of name servers, to test each
> of them. E. g. send A and AAAA queries (simultaneously) for
> nlnetlabs.nl to 1.1.1.1, 2.2.2.2, 3.3.3.3, 4.4.4.4 and 5.5.5.5 . :-)
It might not possible to set a upstream on a per query basis (at least
not via the usual extension mechanism). It might be possible by
configuring a new upstream list before scheduling a new query; I'll have
to try that out.
However if asynchronicity is not important, it is possible to provide a
big list of upstreams and query them all in turn with the
getdns_context_set_round_robin_upstreams() function.
This works only in synchronously because the next upstream is only
selected after a query is received. I consider this a bug which needs
to be addressed in the future, but to give the example that illustrates
the gist:
#include <getdns/getdns_extra.h>
int main(int argc, char **argv)
{
getdns_context *context = NULL;
getdns_list *upstreams = NULL;
size_t n_upstreams, i;
getdns_dict *extensions = NULL;
getdns_dict *response = NULL;
char *response_str = NULL;
getdns_return_t r;
if ((r = getdns_context_create(&context, 0)))
fprintf(stderr, "Could not create context");
else if ((r = getdns_context_set_resolution_type(
context, GETDNS_RESOLUTION_STUB)))
fprintf(stderr, "Could not set resolution type");
else if ((r = getdns_str2list(
"[1.1.1.1, 8.8.8.8, 9.9.9.9, 64.6.64.6]", &upstreams)))
fprintf(stderr, "Error converting upstreams list");
else if ((r = getdns_list_get_length(upstreams, &n_upstreams)))
fprintf(stderr, "Could not get upstreams length");
else if ((r = getdns_context_set_upstream_recursive_servers(
context, upstreams)))
fprintf(stderr, "Could not set upstreams");
else if ((r = getdns_context_set_round_robin_upstreams(
context, 1)))
fprintf(stderr, "Could not set round robin upstreams");
else if ((r = getdns_str2dict(
"{ return_call_reporting: GETDNS_EXTENSION_TRUE }",
&extensions)))
fprintf(stderr, "Error converting extensions dict");
else for (i = 0; i < n_upstreams; i++) {
getdns_bindata *upstream;
getdns_bindata *address;
char *upstream_str = NULL;
char *address_str = NULL;
if ((r = getdns_general_sync(context, "nlnetlabs.nl",
GETDNS_RRTYPE_A, extensions, &response))) {
fprintf(stderr, "Could not schedule query");
break;
}
if (!getdns_dict_get_bindata(response,
"/call_reporting/0/query_to/address_data",
&upstream)
&& !getdns_dict_get_bindata(response,
"/just_address_answers/0/address_data", &address)
&& (upstream_str = getdns_display_ip_address(upstream))
&& (address_str = getdns_display_ip_address(address)))
printf( "%s returned %s\n"
, upstream_str, address_str);
if (upstream_str)
free(upstream_str);
if (address_str)
free(address_str);
getdns_dict_destroy(response);
}
if (extensions)
getdns_dict_destroy(extensions);
if (upstreams)
getdns_list_destroy(upstreams);
if (context)
getdns_context_destroy(context);
if (r)
fprintf(stderr, ": %s\n", getdns_get_errorstr_by_id(r));
return r ? EXIT_FAILURE : EXIT_SUCCESS;
}
This displays:
1.1.1.1 returned 185.49.140.10
8.8.8.8 returned 185.49.140.10
9.9.9.9 returned 185.49.140.10
64.6.64.6 returned 185.49.140.10
Cheers,
-- Willem
>
> Cheers,
>
> VL
>
More information about the ldns-users
mailing list