From 6888c78e1e5a5408adf6a1019e1c2d8789478f36 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Mon, 15 Feb 2010 10:49:03 +0000 Subject: [PATCH] Fix for Roy. git-svn-id: file:///svn/unbound/trunk@1982 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 6 + testdata/black_prime_entry.rpl | 311 +++++++++++++++++++++++++++++++++ validator/val_kentry.c | 5 +- validator/val_kentry.h | 5 +- validator/val_utils.c | 5 +- validator/validator.c | 12 +- validator/validator.h | 9 +- 7 files changed, 343 insertions(+), 10 deletions(-) create mode 100644 testdata/black_prime_entry.rpl diff --git a/doc/Changelog b/doc/Changelog index 70b3b64d8..9eddde136 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,9 @@ +15 February 2010: Wouter + - Fixed the requery protection, the TTL was 0, it is now 900 seconds, + hardcoded. We made the choice to send out more conservatively, + protecting against an aggregate effect more than protecting a + single user (from their own folly, perhaps in case of misconfig). + 12 February 2010: Wouter - Re-query pattern changed on validation failure. To protect troubled authority servers, unbound caches a failure for the DNSKEY or DS diff --git a/testdata/black_prime_entry.rpl b/testdata/black_prime_entry.rpl new file mode 100644 index 000000000..8ccbb90a7 --- /dev/null +++ b/testdata/black_prime_entry.rpl @@ -0,0 +1,311 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with blacklist prime gives bad key entry +; the data response needs a blacklist action as well, since it also +; comes from an 'expired signatures' name server. + +; 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 qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. 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 qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN A +SECTION ANSWER +ns.blabla.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +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. +;example.com. IN NS ns.blabla.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +; no ns.blabla.com, try that later +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. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. AKJ3xUBdSrCiOFkYajsy93d+h06rewpbmBHItTkL8R/26rw57b1gCIg= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR 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 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. ACFVLLBtuSX/1z3461tbOwDz9zTHe5S9DbVtwnSO1f2x06fYbMpzSDE= ;{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 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854} +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 +www.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGj9kE8oW3OhOLhkmJ3HBaNIOpvGf3S8zSd5gWmhpxAMc5hh6cxZfpQ= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACHETweBNPgbmRoNRdKvxuw4X9qNUUTEpSuwV+HhuiBE83gbB98asAc= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGvu9A/nGsbatxJCmnObioIhKg2Tm0Apr0eo+DO1kIDrAHco/bt/EdY= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.blabla.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +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. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{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 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} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABhDNtJramb2a4R1SK5gb/CTYJybQts6mZ++z3kLiwsrUSZInA4ikeQ= ;{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. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{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 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. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{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. +; later on, making sure DNSKEY primes give testbound failure. +RANGE_BEGIN 100 200 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ftp.example.com. IN A +SECTION ANSWER +ftp.example.com. IN A 10.20.33.33 +; very bad signature +ftp.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 100 TIME_PASSES ELAPSE 10 + +; second query should not result in going to the network. +STEP 110 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +ftp.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 120 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +ftp.example.com. IN A +ENTRY_END + + +SCENARIO_END diff --git a/validator/val_kentry.c b/validator/val_kentry.c index 0c80bab5b..fccaed431 100644 --- a/validator/val_kentry.c +++ b/validator/val_kentry.c @@ -294,13 +294,14 @@ key_entry_create_rrset(struct regional* region, struct key_entry_key* key_entry_create_bad(struct regional* region, - uint8_t* name, size_t namelen, uint16_t dclass) + uint8_t* name, size_t namelen, uint16_t dclass, uint32_t ttl, + uint32_t now) { struct key_entry_key* k; struct key_entry_data* d; if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) return NULL; - d->ttl = 0; + d->ttl = now + ttl; d->isbad = 1; d->reason = NULL; d->rrset_type = LDNS_RR_TYPE_DNSKEY; diff --git a/validator/val_kentry.h b/validator/val_kentry.h index 9b0fabe14..a63d1a050 100644 --- a/validator/val_kentry.h +++ b/validator/val_kentry.h @@ -190,10 +190,13 @@ struct key_entry_key* key_entry_create_rrset(struct regional* region, * @param name: the key name * @param namelen: length of name * @param dclass: class of key entry. (host order); + * @param ttl: what ttl should the key have. relative. + * @param now: current time (added to ttl). * @return new key entry or NULL on alloc failure */ struct key_entry_key* key_entry_create_bad(struct regional* region, - uint8_t* name, size_t namelen, uint16_t dclass); + uint8_t* name, size_t namelen, uint16_t dclass, uint32_t ttl, + uint32_t now); /** * Obtain rrset from a key entry, allocated in region. diff --git a/validator/val_utils.c b/validator/val_utils.c index 2eb88cde7..ff2b0f675 100644 --- a/validator/val_utils.c +++ b/validator/val_utils.c @@ -524,9 +524,10 @@ val_verify_new_DNSKEYs(struct regional* region, struct module_env* env, ds_rrset->rk.dname_len, ntohs(ds_rrset->rk.rrset_class), rrset_get_ttl(ds_rrset), *env->now); - } + } return key_entry_create_bad(region, ds_rrset->rk.dname, - ds_rrset->rk.dname_len, ntohs(ds_rrset->rk.rrset_class)); + ds_rrset->rk.dname_len, ntohs(ds_rrset->rk.rrset_class), + BOGUS_KEY_TTL, *env->now); } int diff --git a/validator/validator.c b/validator/validator.c index 7cb903e6a..5ea3ec176 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -2225,7 +2225,8 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, if(qstate->env->cfg->harden_dnssec_stripped) { errinf(qstate, "no DNSKEY rrset"); kkey = key_entry_create_bad(qstate->region, ta->name, - ta->namelen, ta->dclass); + ta->namelen, ta->dclass, BOGUS_KEY_TTL, + *qstate->env->now); } else kkey = key_entry_create_null(qstate->region, ta->name, ta->namelen, ta->dclass, NULL_KEY_TTL, *qstate->env->now); @@ -2275,7 +2276,8 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, if(qstate->env->cfg->harden_dnssec_stripped) { errinf(qstate, reason); kkey = key_entry_create_bad(qstate->region, ta->name, - ta->namelen, ta->dclass); + ta->namelen, ta->dclass, BOGUS_KEY_TTL, + *qstate->env->now); } else kkey = key_entry_create_null(qstate->region, ta->name, ta->namelen, ta->dclass, NULL_KEY_TTL, *qstate->env->now); @@ -2465,7 +2467,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq, } return_bogus: *ke = key_entry_create_bad(qstate->region, qinfo->qname, - qinfo->qname_len, qinfo->qclass); + qinfo->qname_len, qinfo->qclass, + BOGUS_KEY_TTL, *qstate->env->now); return (*ke) != NULL; } @@ -2582,7 +2585,8 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, return; } vq->key_entry = key_entry_create_bad(qstate->region, - qinfo->qname, qinfo->qname_len, qinfo->qclass); + qinfo->qname, qinfo->qname_len, qinfo->qclass, + BOGUS_KEY_TTL, *qstate->env->now); if(!vq->key_entry) { log_err("alloc failure in missing dnskey response"); /* key_entry is NULL for failure in Validate */ diff --git a/validator/validator.h b/validator/validator.h index 8ccf25307..bad084790 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -53,10 +53,17 @@ struct config_strlist; /** * This is the TTL to use when a trust anchor fails to prime. A trust anchor - * will be primed no more often than this interval. + * will be primed no more often than this interval. Used when harden- + * dnssec-stripped is off and the trust anchor fails. */ #define NULL_KEY_TTL 900 /* seconds */ +/** + * TTL for bogus key entries. When a DS or DNSKEY fails in the chain of + * trust the entire zone for that name is blacked out for this TTL. + */ +#define BOGUS_KEY_TTL 900 /* seconds */ + /** max number of query restarts, number of IPs to probe */ #define VAL_MAX_RESTART_COUNT 5