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:
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user