From svallet at genoscope.cns.fr Wed May 2 13:50:47 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Wed, 2 May 2007 15:50:47 +0200 Subject: [ldns-users] Access to raw rdata in ressource records Message-ID: <20070502155047.29d31855@tx174.tx.local> Hi, we're currently considering using ldns as a validating stub resolver in a number of applications needing DNSSEC support. Looking a bit at the API documentation, I wonder wether it is possible to have access to the raw rdata in an RR (i.e. a size and a void *, rather than an ldns_rdf **). Best for us would be to have a drop-in replacement for more common resolver functions, and as some apps do the rdata parsing themselves, I'd rather not reassemble a raw rdata to parse it again once we're out of the compatibility layer. Thanks for any hint Simon -- Simon Vallet Ing?nieur Syst?mes/R?seaux Genoscope / CNRG T?l. : 01 60 87 36 06 E-mail : svallet at genoscope.cns.fr From jelte at NLnetLabs.nl Wed May 2 14:04:35 2007 From: jelte at NLnetLabs.nl (Jelte Jansen) Date: Wed, 02 May 2007 16:04:35 +0200 Subject: [ldns-users] Access to raw rdata in ressource records In-Reply-To: <20070502155047.29d31855@tx174.tx.local> References: <20070502155047.29d31855@tx174.tx.local> Message-ID: <46389A73.8060801@NLnetLabs.nl> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Simon Vallet wrote: > Hi, > > we're currently considering using ldns as a validating stub resolver in > a number of applications needing DNSSEC support. > Cool, let me know how you are faring, and how we can improve on ldns. > Looking a bit at the API documentation, I wonder wether it is possible > to have access to the raw rdata in an RR (i.e. a size and a void *, > rather than an ldns_rdf **). Best for us would be to have a drop-in > replacement for more common resolver functions, and as some apps do the > rdata parsing themselves, I'd rather not reassemble a raw rdata to > parse it again once we're out of the compatibility layer. > For individual rdata fields, or do you want to read out the complete rdata from an rr in one void*? For individual rdata fields, you can get access to the actual data with these functions: uint8_t *ldns_rdf_data (const ldns_rdf *rd) returns the data of the rdf. size_t ldns_rdf_size (const ldns_rdf *rd) returns the size of the rdf. Jelte -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGOJpn4nZCKsdOncURAu3dAJ4nYVp00CBYpjVsCy8q8Y65p/pO9wCgkEaR oh+K+A6mDlvcl5GTkWKrOHE= =9522 -----END PGP SIGNATURE----- From svallet at genoscope.cns.fr Wed May 2 15:08:54 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Wed, 2 May 2007 17:08:54 +0200 Subject: [ldns-users] Access to raw rdata in ressource records In-Reply-To: <46389A73.8060801@NLnetLabs.nl> References: <20070502155047.29d31855@tx174.tx.local> <46389A73.8060801@NLnetLabs.nl> Message-ID: <20070502170854.24396947@tx174.tx.local> On Wed, 02 May 2007 16:04:35 +0200 Jelte Jansen wrote: > Simon Vallet wrote: > Cool, let me know how you are faring, and how we can improve on ldns. I certainly will > > Looking a bit at the API documentation, I wonder wether it is possible > > to have access to the raw rdata in an RR (i.e. a size and a void *, > > rather than an ldns_rdf **). Best for us would be to have a drop-in > > replacement for more common resolver functions, and as some apps do the > > rdata parsing themselves, I'd rather not reassemble a raw rdata to > > parse it again once we're out of the compatibility layer. > > > > For individual rdata fields, or do you want to read out the complete > rdata from an rr in one void*? Well, access to individual rdata fields is practical, since it is already parsed in an ldns_rdf **. But what I'm looking for is a pointer to the complete rdata from an rr, yes. It is not a big problem, since reassembling it from the ldns_rdf array is quite trivial, but I just wanted to make sure it was necessary. It seems the answer is yes. Thanks, Simon From wouter at NLnetLabs.nl Wed May 2 15:42:48 2007 From: wouter at NLnetLabs.nl (Wouter Wijngaards) Date: Wed, 02 May 2007 17:42:48 +0200 Subject: [ldns-users] Access to raw rdata in ressource records In-Reply-To: <20070502170854.24396947@tx174.tx.local> References: <20070502155047.29d31855@tx174.tx.local> <46389A73.8060801@NLnetLabs.nl> <20070502170854.24396947@tx174.tx.local> Message-ID: <4638B178.9040503@nlnetlabs.nl> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Simon Vallet wrote: > On Wed, 02 May 2007 16:04:35 +0200 > Jelte Jansen wrote: >> Simon Vallet wrote: > >> Cool, let me know how you are faring, and how we can improve on ldns. > > I certainly will > >>> Looking a bit at the API documentation, I wonder wether it is possible >>> to have access to the raw rdata in an RR (i.e. a size and a void *, >>> rather than an ldns_rdf **). Best for us would be to have a drop-in >>> replacement for more common resolver functions, and as some apps do the >>> rdata parsing themselves, I'd rather not reassemble a raw rdata to >>> parse it again once we're out of the compatibility layer. >>> >> For individual rdata fields, or do you want to read out the complete >> rdata from an rr in one void*? > > Well, access to individual rdata fields is practical, since it is > already parsed in an ldns_rdf **. But what I'm looking for is a pointer > to the complete rdata from an rr, yes. > > It is not a big problem, since reassembling it from the ldns_rdf array > is quite trivial, but I just wanted to make sure it was necessary. It > seems the answer is yes. Well you can also use ldns_rdf2wire(), it will give you a void* and size_t. You can find its description in host2wire.h. Best regards, Wouter -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org iD8DBQFGOLF4kDLqNwOhpPgRAjlhAJ9uA23Eg92QpyJ1RtmE0a23q4KsWQCfbwFK FXV8A9ObQzaujCW0JjkFQUg= =RQjC -----END PGP SIGNATURE----- From svallet at genoscope.cns.fr Fri May 4 14:52:33 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Fri, 4 May 2007 16:52:33 +0200 Subject: [ldns-users] Configuring a trust anchor in ldns ? Message-ID: <20070504165233.36346125@tx174.tx.local> Hi, trying to implement a quick-and-dirty signature verification, I stumbled on the issue of trust anchor configuration -- this is what I'm doing : -> fetch the RR I need -> fetch the corresponding DNSKEY -> call ldns_verify() The key in question is a ZSK, which is signed by a domain-wide KSK. Now since global DNSSEC deployment will probably take a while, I'd like to configure this KSK as a trust anchor in ldns. I see entries for TSIG keys in the ldns_struct_resolver struct, but not any for trust anchors. Is there a reason for this ? Thanks, Simon From jelte at NLnetLabs.nl Sun May 6 12:24:15 2007 From: jelte at NLnetLabs.nl (Jelte Jansen) Date: Sun, 06 May 2007 14:24:15 +0200 Subject: [ldns-users] Configuring a trust anchor in ldns ? In-Reply-To: <20070504165233.36346125@tx174.tx.local> References: <20070504165233.36346125@tx174.tx.local> Message-ID: <463DC8EF.6090001@NLnetLabs.nl> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Simon Vallet wrote: > Hi, > > trying to implement a quick-and-dirty signature verification, I > stumbled on the issue of trust anchor configuration -- this is what I'm > doing : > > -> fetch the RR I need > -> fetch the corresponding DNSKEY > -> call ldns_verify() > > The key in question is a ZSK, which is signed by a domain-wide KSK. Now > since global DNSSEC deployment will probably take a while, I'd like to > configure this KSK as a trust anchor in ldns. > > I see entries for TSIG keys in the ldns_struct_resolver struct, but not > any for trust anchors. Is there a reason for this ? > the functions in the main library only verify signatures and keys directly. There is functionality to find the KSK but this is only in drill, since this is part of chasing/tracing and 'complete' validation, which hasn't made it back to the main library yet (the present code is too specific and not really ready for that (yet)). Jelte -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGPcju4nZCKsdOncURArEQAJ0QoR/aLQltYlE0vrvNjIXSkknkpQCfUsoz 5YeJuOX6VXz3lbNsUj7YaEU= =T1YD -----END PGP SIGNATURE----- From svallet at genoscope.cns.fr Wed May 9 08:20:22 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Wed, 9 May 2007 10:20:22 +0200 Subject: [ldns-users] Configuring a trust anchor in ldns ? In-Reply-To: <463DC8EF.6090001@NLnetLabs.nl> References: <20070504165233.36346125@tx174.tx.local> <463DC8EF.6090001@NLnetLabs.nl> Message-ID: <20070509102022.16254a8b@tx174.tx.local> On Sun, 06 May 2007 14:24:15 +0200 Jelte Jansen wrote: > > I see entries for TSIG keys in the ldns_struct_resolver struct, but not > > any for trust anchors. Is there a reason for this ? > > > > the functions in the main library only verify signatures and keys > directly. There is functionality to find the KSK but this is only in > drill, since this is part of chasing/tracing and 'complete' validation, > which hasn't made it back to the main library yet (the present code is > too specific and not really ready for that (yet)). OK -- I'll take a look at drill and try to cook something up using the code there. Anyway, ldns has been quite pleasant to work with until now. Thanks, Simon From svallet at genoscope.cns.fr Fri May 11 12:51:49 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Fri, 11 May 2007 14:51:49 +0200 Subject: [ldns-users] [ Patch ] Configuring a trust anchor in ldns ? In-Reply-To: <20070509102022.16254a8b@tx174.tx.local> References: <20070504165233.36346125@tx174.tx.local> <463DC8EF.6090001@NLnetLabs.nl> <20070509102022.16254a8b@tx174.tx.local> Message-ID: <20070511145149.13ec04cf@tx174.tx.local> On Wed, 9 May 2007 10:20:22 +0200 Simon Vallet wrote: > On Sun, 06 May 2007 14:24:15 +0200 > Jelte Jansen wrote: > > > the functions in the main library only verify signatures and keys > > directly. There is functionality to find the KSK but this is only in > > drill, since this is part of chasing/tracing and 'complete' validation, > > which hasn't made it back to the main library yet (the present code is > > too specific and not really ready for that (yet)). > > OK -- I'll take a look at drill and try to cook something up using the > code there. Hmmm... looking at the code in drill I'm a bit puzzled by the following bit, for which there is a simple patch, which is attached. /* check the other signatures, there might be a trusted KSK here */ for (ksk_sig_i = 0; ksk_sig_i < ldns_rr_list_rr_count(sigs); ksk_sig_i++) { ksk_sig = ldns_rr_list_rr(sigs, ksk_sig_i); if (ldns_rdf2native_int16(ldns_rr_rrsig_keytag(ksk_sig)) != ldns_calc_keytag(ldns_rr_list_rr(keys, key_i))) { for (ksk_i = 0; ksk_i < ldns_rr_list_rr_count(keys); ksk_i++) { if (ldns_rdf2native_int16(ldns_rr_rrsig_keytag(ksk_sig)) == ldns_calc_keytag(ldns_rr_list_rr(keys, ksk_i))) { result = ldns_verify_rrsig(rrset, cur_sig, ldns_rr_list_rr(keys, key_i)); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ if (result == LDNS_STATUS_OK) { for (tkey_i = 0; tkey_i < ldns_rr_list_rr_count(trusted_keys); tkey_i++) { if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, ksk_i), ldns_rr_list_rr(trusted_keys, tkey_i) )) { if (verbosity > 1) { mesg("Key is signed by trusted KSK"); } ldns_rr_list_deep_free(rrset); ldns_rr_list_deep_free(sigs); ldns_rr_list_deep_free(keys); ldns_pkt_free(pkt); ldns_rr_free(cur_sig); return LDNS_STATUS_OK; } } } } } } } The rationale is that there seems to be no point in re-verifying the sig in cur_sig with the key indexed by key_i, and that this call is likely to always return a successful status. There might be a point to call ldns_verify_rrsig() with ksk_sig and the key indexed by ksk_i, though. Simon -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: patch URL: From svallet at genoscope.cns.fr Mon May 14 10:12:29 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Mon, 14 May 2007 12:12:29 +0200 Subject: [ldns-users] [PATCH 0/3] Add full validating capabilities to ldns Message-ID: <20070514121229.63bb073c@tx174.tx.local> Hi, these series of patches adds rudimentary full validation to ldns, which has been tested in the following cases: Configured anchor (ZSK) -> RR Configured anchor (KSK) -> ZSK -> RR Configured anchor (KSK) -> ZSK -> DS -> ZSK -> RR Please consider these for integration Thanks, Simon -- Simon Vallet Ing?nieur Syst?mes/R?seaux Genoscope / CNRG T?l. : 01 60 87 36 06 E-mail : svallet at genoscope.cns.fr From svallet at genoscope.cns.fr Mon May 14 10:16:00 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Mon, 14 May 2007 12:16:00 +0200 Subject: [ldns-users] [PATCH 1/3] Add an anchor keyword to the resolver configuration In-Reply-To: <20070514121229.63bb073c@tx174.tx.local> References: <20070514121229.63bb073c@tx174.tx.local> Message-ID: <20070514121600.54a5508b@tx174.tx.local> this one adds an anchor keyword to the resolver configuration, allowing for trust anchors in ldns. Simon Index: ldns/resolver.h =================================================================== --- ldns/resolver.h (revision 2344) +++ ldns/resolver.h (working copy) @@ -39,8 +39,9 @@ #define LDNS_RESOLV_SEARCH 2 #define LDNS_RESOLV_SORTLIST 3 #define LDNS_RESOLV_OPTIONS 4 +#define LDNS_RESOLV_ANCHOR 5 -#define LDNS_RESOLV_KEYWORDS 5 +#define LDNS_RESOLV_KEYWORDS 6 #define LDNS_RESOLV_INETANY 0 #define LDNS_RESOLV_INET 1 @@ -62,8 +63,8 @@ /** Number of nameservers in \c _nameservers */ size_t _nameserver_count; /* how many do we have */ - /** Round trip time; 0 -> infinity. Unit: ms? */ - size_t *_rtt; + /** Round trip time; 0 -> infinity. Unit: ms? */ + size_t *_rtt; /** Wether or not to be recursive */ bool _recursive; @@ -89,6 +90,8 @@ bool _dnssec; /** Whether to set the CD bit on DNSSEC requests */ bool _dnssec_cd; + /** Optional trust anchors for complete DNSSEC validation */ + ldns_rr_list * _dnssec_anchors; /** Whether to use tcp or udp (tcp if the value is true)*/ bool _usevc; /** Whether to ignore the tc bit */ @@ -209,6 +212,12 @@ */ bool ldns_resolver_dnssec_cd(const ldns_resolver *r); /** + * Get the resolver's DNSSEC anchors + * \param[in] r the resolver + * \return an rr_list containg trusted DNSSEC anchors + */ +ldns_rr_list * ldns_resolver_dnssec_anchors(const ldns_resolver *r); +/** * Does the resolver ignore the TC bit (truncated) * \param[in] r the resolver * \return true: yes, false: no @@ -409,6 +418,21 @@ */ void ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool b); /** + * Set the resolver's DNSSEC anchor list directly. RRs should be of type DS or DNSKEY. + * \param[in] r the resolver + * \param[in] l the list of RRs to use as trust anchors + */ +void ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l); + +/** + * Push a new trust anchor to the resolver. It must be a DS or DNSKEY rr + * \param[in] r the resolver. + * \param[in] rr the RR to add as a trust anchor. + * \return a status + */ +ldns_status ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr); + +/** * Set the resolver retrans timeout (in seconds) * \param[in] r the resolver * \param[in] re the retransmission interval in seconds @@ -655,4 +679,20 @@ */ void ldns_resolver_nameservers_randomize(ldns_resolver *r); +/** + * Returns true if at least one of the provided keys is a trust anchor + * \param[in] r the current resolver + * \param[in] keys the keyset to check + * \param[out] trusted_keys the subset of trusted keys in the 'keys' rrset + * \return true if at least one of the provided keys is a configured trust anchor + */ +bool ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys); + +/** + * Instantiates a DNSKEY or DS RR from file. + * \param[in] filename the file to read the record from + * \return the corresponding RR, or NULL if the parsing failed + */ +ldns_rr * ldns_read_anchor_file(const char *filename); + #endif /* LDNS_RESOLVER_H */ Index: resolver.c =================================================================== --- resolver.c (revision 2344) +++ resolver.c (working copy) @@ -116,7 +116,34 @@ return r->_dnssec_cd; } +ldns_rr_list * +ldns_resolver_dnssec_anchors(const ldns_resolver *r) +{ + return r->_dnssec_anchors; +} + bool +ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys) +{ + unsigned int i; bool result = false; + ldns_rr_list * trust_anchors = ldns_resolver_dnssec_anchors(r); + ldns_rr * cur_rr; + + if (!r || !trust_anchors || !keys) { return false; } + + for (i=0; i< ldns_rr_list_rr_count(keys); i++) { + + cur_rr = ldns_rr_list_rr(keys, i); + if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) { + if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); } + result = true; + } + } + + return result; +} + +bool ldns_resolver_igntc(const ldns_resolver *r) { return r->_igntc; @@ -316,6 +343,29 @@ } void +ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l) +{ + r->_dnssec_anchors = l; +} + +ldns_status +ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr) +{ + ldns_rr_list * trust_anchors; + + if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY)) { + return LDNS_STATUS_ERR; + } + + if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */ + trust_anchors = ldns_rr_list_new(); + ldns_resolver_set_dnssec_anchors(r, trust_anchors); + } + + return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR; +} + +void ldns_resolver_set_igntc(ldns_resolver *r, bool i) { r->_igntc = i; @@ -519,6 +569,7 @@ ldns_resolver_set_edns_udp_size(r, 0); ldns_resolver_set_dnssec(r, false); ldns_resolver_set_dnssec_cd(r, false); + ldns_resolver_set_dnssec_anchors(r, NULL); ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY); /* randomize the nameserver to be queried @@ -557,6 +608,7 @@ int8_t expect; uint8_t i; ldns_rdf *tmp; + ldns_rr *tmp_rr; ssize_t gtr; ldns_buffer *b; @@ -574,6 +626,7 @@ /* these two are read but not used atm TODO */ keyword[LDNS_RESOLV_SORTLIST] = "sortlist"; keyword[LDNS_RESOLV_OPTIONS] = "options"; + keyword[LDNS_RESOLV_ANCHOR] = "anchor"; expect = LDNS_RESOLV_KEYWORD; r = ldns_resolver_new(); @@ -687,6 +740,18 @@ /* options not implemented atm */ expect = LDNS_RESOLV_KEYWORD; break; + case LDNS_RESOLV_ANCHOR: + /* a file containing a DNSSEC trust anchor */ + gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + if (gtr == 0) { + return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; + } + + tmp_rr = ldns_read_anchor_file(word); + ldns_resolver_push_dnssec_anchor(r, tmp_rr); + ldns_rr_free(tmp_rr); + expect = LDNS_RESOLV_KEYWORD; + break; } } @@ -766,6 +831,9 @@ if (res->_rtt) { LDNS_FREE(res->_rtt); } + if (res->_dnssec_anchors) { + ldns_rr_list_deep_free(res->_dnssec_anchors); + } LDNS_FREE(res); } } @@ -1073,3 +1141,41 @@ } ldns_resolver_set_nameservers(r, ns); } + +ldns_rr * +ldns_read_anchor_file(const char *filename) +{ + FILE *fp; + char line[LDNS_MAX_PACKETLEN]; + int c; + size_t i = 0; + ldns_rr *r; + ldns_status status; + + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); + return NULL; + } + + while ((c = fgetc(fp)) && i < LDNS_MAX_PACKETLEN && c != EOF) { + line[i] = c; + i++; + } + line[i] = '\0'; + + fclose(fp); + + if (i <= 0) { + fprintf(stderr, "nothing read from %s", filename); + return NULL; + } else { + status = ldns_rr_new_frm_str(&r, line, 0, NULL, NULL); + if (status == LDNS_STATUS_OK && (ldns_rr_get_type(r) == LDNS_RR_TYPE_DNSKEY || ldns_rr_get_type(r) == LDNS_RR_TYPE_DS)) { + return r; + } else { + fprintf(stderr, "Error creating DNSKEY or DS rr from %s: %s\n", filename, ldns_get_errorstr_by_id(status)); + return NULL; + } + } +} From svallet at genoscope.cns.fr Mon May 14 10:18:30 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Mon, 14 May 2007 12:18:30 +0200 Subject: [ldns-users] [PATCH 2/3] Miscellaneous API cleanup In-Reply-To: <20070514121229.63bb073c@tx174.tx.local> References: <20070514121229.63bb073c@tx174.tx.local> Message-ID: <20070514121830.340900c9@tx174.tx.local> this one adds some cleanups to the existing API, mostly to avoid compiler warnings Simon Index: ldns/dname.h =================================================================== --- ldns/dname.h (revision 2344) +++ ldns/dname.h (working copy) @@ -74,7 +74,7 @@ * \param[in] d the dname to chop * \return the remaining dname */ -ldns_rdf *ldns_dname_left_chop(ldns_rdf *d); +ldns_rdf *ldns_dname_left_chop(const ldns_rdf *d); /** * count the number of labels inside a LDNS_RDF_DNAME type rdf. Index: dname.c =================================================================== --- dname.c (revision 2344) +++ dname.c (working copy) @@ -116,7 +116,7 @@ } ldns_rdf * -ldns_dname_left_chop(ldns_rdf *d) +ldns_dname_left_chop(const ldns_rdf *d) { uint8_t label_pos; ldns_rdf *chop; Index: ldns/rr.h =================================================================== --- ldns/rr.h (revision 2344) +++ ldns/rr.h (working copy) @@ -593,7 +593,7 @@ * \param[in] rr the rr to check * \return true if rr_list contains rr, false otherwise */ -bool ldns_rr_list_contains_rr(ldns_rr_list *rr_list, ldns_rr *rr); +bool ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr); /** * checks if an rr_list is a rrset. Index: rr.c =================================================================== --- rr.c (revision 2344) +++ rr.c (working copy) @@ -965,7 +965,7 @@ bool -ldns_rr_list_contains_rr(ldns_rr_list *rr_list, ldns_rr *rr) +ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr) { size_t i; From svallet at genoscope.cns.fr Mon May 14 10:22:58 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Mon, 14 May 2007 12:22:58 +0200 Subject: [ldns-users] [PATCH 3/3] Add ldns_verify_trusted and associated In-Reply-To: <20070514121229.63bb073c@tx174.tx.local> References: <20070514121229.63bb073c@tx174.tx.local> Message-ID: <20070514122258.398a27ec@tx174.tx.local> this one adds an ldns_verify_trusted() method and associated utility functions to build a trust path and verify the sig using the apex RRset. It also adds status messages in case there is no valid DS along the path. Simon Index: ldns/dnssec.h =================================================================== --- ldns/dnssec.h (revision 2344) +++ ldns/dnssec.h (working copy) @@ -29,6 +29,7 @@ #include #include #include +#include #define LDNS_MAX_KEYLEN 2048 #define LDNS_DNSSEC_KEYPROTO 3 @@ -52,7 +53,7 @@ * \param[out] good_keys if this is a (initialized) list, the keys from keys that validate one of the signatures are added to it * \return status LDNS_STATUS_OK if there is at least one correct key */ -ldns_status ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, ldns_rr_list *keys, ldns_rr_list *good_keys); +ldns_status ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, ldns_rr_list *good_keys); /** * Verifies the already processed data in the buffers @@ -74,7 +75,7 @@ * \param[out] good_keys if this is a (initialized) list, the keys from keys that validate one of the signatures are added to it * \return a list of keys which validate the rrsig + rrset. Return NULL when none of the keys validate. */ -ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr_list *keys, ldns_rr_list *good_keys); +ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_list *keys, ldns_rr_list *good_keys); /** * verify an rrsig with 1 key @@ -237,4 +238,52 @@ */ ldns_status ldns_init_random(FILE *fd, uint16_t bytes); +/** + * Tries to build an authentication chain from the given keys down to the queried domain. + * + * If we find a valid trust path, return the valid keys for the domain. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \return the set of trusted keys for the domain, or NULL if no trust path could be built. + */ +ldns_rr_list * +ldns_fetch_valid_domain_keys(const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys); + +/** + * Validates the DNSKEY RRset for the given domain using the provided trusted keys. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated + */ +ldns_rr_list * +ldns_validate_domain_dnskey (const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys); + +/** + * Validates the DS RRset for the given domain using the provided trusted keys. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated + */ +ldns_rr_list * +ldns_validate_domain_ds (const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys); + +/** + * Verifies a list of signatures for one RRset using a valid trust path. + * + * \param[in] res the current resolver + * \param[in] rrset the rrset to verify + * \param[in] rrsigs a list of signatures to check + * \param[out] validating_keys if this is a (initialized) list, the keys from keys that validate one of the signatures are added to it + * \return status LDNS_STATUS_OK if there is at least one correct key + */ +ldns_status +ldns_verify_trusted(ldns_resolver * res, ldns_rr_list * rrset, ldns_rr_list * rrsigs, ldns_rr_list * validating_keys); + + #endif /* LDNS_DNSSEC_H */ Index: dnssec.c =================================================================== --- dnssec.c (revision 2344) +++ dnssec.c (working copy) @@ -76,7 +76,7 @@ } ldns_status -ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, ldns_rr_list *keys, +ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, ldns_rr_list *good_keys) { uint16_t i; @@ -112,7 +112,198 @@ return verify_result; } +ldns_rr_list * +ldns_fetch_valid_domain_keys(const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys) +{ + ldns_status status; + ldns_rr_list * trusted_keys = NULL; + ldns_rr_list * ds_keys = NULL; + + if (res && domain && keys) { + + if ((trusted_keys = ldns_validate_domain_dnskey(res, domain, keys))) { + status = LDNS_STATUS_OK; + } else { + + /* No trusted keys in this domain, we'll have to find some in the parent domain */ + status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; + + if (ldns_rdf_size(domain) > 1) { /* Fail if we are at the root */ + ldns_rr_list * parent_keys; + ldns_rdf * parent_domain = ldns_dname_left_chop(domain); + + if ((parent_keys = ldns_fetch_valid_domain_keys(res, parent_domain, keys))) { + + /* Check DS records */ + if ((ds_keys = ldns_validate_domain_ds(res, domain, parent_keys))) { + trusted_keys = ldns_fetch_valid_domain_keys(res, domain, ds_keys); + ldns_rr_list_deep_free(ds_keys); + } else { + /* No valid DS at the parent -- fail */ + status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ; + } + ldns_rr_list_deep_free(parent_keys); + } + ldns_rdf_free(parent_domain); + } + } + } + + return trusted_keys; +} + +ldns_rr_list * +ldns_validate_domain_dnskey (const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys) +{ + ldns_status status; + ldns_pkt * keypkt; + ldns_rr * cur_key; + uint16_t key_i; uint16_t key_j; uint16_t key_k; + uint16_t sig_i; ldns_rr * cur_sig; + + ldns_rr_list * domain_keys = NULL; + ldns_rr_list * domain_sigs = NULL; + ldns_rr_list * trusted_keys = NULL; + + /* Fetch keys for the domain */ + if ((keypkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD))) { + + domain_keys = ldns_pkt_rr_list_by_type(keypkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANSWER); + domain_sigs = ldns_pkt_rr_list_by_type(keypkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER); + + /* Try to validate the record using our keys */ + for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) { + + cur_key = ldns_rr_list_rr(domain_keys, key_i); + for (key_j=0; key_j References: <20070514121229.63bb073c@tx174.tx.local> Message-ID: <464839D0.2030200@NLnetLabs.nl> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Simon Vallet wrote: > Hi, > > these series of patches adds rudimentary full validation to ldns, which > has been tested in the following cases: > > Configured anchor (ZSK) -> RR > Configured anchor (KSK) -> ZSK -> RR > Configured anchor (KSK) -> ZSK -> DS -> ZSK -> RR > > Please consider these for integration > Thanks! We will Jelte -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGSDnO4nZCKsdOncURAm39AJ9yFuo+XgdrxLYc6HGVDseD5pcPxgCfWAVF 4lI0BnnoQ0hPqdk2DQyhZVg= =pQp8 -----END PGP SIGNATURE----- From svallet at genoscope.cns.fr Mon May 14 18:26:50 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Mon, 14 May 2007 20:26:50 +0200 Subject: [ldns-users] [PATCH 1bis/3] Add an anchor keyword to the resolver configuration In-Reply-To: <20070514121600.54a5508b@tx174.tx.local> References: <20070514121229.63bb073c@tx174.tx.local> <20070514121600.54a5508b@tx174.tx.local> Message-ID: <20070514202650.107fb384@mlejnas.priv.castalie.org> config.h.in needs to include errno.h for this one to build cleanly on Linux Simon --- ldns/config.h.in.orig 2007-05-14 20:20:41.000000000 +0200 +++ ldns/config.h.in 2007-05-14 20:08:49.000000000 +0200 @@ -206,6 +206,7 @@ #include #include #include +#include #if STDC_HEADERS #include From jelte at NLnetLabs.nl Wed May 16 14:56:11 2007 From: jelte at NLnetLabs.nl (Jelte Jansen) Date: Wed, 16 May 2007 16:56:11 +0200 Subject: [ldns-users] [PATCH 0/3] Add full validating capabilities to ldns In-Reply-To: <20070514121229.63bb073c@tx174.tx.local> References: <20070514121229.63bb073c@tx174.tx.local> Message-ID: <464B1B8B.4090005@NLnetLabs.nl> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Simon Vallet wrote: > Hi, > > these series of patches adds rudimentary full validation to ldns, which > has been tested in the following cases: > > Configured anchor (ZSK) -> RR > Configured anchor (KSK) -> ZSK -> RR > Configured anchor (KSK) -> ZSK -> DS -> ZSK -> RR > > Please consider these for integration > I have looked at the patches, and they look very useful. Thanks again. However, I don't think i want to leave the functions as they are now. I think it needs more error feedback (as they are, it almost always returns 'general error' on any dnssec error. While this might not be a problem for apps that only want to know 'ok' or 'not ok', it will be for more specified applications that want to know what went wrong. A lesser problem is something that is a bug in my opinion; the fetch_valid_domain_keys does not convey its status back to its calling function; my proposal for that would be to not let it return the trusted_keys value, but rather pass that one as a pointer argument, and return the status code. But what i want to reach is the point where one can see at what level and what the underlying error was; like 'validation failed at bogussig.test.jelte.nlnetlabs.nl; The DS record could not be validated: Bogus Signature'. But i need some time to examine how to put this in an (easy, or at least sane) API. Which has reminded me why i hadn't put this in the library yet :) If you have any objections to this, i can also make extra functions that to this, and leave your functions as they are (at least on the API level). Jelte -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGSxuK4nZCKsdOncURAqZIAJ47srQgmq6qpeVr2KVrINGeY1nyuACfaEGG 8DlFH6OTOvp6uiZfHL5Ez+M= =TS6n -----END PGP SIGNATURE----- From svallet at genoscope.cns.fr Thu May 17 09:29:41 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Thu, 17 May 2007 11:29:41 +0200 Subject: [ldns-users] [PATCH 0/3] Add full validating capabilities to ldns In-Reply-To: <464B1B8B.4090005@NLnetLabs.nl> References: <20070514121229.63bb073c@tx174.tx.local> <464B1B8B.4090005@NLnetLabs.nl> Message-ID: <20070517112941.2f814a08@mlejnas.priv.castalie.org> On Wed, 16 May 2007 16:56:11 +0200 Jelte Jansen wrote: > I have looked at the patches, and they look very useful. Thanks again. No problem -- thanks for ldns :-) > However, I don't think i want to leave the functions as they are now. I > think it needs more error feedback (as they are, it almost always > returns 'general error' on any dnssec error. While this might not be a > problem for apps that only want to know 'ok' or 'not ok', it will be for > more specified applications that want to know what went wrong. Yes -- I agree with that. This is what I had in mind first: in fact, you can still see the 'status' variable everywhere. But I got lazy trying to figure out a way to pass trusted_keys to fetch_valid_domain_keys: since it is called recursively, doing this cleanly without leaking could become very inelegant. I agree on the goal, though: it's always better to have a specific error status -- I'll take a look at it also. > But what i want to reach is the point where one can see at what level > and what the underlying error was; like > 'validation failed at bogussig.test.jelte.nlnetlabs.nl; The DS record > could not be validated: Bogus Signature'. Hmmm... if you want to propagate domain information along with the status code, then there is some more work to do. Maybe we could use some specific status struct here ? > If you have any objections to this, i can also make extra functions that > to this, and leave your functions as they are (at least on the API level). I'm totally OK with this: as I said, returning a specific status is always better. Besides, the only API I'm depending on is the one for ldns_verify_trusted, and I think this one is acceptable. Simon From jelte at NLnetLabs.nl Mon May 21 10:21:52 2007 From: jelte at NLnetLabs.nl (Jelte Jansen) Date: Mon, 21 May 2007 12:21:52 +0200 Subject: [ldns-users] [PATCH 0/3] Add full validating capabilities to ldns In-Reply-To: <20070517112941.2f814a08@mlejnas.priv.castalie.org> References: <20070514121229.63bb073c@tx174.tx.local> <464B1B8B.4090005@NLnetLabs.nl> <20070517112941.2f814a08@mlejnas.priv.castalie.org> Message-ID: <465172C0.2030204@NLnetLabs.nl> Simon Vallet wrote: > On Wed, 16 May 2007 16:56:11 +0200 > Jelte Jansen wrote: >> But what i want to reach is the point where one can see at what level >> and what the underlying error was; like >> 'validation failed at bogussig.test.jelte.nlnetlabs.nl; The DS record >> could not be validated: Bogus Signature'. > > Hmmm... if you want to propagate domain information along with the > status code, then there is some more work to do. Maybe we could use > some specific status struct here ? > I have got two approaches to this problem, a 'simple' one, and a not-so-simple, but in the end probably more flexible and clean one: 1) a linked list of errors, containing for example; dname, rr type, error, and a link to the same structure This approach would be the least work, and would let the current function remain mostly as they are now. However, this approach is also not very flexible, and an application would not be able to do much more that print what went wrong (not that i can think of much else to do at this moment, but hey). Therefore, i suggest another approach 3) separate the building of the dnssec trust chain and the validation of that chain: - first build a list-like structure, containing: - node rrset - parent type (DS or DNSKEY, if DS then there is no rrsig) - parent (pointer to another instance of this structure) - rrsig (and possibly some entries for optimization, like 'is_verified', but i want the base structures and algorithm right first) - then a seperate function can validate that chain at this point we're not much further than with the current approach, but now we can use the default functions that calls both of these if you only want to know 'verified' or 'not verified' (and optionally, return the error the application os most likely to want to know). Debuggers, and other programs that are more interested in failure scenario's, can show the complete dnssec chain together with all of it's data and intermediate results. This approach will definitely not be more efficient (you need to copy and store data, because the origin packets will be lost), Altough it might be more efficient in the number of actual queries it sends. It will definitely be more flexible (and allows, i think, for cleaner code). One question is whether it is actually possible to reliably build the chain without doing any validation in between (this could maybe be optimized later by optionally calling the verification at each level anyway). Anyway, this is what i'm leaning towards, thoughts are welcome. Jelte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 254 bytes Desc: OpenPGP digital signature URL: From jelte at NLnetLabs.nl Mon May 21 10:30:35 2007 From: jelte at NLnetLabs.nl (Jelte Jansen) Date: Mon, 21 May 2007 12:30:35 +0200 Subject: [ldns-users] [PATCH 0/3] Add full validating capabilities to ldns In-Reply-To: <465172C0.2030204@NLnetLabs.nl> References: <20070514121229.63bb073c@tx174.tx.local> <464B1B8B.4090005@NLnetLabs.nl> <20070517112941.2f814a08@mlejnas.priv.castalie.org> <465172C0.2030204@NLnetLabs.nl> Message-ID: <465174CB.4000503@NLnetLabs.nl> Jelte Jansen wrote: > Therefore, i suggest another approach > 3) separate the building of the dnssec trust chain and the validation of ^^^^^^ of course, i meant 2) here :) Jelte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 254 bytes Desc: OpenPGP digital signature URL: From miek at miek.nl Tue May 22 19:06:49 2007 From: miek at miek.nl (Miek Gieben) Date: Tue, 22 May 2007 21:06:49 +0200 Subject: [ldns-users] [PATCH 0/3] Add full validating capabilities to ldns In-Reply-To: <465172C0.2030204@NLnetLabs.nl> References: <20070514121229.63bb073c@tx174.tx.local> <464B1B8B.4090005@NLnetLabs.nl> <20070517112941.2f814a08@mlejnas.priv.castalie.org> <465172C0.2030204@NLnetLabs.nl> Message-ID: <20070522190649.GB20588@miek.nl> [On 21 May, @12:21, Jelte Jansen wrote in "Re: [ldns-users] [PATCH 0/3] A ..."] > 1) a linked list of errors, containing for example; dname, rr type, > error, and a link to the same structure > > However, this approach is also not very flexible, and an application > would not be able to do much more that print what went wrong (not that i > can think of much else to do at this moment, but hey). > > 2) separate the building of the dnssec trust chain and the validation of > that chain: > - first build a list-like structure, containing: > - node rrset > - parent type (DS or DNSKEY, if DS then there is no rrsig) > - parent (pointer to another instance of this structure) > - rrsig > (and possibly some entries for optimization, like 'is_verified', but i > want the base structures and algorithm right first) I think you make a good case for the second option, so my vote would be for number 2, -- grtz, - Miek http://www.miek.nl PGP: 6A3C F450 6D4E 7C6B C23C F982 258B 85CF 3880 D0F6 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 189 bytes Desc: Digital signature URL: From svallet at genoscope.cns.fr Wed May 23 15:57:06 2007 From: svallet at genoscope.cns.fr (Simon Vallet) Date: Wed, 23 May 2007 17:57:06 +0200 Subject: [ldns-users] [PATCH 0/3] Add full validating capabilities to ldns In-Reply-To: <465172C0.2030204@NLnetLabs.nl> References: <20070514121229.63bb073c@tx174.tx.local> <464B1B8B.4090005@NLnetLabs.nl> <20070517112941.2f814a08@mlejnas.priv.castalie.org> <465172C0.2030204@NLnetLabs.nl> Message-ID: <20070523175706.063d5754@tx174.tx.local> On Mon, 21 May 2007 12:21:52 +0200 Jelte Jansen wrote: > Therefore, i suggest another approach > 3) separate the building of the dnssec trust chain and the validation of > that chain: > - first build a list-like structure, containing: > - node rrset > - parent type (DS or DNSKEY, if DS then there is no rrsig) > - parent (pointer to another instance of this structure) > - rrsig > (and possibly some entries for optimization, like 'is_verified', but i > want the base structures and algorithm right first) > > - then a seperate function can validate that chain > > at this point we're not much further than with the current approach, but > now we can use the default functions that calls both of these if you > only want to know 'verified' or 'not verified' (and optionally, return > the error the application os most likely to want to know). Debuggers, > and other programs that are more interested in failure scenario's, can > show the complete dnssec chain together with all of it's data and > intermediate results. > > This approach will definitely not be more efficient (you need to copy > and store data, because the origin packets will be lost), Altough it > might be more efficient in the number of actual queries it sends. It > will definitely be more flexible (and allows, i think, for cleaner code). Well, you got my vote on this one too, even if the implementation is likely to be more complex (see below). > One question is whether it is actually possible to reliably build the > chain without doing any validation in between (this could maybe be > optimized later by optionally calling the verification at each level > anyway). I think it's possible, but unless all we have is a DS -> DNSKEY [-> DS ... ] chain, you'll probably end up with multiple possibilities to check at the end. Consider the following: (. DNSKEY) -> (com. DS) -> (com. DNSKEY) -> (example.com. DS) -> (example.com. DNSKEY) -> (www.example.com A) in this case, there will only be 1 RRSIG per RR, and we can walk up to the root without problems if we introduce a trusted (or non-trusted) KSK somewhere, say a second example.com DNSKEY, we now have two RRSIG on the example.com. apex RRset. This gives us several possible valid chains starting from example.com, which we'll all have to verify (at least until we find a trusted one). If you have the same situation at com., then you multiply the chains -- in this scenario, a tree-like structure with several parents might be more appropriate. As you said, efficiency would probably suffer, since you won't be able to know before validation which branches are worth building, and which are not. It seems worth to implement, though Simon