2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-31 05:55:28 +00:00

[trac999] apply query ACL for incoming queries

This commit is contained in:
JINMEI Tatuya
2011-06-21 17:18:59 -07:00
parent e9a1e75b3d
commit 5aabfb971d
5 changed files with 98 additions and 16 deletions

View File

@@ -155,6 +155,14 @@ public:
OutputBufferPtr buffer,
DNSServer* server);
const Resolver::ClientACL& getQueryACL() const {
return (*query_acl_);
}
void setQueryACL(shared_ptr<const Resolver::ClientACL> new_acl) {
query_acl_ = new_acl;
}
/// Currently non-configurable, but will be.
static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
@@ -177,11 +185,10 @@ public:
/// Number of retries after timeout
unsigned retries_;
private:
/// TBD
shared_ptr<const Resolver::ClientACL> query_acl_;
private:
/// Object to handle upstream queries
RecursiveQuery* rec_query_;
};
@@ -453,25 +460,44 @@ Resolver::processMessage(const IOMessage& io_message,
buffer, Rcode::NOTAUTH());
// Notify arrived, but we are not authoritative.
LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_NFYNOTAUTH);
} else if (query_message->getOpcode() != Opcode::QUERY()) {
// Unsupported opcode.
LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_OPCODEUNS)
.arg(query_message->getOpcode());
makeErrorMessage(query_message, answer_message,
buffer, Rcode::NOTIMP());
} else if (query_message->getRRCount(Message::SECTION_QUESTION) != 1) {
// Not one question
LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_NOTONEQUES)
.arg(query_message->getRRCount(Message::SECTION_QUESTION));
makeErrorMessage(query_message, answer_message,
buffer, Rcode::FORMERR());
} else {
ConstQuestionPtr question = *query_message->beginQuestion();
const RRType &qtype = question->getType();
const ConstQuestionPtr question = *query_message->beginQuestion();
const RRType qtype = question->getType();
Client client(io_message);
const BasicAction query_action(impl_->getQueryACL().execute(client));
if (query_action == REJECT) {
LOG_INFO(resolver_logger, RESOLVER_QUERYREJECTED)
.arg(question->getName()).arg(qtype).arg(question->getClass())
.arg(client);
makeErrorMessage(query_message, answer_message, buffer,
Rcode::REFUSED());
// the following should be refactored
server->resume(true);
return;
} else if (query_action == DROP) {
LOG_INFO(resolver_logger, RESOLVER_QUERYDROPPED)
.arg(question->getName()).arg(qtype).arg(question->getClass())
.arg(client);
server->resume(false);
return;
}
LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_QUERYACCEPTED)
.arg(question->getName()).arg(qtype).arg(question->getClass())
.arg(client);
if (qtype == RRType::AXFR()) {
if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
@@ -481,7 +507,6 @@ Resolver::processMessage(const IOMessage& io_message,
makeErrorMessage(query_message, answer_message,
buffer, Rcode::FORMERR());
} else {
// ... or over TCP for that matter
LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
RESOLVER_AXFRTCP);
@@ -489,12 +514,10 @@ Resolver::processMessage(const IOMessage& io_message,
buffer, Rcode::NOTIMP());
}
} else if (qtype == RRType::IXFR()) {
// Can't process IXFR request
LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_IXFR);
makeErrorMessage(query_message, answer_message,
buffer, Rcode::NOTIMP());
} else if (question->getClass() != RRClass::IN()) {
// Non-IN message received, refuse it.
@@ -754,11 +777,11 @@ Resolver::getListenAddresses() const {
const Resolver::ClientACL&
Resolver::getQueryACL() const {
return (*impl_->query_acl_);
return (impl_->getQueryACL());
}
void
Resolver::setQueryACL(shared_ptr<const ClientACL> new_acl) {
LOG_INFO(resolver_logger, RESOLVER_SETQUERYACL);
impl_->query_acl_ = new_acl;
impl_->setQueryACL(new_acl);
}

View File

@@ -195,3 +195,12 @@ query and is ignoring it.
% SETQUERYACL query ACL is configured
A debug message that appears when a new query ACL is configured for the
resolver.
%QUERYREJECTED query rejected: '%1/%2/%3' from %4
TBD
%QUERYDROPPED query dropped: '%1/%2/%3' from %4
TBD
%QUERYACCEPTED query accepted: '%1/%2/%3' from %4
TBD

View File

@@ -12,14 +12,19 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <string>
#include <dns/name.h>
#include <cc/data.h>
#include <resolver/resolver.h>
#include <dns/tests/unittest_util.h>
#include <testutils/dnsmessage_test.h>
#include <testutils/srv_test.h>
using namespace std;
using namespace isc::dns;
using namespace isc::data;
using namespace isc::testutils;
using isc::UnitTestUtil;
@@ -28,7 +33,17 @@ const char* const TEST_PORT = "53535";
class ResolverTest : public SrvTestBase{
protected:
ResolverTest() : server(){}
ResolverTest() : server() {
// By default queries from the "default remote address" will be
// rejected, so we'll need to add an explicit ACL entry to allow that.
server.setConfigured();
server.updateConfig(Element::fromJSON(
"{ \"query_acl\": "
" [ {\"action\": \"ACCEPT\","
" \"from\": \"" +
string(DEFAULT_REMOTE_ADDRESS) +
"\"} ] }"));
}
virtual void processMessage() {
server.processMessage(*io_message,
parse_message,
@@ -136,4 +151,38 @@ TEST_F(ResolverTest, notifyFail) {
Opcode::NOTIFY().getCode(), QR_FLAG, 0, 0, 0, 0);
}
TEST_F(ResolverTest, queryACL) {
// The "ACCEPT" cases are covered in other tests. Here we explicitly
// test "REJECT" and "DROP" cases.
// Clear the existing ACL, reverting to the "default reject" rule.
// AXFR over UDP. This would otherwise result in FORMERR.
server.updateConfig(Element::fromJSON("{ \"query_acl\": [] }"));
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("example.com"), RRClass::IN(),
RRType::AXFR());
createRequestPacket(request_message, IPPROTO_UDP);
server.processMessage(*io_message, parse_message, response_message,
response_obuffer, &dnsserv);
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, Rcode::REFUSED(),
Opcode::QUERY().getCode(), QR_FLAG, 1, 0, 0, 0);
// Same query, but with an explicit "DROP" ACL entry. There should be
// no response.
parse_message->clear(Message::PARSE);
response_message->clear(Message::RENDER);
response_obuffer->clear();
server.updateConfig(Element::fromJSON("{ \"query_acl\": "
" [ {\"action\": \"DROP\","
" \"from\": \"" +
string(DEFAULT_REMOTE_ADDRESS) +
"\"} ] }"));
server.processMessage(*io_message, parse_message, response_message,
response_obuffer, &dnsserv);
EXPECT_FALSE(dnsserv.hasAnswer());
}
}

View File

@@ -23,7 +23,8 @@ main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
isc::UnitTestUtil::addDataPath(TEST_DATA_DIR);
isc::UnitTestUtil::addDataPath(TEST_DATA_BUILDDIR);
isc::log::initLogger();
isc::log::initLogger("resolver_test", isc::log::DEBUG,
isc::log::MAX_DEBUG_LEVEL);
return (isc::util::unittests::run_all());
}

View File

@@ -1,3 +1,3 @@
SUBDIRS = exceptions util log cryptolink dns cc config python xfr \
bench asiolink asiodns nsas cache resolve testutils datasrc \
server_common acl
acl server_common