From: JINMEI Tatuya Date: Tue, 21 May 2013 20:50:01 +0000 (-0700) Subject: [2905] updated Query::process so it'll return SERVFAIL for empty(broken) zones. X-Git-Tag: bind10-1.2.0beta1-release~434^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fde6aa002772b6529f185148ce22cdbfabfe6a49;p=thirdparty%2Fkea.git [2905] updated Query::process so it'll return SERVFAIL for empty(broken) zones. --- diff --git a/src/bin/auth/query.cc b/src/bin/auth/query.cc index 770f624c8b..65e54100b8 100644 --- a/src/bin/auth/query.cc +++ b/src/bin/auth/query.cc @@ -386,6 +386,12 @@ Query::process(datasrc::ClientList& client_list, response_->setHeaderFlag(Message::HEADERFLAG_AA, false); response_->setRcode(Rcode::REFUSED()); return; + } else if (!result.finder_) { + // We found a matching zone in a data source but its data are not + // available. + response_->setHeaderFlag(Message::HEADERFLAG_AA, false); + response_->setRcode(Rcode::SERVFAIL()); + return; } ZoneFinder& zfinder = *result.finder_; diff --git a/src/bin/auth/tests/auth_srv_unittest.cc b/src/bin/auth/tests/auth_srv_unittest.cc index d63dc63613..f17d91eca2 100644 --- a/src/bin/auth/tests/auth_srv_unittest.cc +++ b/src/bin/auth/tests/auth_srv_unittest.cc @@ -1210,6 +1210,38 @@ TEST_F(AuthSrvTest, updateWithInMemoryClient) { opcode.getCode(), QR_FLAG, 1, 0, 0, 0); } +TEST_F(AuthSrvTest, emptyZone) { + // Similar to the previous setup, but the configuration has an error + // (zone file doesn't exist) and the query should result in SERVFAIL. + // Here we check the rcode other header parameters, and statistics. + + const ConstElementPtr config(Element::fromJSON("{" + "\"IN\": [{" + " \"type\": \"MasterFiles\"," + " \"params\": {\"example.com\": \"nosuchfile.zone\"}," + " \"cache-enable\": true" + "}]}")); + installDataSrcClientLists(server, configureDataSource(config)); + createDataFromFile("examplequery_fromWire.wire"); + server.processMessage(*io_message, *parse_message, *response_obuffer, + &dnsserv); + EXPECT_TRUE(dnsserv.hasAnswer()); + headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(), + opcode.getCode(), QR_FLAG, 1, 0, 0, 0); + + checkAllRcodeCountersZeroExcept(Rcode::SERVFAIL(), 1); + ConstElementPtr stats = server.getStatistics()->get("zones")-> + get("_SERVER_"); + std::map expect; + expect["request.v4"] = 1; + expect["request.udp"] = 1; + expect["opcode.query"] = 1; + expect["responses"] = 1; + expect["qrynoauthans"] = 1; + expect["rcode.servfail"] = 1; + checkStatisticsCounters(stats, expect); +} + TEST_F(AuthSrvTest, queryWithInMemoryClientNoDNSSEC) { // In this example, we do simple check that query is handled from the // query handler class, and confirm it returns no error and a non empty diff --git a/src/bin/auth/tests/query_unittest.cc b/src/bin/auth/tests/query_unittest.cc index 0c11dcd591..32092b0a14 100644 --- a/src/bin/auth/tests/query_unittest.cc +++ b/src/bin/auth/tests/query_unittest.cc @@ -961,6 +961,12 @@ protected: setNSEC3HashCreator(NULL); } + bool isEmptyZoneSupported() const { + // Not all data sources support the concept of empty zones. + // Specifically for this test, SQLite3-based data source doesn't. + return (GetParam() != SQLITE3); + } + void enableNSEC3(const vector& rrsets_to_add) { boost::shared_ptr new_list; switch (GetParam()) { @@ -1160,6 +1166,25 @@ TEST_P(QueryTest, noZone) { EXPECT_EQ(Rcode::REFUSED(), response.getRcode()); } +TEST_P(QueryTest, emptyZone) { + // Query for an "empty (broken)" zone. If the concept is supported by + // the underlying data source, the result should be SERVFAIL; otherwise + // it would be handled as a nonexistent zone, resulting in REFUSED. + const Rcode expected_rcode = + isEmptyZoneSupported() ? Rcode::SERVFAIL() : Rcode::REFUSED(); + + query.process(*list_, Name(EMPTY_ZONE_NAME), qtype, response); + responseCheck(response, expected_rcode, 0, 0, 0, 0, NULL, NULL, NULL); + + // Same for the partial match case + response.clear(isc::dns::Message::RENDER); + response.setRcode(Rcode::NOERROR()); + response.setOpcode(Opcode::QUERY()); + query.process(*list_, Name(string("www.") + EMPTY_ZONE_NAME), qtype, + response); + responseCheck(response, expected_rcode, 0, 0, 0, 0, NULL, NULL, NULL); +} + TEST_P(QueryTest, exactMatch) { EXPECT_NO_THROW(query.process(*list_, qname, qtype, response)); // find match rrset