diff --git a/doc/Changelog b/doc/Changelog index 325285337..2a7cb870d 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,8 @@ +4 July 2024: Wouter + - Fix to print details about the failure to lookup a DNSKEY record + when validation fails due to the missing DNSKEY. Also for key prime + and DS lookups. + 3 July 2024: Yorgos - Fix for repeated use of a DNAME record: first overallocate and then move the exact size of the init value to avoid false positive heap diff --git a/testdata/val_failure_dnskey.rpl b/testdata/val_failure_dnskey.rpl new file mode 100644 index 000000000..3f25f15b2 --- /dev/null +++ b/testdata/val_failure_dnskey.rpl @@ -0,0 +1,348 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DS 1444 8 2 69887be92d4848c0bc10acc95682a01e7e3b57ab0750a2ee6f72cac7191a64f1" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: "no" + fake-sha1: yes + trust-anchor-signaling: no + minimal-responses: no + log-servfail: yes + val-log-level: 2 + ede: yes + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with failure for chaing of trust lookup. +; The error message that is created, also for EDE is more extensive. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +;ENTRY_BEGIN +;MATCH opcode qtype qname +;ADJUST copy_id +;REPLY QR NOERROR +;SECTION QUESTION +;example.com. IN DNSKEY +;SECTION ANSWER +;example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +;SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +;ENTRY_END +; servfail for DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +example.com. IN DNSKEY +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. 3600 IN NS ns.example.net. +example.net. 3600 IN RRSIG NS 8 2 3600 20070926134150 20070829134150 1444 example.net. nHpOqZb00nIGytQ1YmVoXEHURL/75dWhlKSEtRTorjVdPGPZNN7ziCWJW303v7u07TkZ+i6oFVEWG/SDR4ejn5o31UKJy1373PEH/cvPf9/44jw9gAFaHF1eO6ZQGaRQaeEpU06+xUcnc2QXFt6rNu60EsTvMRDN83bD+r7FA7Y= +SECTION ADDITIONAL +ns.example.net. 3600 IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 1444 example.net. TgQ4nfGtLHuZXlC4JJlVQ6mejf1WJbstTxsh/kgMAc2tryOxF/gvGBHaMtz6oceFZrIgk6g3RYI1Gk5gjSFNADh+EIwI422M8XPAAxRLfFahiO4lr1aCo4c94TYeZNpnDKy81rINTz2hQE1pGWr8Z03ySABqSBnTE1FQt4N/JCo= +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. 3600 IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 1444 example.net. TgQ4nfGtLHuZXlC4JJlVQ6mejf1WJbstTxsh/kgMAc2tryOxF/gvGBHaMtz6oceFZrIgk6g3RYI1Gk5gjSFNADh+EIwI422M8XPAAxRLfFahiO4lr1aCo4c94TYeZNpnDKy81rINTz2hQE1pGWr8Z03ySABqSBnTE1FQt4N/JCo= +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. 3600 IN SOA ns.example.net. host.example.net. 1 3600 300 7200 3600 +example.net. 3600 IN RRSIG SOA 8 2 3600 20070926134150 20070829134150 1444 example.net. P5FRQ4A/0n5owaBhZqlYBFD2PNAWJc5oxiDwvwh0hdjxETx8ta3EAvDKtNj5XZ5EKDAhP/tivd+Bq50I0xfRBmrouxgxjgnV3ye8zU+M1fXbuKpsWme9R3S4cs9WYfggTn7X00Af8m0tE62SLH/ZtOOQi2CvOPu7PXtHYT6KW4Q= +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 257 3 8 AwEAAbd9WqjzE2Pynz21OG5doSf9hFzMr5dhzz2waZ3vTa+0o5r7AjTAqmA1yH/B3+aAMihUm5ucZSfVqo7+kOaRE8yFj9aivOmA1n1+JLevJq/oyvQyjxQN2Qb89LyaNUT5oKZIiL+uyyhNW3KDR3SSbQ/GBwQNDHVcZi+JDR3RC0r7 ;{id = 1444 (ksk), size = 1024b} +example.net. 3600 IN RRSIG DNSKEY 8 2 3600 20070926134150 20070829134150 1444 example.net. hAAlJt/YwAgWBzseK0N42+ysSMaWgntcuftF8a43chLh+fbe3vPWrgwqr/Cic52tu4ZqMox592tqWDxAG7F1eDGfO0SfzS2C9Tc/Wnz5nFjFh75G4Mtt8DTv5vTyGUVX5zAFzV8SNijVC0o1F7MHaVPt3rFtjjg2zW/UOz2m9+U= +ENTRY_END + +; For sub1.example.net. zone; it is co-hosted with example.net, so that +; there can be failures for the DS lookup. But the data lookup succeeds. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub1.example.net. IN A +SECTION ANSWER +www.sub1.example.net. IN A 10.20.30.41 +www.sub1.example.net. 3600 IN RRSIG A 8 4 3600 20070926134150 20070829134150 29332 sub1.example.net. NcFP77Hixawt8hb+STIbbeqdF9tWTuHsbGEB4agKXlwHqS0BnyA+It6+UdE57IF0Kbnc7gSuaslX9At8ctd4HuC/9F/osbo96o23JEfnXPky/r5SsLaeN5KmUmUVjG9oxyAEc6PVlaaQ5a/RhaxmDRaDiku2gB7KjdjPxwxe+Rc54GV2eM3GtcfT+oDakLdSSACqeVjUFIOtYMpG8jAHrBe4uSnjKI7O0fWDFN5OES6sN9iUS9/ceorIoF/gSIqM7xWEuPLxE2c5TtYJyPtMCeGJ9wBP4wrTXfJ58+Lg5SFKgEuKTvAqEv9KEwg/kJb1GQ+ho5XKFO6EII2iyeUK/w== +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR SERVFAIL +SECTION QUESTION +sub1.example.net. IN DS +SECTION ANSWER +; no DS for sub1.example.net id=29332 algo=8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub2.example.net. IN A +SECTION ANSWER +www.sub2.example.net. IN A 10.20.30.42 +www.sub2.example.net. 3600 IN RRSIG A 8 4 3600 20070926134150 20070829134150 29332 sub2.example.net. FOY6YxNoFyrSkBtWV7HcECmORTMedRWHdGk7Rm04icT8Bw0dWfzVaIpAkBY6FXx8UvqN7McN4IJI5dAVXptfekO+Yvy2PwkjehRUXvQK64XH5UM5pVbX5g8E4pnOrLa/jzPB7srzMpyWVCpt81lPoFpdfXUMm7434ifkTYhpAll7y5NAocFiT3F+XGe06qMIr51WxoFfegIGohMFhkTDUdLWrdV10128W+NzPdwoYtiigtCObKxTtyj3gK+mxqXvX4X4F2YIGQ+mx62ovdUilnLYZm/WC/ZQkdxeOZjeCTxvSpGGG+wtu1QufgIJ+BpAZAOxREOYZkhR29AG0np4EA== +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR SERVFAIL +SECTION QUESTION +sub2.example.net. IN DNSKEY +SECTION ANSWER +; sub2.example.net. IN DNSKEY 257 3 8 AwEAAb4WMOTBLTFvmBra5m6SK4VfViOzmvyUAU0qv861ZQXeEFvwlndqNU9rwRsMxrSWAYs5nHErKDn49usC/HyxxW1477iGFHhfgL4mjNreJm9zft2QFB1VLbRbEPYdDMLCn4co0qnG7/KG8W2i8Pym1L7f+aREwbLo+/716AS2PbaKMhfWLKLiq5wnBcUClQMNzCiwhqxDJp1oePqfkVdeUgXOtgi0dYRIKyQFhJ5VWJ22npoi/Gif0XLCADAlAwRLKc8o/yJkCxskzgpHpw5Cki1lclg0aq4ssOuPRQ+ne6IHYCz9D2mwzulblhLFamKdq7aHzNt4NlyxhpANVFiKLD8= ;{id = 29332 (ksk), size = 2048b} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub2.example.net. IN DS +SECTION ANSWER +sub2.example.net. 3600 IN DS 29332 8 2 d53e615d9d736b0f2a0097f1d5fa51c84320610f94ecbd7197e7de5f44f02d72 +sub2.example.net. 3600 IN RRSIG DS 8 3 3600 20070926134150 20070829134150 1444 example.net. dYLYs1uMxJm5+MB6L1+uStE5S1YtyYR0JF+1pPoTptc/H1hYqMxK7pVQPtIGvq8j8wNyC7jOzALfEXgwRKiSdR1l1GQ5HIxWkhUmkpLcecwJOjemee4nXaifOFa5bdbdYpuDwTiIzx+PvanlaVjEPy0i1IukanDi6jojfyWcgLA= +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; The DNSKEY lookup for the key prime is a failure. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ede=9 +REPLY QR RD RA DO SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub1.example.net. IN A +ENTRY_END + +; The DS lookup is a failure. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ede=23 +REPLY QR RD RA DO SERVFAIL +SECTION QUESTION +www.sub1.example.net. IN A +SECTION ANSWER +ENTRY_END + +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub2.example.net. IN A +ENTRY_END + +; The DNSKEY lookup is a failure. +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ede=9 +REPLY QR RD RA DO SERVFAIL +SECTION QUESTION +www.sub2.example.net. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/validator/validator.c b/validator/validator.c index 39ae58eae..59226abcc 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -72,7 +72,8 @@ /* forward decl for cache response and normal super inform calls of a DS */ static void process_ds_response(struct module_qstate* qstate, struct val_qstate* vq, int id, int rcode, struct dns_msg* msg, - struct query_info* qinfo, struct sock_list* origin, int* suspend); + struct query_info* qinfo, struct sock_list* origin, int* suspend, + struct module_qstate* sub_qstate); /* Updates the suplied EDE (RFC8914) code selectively so we don't lose @@ -2066,7 +2067,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id) verbose(VERB_ALGO, "Process suspended sub DS response"); msg = vq->sub_ds_msg; process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR, - msg, &msg->qinfo, NULL, &suspend); + msg, &msg->qinfo, NULL, &suspend, NULL); if(suspend) { /* we'll come back here later to continue */ if(!validate_suspend_setup_timer(qstate, vq, @@ -2082,7 +2083,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id) vq->key_entry->name)) ) { verbose(VERB_ALGO, "Process cached DS response"); process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR, - msg, &msg->qinfo, NULL, &suspend); + msg, &msg->qinfo, NULL, &suspend, NULL); if(suspend) { /* we'll come back here later to continue */ if(!validate_suspend_setup_timer(qstate, vq, @@ -2664,6 +2665,8 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id, * @param ta: trust anchor. * @param qstate: qstate that needs key. * @param id: module id. + * @param sub_qstate: the sub query state, that is the lookup that fetched + * the trust anchor data, it contains error information for the answer. * @return new key entry or NULL on allocation failure. * The key entry will either contain a validated DNSKEY rrset, or * represent a Null key (query failed, but validation did not), or a @@ -2671,7 +2674,8 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id, */ static struct key_entry_key* primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, - struct trust_anchor* ta, struct module_qstate* qstate, int id) + struct trust_anchor* ta, struct module_qstate* qstate, int id, + struct module_qstate* sub_qstate) { struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; struct key_entry_key* kkey = NULL; @@ -2681,11 +2685,18 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, int downprot = qstate->env->cfg->harden_algo_downgrade; if(!dnskey_rrset) { + char* err = errinf_to_str_misc(sub_qstate); + char reason[1024]; log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- " "could not fetch DNSKEY rrset", ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); reason_bogus = LDNS_EDE_DNSKEY_MISSING; - reason = "no DNSKEY rrset"; + if(!err) { + snprintf(reason, sizeof(reason), "no DNSKEY rrset"); + } else { + snprintf(reason, sizeof(reason), "no DNSKEY rrset " + "[%s]", err); + } if(qstate->env->cfg->harden_dnssec_stripped) { errinf_ede(qstate, reason, reason_bogus); kkey = key_entry_create_bad(qstate->region, ta->name, @@ -2760,6 +2771,9 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, * DS response indicated an end to secure space, is_good if the DS * validated. It returns ke=NULL if the DS response indicated that the * request wasn't a delegation point. + * @param sub_qstate: the sub query state, that is the lookup that fetched + * the trust anchor data, it contains error information for the answer. + * Can be NULL. * @return * 0 on success, * 1 on servfail error (malloc failure), @@ -2768,7 +2782,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, static int ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq, int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, - struct key_entry_key** ke) + struct key_entry_key** ke, struct module_qstate* sub_qstate) { struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; char* reason = NULL; @@ -2783,6 +2797,11 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq, verbose(VERB_DETAIL, "DS response was error, thus bogus"); errinf(qstate, rc); reason = "no DS"; + if(sub_qstate) { + errinf(qstate, "["); + errinf(qstate, errinf_to_str_misc(sub_qstate)); + errinf(qstate, "]"); + } reason_bogus = LDNS_EDE_NETWORK_ERROR; errinf_ede(qstate, reason, reason_bogus); goto return_bogus; @@ -3008,11 +3027,15 @@ return_bogus: * @param origin: the origin of msg. * @param suspend: returned true if the task takes too long and needs to * suspend to continue the effort later. + * @param sub_qstate: the sub query state, that is the lookup that fetched + * the trust anchor data, it contains error information for the answer. + * Can be NULL. */ static void process_ds_response(struct module_qstate* qstate, struct val_qstate* vq, int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, - struct sock_list* origin, int* suspend) + struct sock_list* origin, int* suspend, + struct module_qstate* sub_qstate) { struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; struct key_entry_key* dske = NULL; @@ -3020,7 +3043,8 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq, int ret; *suspend = 0; vq->empty_DS_name = NULL; - ret = ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske); + ret = ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske, + sub_qstate); if(ret != 0) { switch(ret) { case 1: @@ -3096,11 +3120,13 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq, * @param msg: result message (if rcode is OK). * @param qinfo: from the sub query state, query info. * @param origin: the origin of msg. + * @param sub_qstate: the sub query state, that is the lookup that fetched + * the trust anchor data, it contains error information for the answer. */ static void process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, - struct sock_list* origin) + struct sock_list* origin, struct module_qstate* sub_qstate) { struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; struct key_entry_key* old = vq->key_entry; @@ -3113,6 +3139,8 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, dnskey = reply_find_answer_rrset(qinfo, msg->rep); if(dnskey == NULL) { + char* err; + char reason[1024]; /* bad response */ verbose(VERB_DETAIL, "Missing DNSKEY RRset in response to " "DNSKEY query."); @@ -3124,7 +3152,13 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, vq->restart_count++; return; } - reason = "No DNSKEY record"; + err = errinf_to_str_misc(sub_qstate); + if(!err) { + snprintf(reason, sizeof(reason), "No DNSKEY record"); + } else { + snprintf(reason, sizeof(reason), "No DNSKEY record " + "[%s]", err); + } reason_bogus = LDNS_EDE_DNSKEY_MISSING; vq->key_entry = key_entry_create_bad(qstate->region, qinfo->qname, qinfo->qname_len, qinfo->qclass, @@ -3198,10 +3232,13 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, * @param rcode: rcode result value. * @param msg: result message (if rcode is OK). * @param origin: the origin of msg. + * @param sub_qstate: the sub query state, that is the lookup that fetched + * the trust anchor data, it contains error information for the answer. */ static void process_prime_response(struct module_qstate* qstate, struct val_qstate* vq, - int id, int rcode, struct dns_msg* msg, struct sock_list* origin) + int id, int rcode, struct dns_msg* msg, struct sock_list* origin, + struct module_qstate* sub_qstate) { struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; struct ub_packed_rrset_key* dnskey_rrset = NULL; @@ -3233,7 +3270,8 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq, return; } } - vq->key_entry = primeResponseToKE(dnskey_rrset, ta, qstate, id); + vq->key_entry = primeResponseToKE(dnskey_rrset, ta, qstate, id, + sub_qstate); lock_basic_unlock(&ta->lock); if(vq->key_entry) { if(key_entry_isbad(vq->key_entry) @@ -3284,14 +3322,14 @@ val_inform_super(struct module_qstate* qstate, int id, if(vq->wait_prime_ta) { vq->wait_prime_ta = 0; process_prime_response(super, vq, id, qstate->return_rcode, - qstate->return_msg, qstate->reply_origin); + qstate->return_msg, qstate->reply_origin, qstate); return; } if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS) { int suspend; process_ds_response(super, vq, id, qstate->return_rcode, qstate->return_msg, &qstate->qinfo, - qstate->reply_origin, &suspend); + qstate->reply_origin, &suspend, qstate); /* If NSEC3 was needed during validation, NULL the NSEC3 cache; * it will be re-initiated if needed later on. * Validation (and the cache table) are happening/allocated in @@ -3312,7 +3350,7 @@ val_inform_super(struct module_qstate* qstate, int id, } else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY) { process_dnskey_response(super, vq, id, qstate->return_rcode, qstate->return_msg, &qstate->qinfo, - qstate->reply_origin); + qstate->reply_origin, qstate); return; } log_err("internal error in validator: no inform_supers possible");