[getdns-users] Example using the "dnssec_return_validation_chain" extension

Linus Nordberg linus at nordberg.se
Thu Feb 11 13:15:48 CET 2016


Hi Willem,

Thanks for bringing this up. I'm a bit undereducated on the matter of
DNSSEC so please bear with me for being a bit daft here.

The tl;dr reads "Sounds great! Can I haz a public wire-format-input
entry-point as well?". For background and details, read on.


My immediate use for a function validating a (single) DS RR is to be
able to thwart spamming of an experimental DNSSEC Transparency log. In
short, the log will accept submissions of a DS RR (from a limited number
of zones) if accompanied by a valid chain consisting of RRSIG, DNSKEY
and DS RR's. The log will store the DS and chain RRs together with a
timestamp for later retrieval by any log client. (Current thinking is
that the DS RR and the timestamp (but not the chain) will be covered by
a signature issued by the log but this might change.)

I've so far expected the time of submission of a DS RR to be close in
time of observation in the DNS but I've lately come to think that this
might not be such a good idea. I'd very much like old DS records to be
submitted as well.


The next use for a validation function would be log monitors. Their job
is to poll logs for new entries and look at the data with the goal of
finding proof of misissuance. Imagine f.ex. that you ran a monitor
looking for DS records for getdnsapi.net which raised the alarm whenever
it saw one, so that you could decide if that issuance was ordered by
someone with control over the domain or if it was .net or . acting
unauthorized.

This is expected to happen not only close in time to the publication of
the DS record in the DNS but also a long time after that. Since the log
stores and on request hands out the full chain (up to and including one
of potentially several configured trust anchors, but typically the
DNSSEC root), this shouldn't be a problem using your suggested
function. All a monitor would have to do is to use the timestamp from
the log entry as the 'moment' argument.

While perhaps not strictly necessary, I think this will be useful
especially for spam mitigation -- a log could choose to refuse records
that are deemed too old for being interesting and stop someone trying to
fill up the log by submitting a gazillion of old DS records they've
stored.


Last, to my request for a validation function accepting RR's in wire
format. Since all RR's to and from the log will be sent in DNS wire
format, it'd be more conventient if I could use that with the
getdns_validate_dnssec() function (or its variant with 'moment'). As it
is now, I have to first turn the wire format into getdns_dict's and then
put them in getdns_list's. What do you think?


On a side note, it'd be great to have you and other DNS and DNSSEC
experts participating in the transparency discussions over at [1].

[1] https://lists.sunet.se/listinfo/dnssec-transparency


Willem Toorop <willem at nlnetlabs.nl> wrote
Thu, 11 Feb 2016 10:25:24 +0100:

| I know you're interested to validate resource records at specified
| moments.  I'll try to expose a "non-API" version of the
| getdns_validate_dnssec() function with that extra parameter in the
| upcoming release.  I.e.
| 
| getdns_return_t getdns_validate_dnssec2(
| 	getdns_list *to_validate,
| 	getdns_list *bundle_of_support_records,
| 	getdns_list *trust_anchor_records,
| 	time_t       moment
| );
| 
| OK?
| 
| -- Willem
| 
| Op 11-02-16 om 10:15 schreef Willem Toorop:
| > Hi Linus,
| > 
| > Rereading that message you are referring, I realise that a lot has been
| > improved since may 2015.
| > 
| > The dnssec_return_validation_chain extension currently works perfectly
| > inn all possible circumstances.  The chain will also contain proofs for
| > insecure zones.
| > 
| > The record_to_validate parameter to getdns_validate_dnssec() may now
| > also contain a list of reply dicts to validate actual DNS packets.  This
| > allows to also validate proof of denial of existence or insecure
| > NXDOMAINs etc.
| > 
| > The getdns_query program (did you compile the binary with
| > --with-getdns_query ?) contains example usage of getdns_validate_dnssec
| > and will revalidate the answer with getdns_validate_dnssec() when the
| > dnssec_return_validation_chain was used.  This happens in function
| > validate_chain on line 537 of getdns_query.c.
| > 
| > It basically boils down to:
| > 
| > getdns_return_t validate_chain(getdns_dict *response)
| > {
| > 	getdns_status r = GETDNS_RETURN_GENERIC_ERROR;
| > 	getdns_list  *trust_anchor;
| > 	getdns_list  *validation_chain;
| > 	getdns_list  *replies_tree;
| > 
| > 	/* Get the trust anchors ...
| > 	 */
| >         if (getdns_context_get_dnssec_trust_anchors(
| > 	    context, &trust_anchor))
| >                 trust_anchor = getdns_root_trust_anchor(NULL);
| > 
| > 	if (!trust_anchor)
| > 		fprintf(stderr, "No trust anchor to validate with.\n");
| > 
| > 	/* ... get the validation chain ...
| > 	 */
| > 	else if ((r = getdns_dict_get_list(
| >             response, "validation_chain", &validation_chain)))
| > 		fprintf(stderr, "Could not get validation chain\n");
| > 
| > 
| > 	/* .. get the replies tree ..
| > 	 */
| > 	else if (r = getdns_dict_get_list(
| >             response, "replies_tree", &replies_tree)))
| > 		fprintf(stderr, "Could not get replies tree\n");
| > 
| > 	/* .. and validate.
| > 	 */
| > 	else switch(getdns_validate_dnssec(
| > 	    replies_tree, validation_chain, trust_anchors)) {
| > 
| > 	case GETDNS_DNSSEC_SECURE  : printf("Replies are secure\n");
| > 	                             return GETDNS_RETURN_GOOD;
| > 
| > 	case GETDNS_DNSSEC_INDETERMINATE:
| > 	case GETDNS_DNSSEC_INSECURE: printf("Replies are insecure\n");
| > 	                             return GETDNS_RETURN_GOOD;
| > 
| > 	case GETDNS_DNSSEC_BOGUS   : printf("Replies are bogus\n");
| >                                      return GETDNS_RETURN_GOOD;
| > 
| > 	default                    : /* Not possible to get here */
| >                                      fprintf( stderr
| > 	                                    , "Unkown dnssec status\n");
| > 	                             return GETDNS_RETURN_GENERIC_ERROR;
| > 	}
| > 	return r;
| > }
| > 
| > Op 10-02-16 om 20:44 schreef Linus Nordberg:
| >> Hi list,
| >>
| >> I've been trying to use the "dnssec_return_validation_chain" extension,
| >> so far without luck. I define luck as seeing a "validation_chain"
| >> section in a reply. I have verified that my context has proper trust
| >> anchor(s).
| >>
| >> It'd be great to be able to run some example code, C or Python, to rule
| >> out local problems at my end.
| >>
| >> My ultimate goal with this exercise is to understand what to pass in the
| >> support_records argument to getdns_validate_dnssec(). The rationale
| >> behind this is
| >> https://getdnsapi.net/pipermail/users/2015-May/000032.html which says
| >>
| >> --8<---------------cut here---------------start------------->8---
| >> - bundle_of_support_records must be a list of DS's RR-dicts and DNSKEY
| >> RR-dicts with companion RRSIG-RR-dicts that lead up from one of the
| >> trust_anchors to the RR-dicts to validate.
| >> ...
| >> If you would do a query with the "dnssec_return_validation_chain"
| >> extension, you can use the "validation_chain" key in the response dict
| >> as the bundle_of_support_records parameter ro getdns_validate_dnssec.
| >> --8<---------------cut here---------------end--------------->8---
| >>
| >> Thanks,
| >> Linus
| >> _______________________________________________
| >> Users mailing list
| >> Users at getdnsapi.net
| >> http://getdnsapi.net/mailman/listinfo/users>>
| > 
| > _______________________________________________
| > Users mailing list
| > Users at getdnsapi.net
| > http://getdnsapi.net/mailman/listinfo/users> 
| 
| _______________________________________________
| Users mailing list
| Users at getdnsapi.net
| http://getdnsapi.net/mailman/listinfo/users


More information about the Users mailing list