|
@@ -16,12 +16,23 @@
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
+#include <boost/scoped_ptr.hpp>
|
|
|
+
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
#include <cc/data.h>
|
|
|
|
|
|
+#include <config/ccsession.h>
|
|
|
+
|
|
|
#include <asiodns/asiodns.h>
|
|
|
#include <asiolink/asiolink.h>
|
|
|
+#include <asiolink/io_address.h>
|
|
|
+#include <asiolink/io_socket.h>
|
|
|
+#include <asiolink/io_message.h>
|
|
|
+
|
|
|
+#include <acl/acl.h>
|
|
|
+
|
|
|
+#include <server_common/client.h>
|
|
|
|
|
|
#include <resolver/resolver.h>
|
|
|
|
|
@@ -30,25 +41,37 @@
|
|
|
#include <testutils/portconfig.h>
|
|
|
|
|
|
using namespace std;
|
|
|
+using boost::scoped_ptr;
|
|
|
+using namespace isc::acl;
|
|
|
using namespace isc::data;
|
|
|
using namespace isc::testutils;
|
|
|
using namespace isc::asiodns;
|
|
|
using namespace isc::asiolink;
|
|
|
+using namespace isc::server_common;
|
|
|
using isc::UnitTestUtil;
|
|
|
|
|
|
namespace {
|
|
|
class ResolverConfig : public ::testing::Test {
|
|
|
- public:
|
|
|
- IOService ios;
|
|
|
- DNSService dnss;
|
|
|
- Resolver server;
|
|
|
- ResolverConfig() :
|
|
|
- dnss(ios, NULL, NULL, NULL)
|
|
|
- {
|
|
|
- server.setDNSService(dnss);
|
|
|
- server.setConfigured();
|
|
|
- }
|
|
|
- void invalidTest(const string &JSON, const string& name);
|
|
|
+protected:
|
|
|
+ IOService ios;
|
|
|
+ DNSService dnss;
|
|
|
+ Resolver server;
|
|
|
+ scoped_ptr<const IOEndpoint> endpoint;
|
|
|
+ scoped_ptr<const IOMessage> request;
|
|
|
+ scoped_ptr<const Client> client;
|
|
|
+ ResolverConfig() : dnss(ios, NULL, NULL, NULL) {
|
|
|
+ server.setDNSService(dnss);
|
|
|
+ server.setConfigured();
|
|
|
+ }
|
|
|
+ const Client& createClient(const string& source_addr) {
|
|
|
+ endpoint.reset(IOEndpoint::create(IPPROTO_UDP, IOAddress(source_addr),
|
|
|
+ 53210));
|
|
|
+ request.reset(new IOMessage(NULL, 0, IOSocket::getDummyUDPSocket(),
|
|
|
+ *endpoint));
|
|
|
+ client.reset(new Client(*request));
|
|
|
+ return (*client);
|
|
|
+ }
|
|
|
+ void invalidTest(const string &JSON, const string& name);
|
|
|
};
|
|
|
|
|
|
TEST_F(ResolverConfig, forwardAddresses) {
|
|
@@ -228,4 +251,122 @@ TEST_F(ResolverConfig, invalidTimeoutsConfig) {
|
|
|
"}", "Negative number of retries");
|
|
|
}
|
|
|
|
|
|
+TEST_F(ResolverConfig, defaultQueryACL) {
|
|
|
+ // If no configuration is loaded, the default ACL should reject everything.
|
|
|
+ EXPECT_EQ(REJECT, server.getQueryACL().execute(createClient("192.0.2.1")));
|
|
|
+ EXPECT_EQ(REJECT, server.getQueryACL().execute(
|
|
|
+ createClient("2001:db8::1")));
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(ResolverConfig, emptyQueryACL) {
|
|
|
+ // Explicitly configured empty ACL should have the same effect.
|
|
|
+ ElementPtr config(Element::fromJSON("{ \"query_acl\": [] }"));
|
|
|
+ ConstElementPtr result(server.updateConfig(config));
|
|
|
+ EXPECT_EQ(result->toWire(), isc::config::createAnswer()->toWire());
|
|
|
+ EXPECT_EQ(REJECT, server.getQueryACL().execute(createClient("192.0.2.1")));
|
|
|
+ EXPECT_EQ(REJECT, server.getQueryACL().execute(
|
|
|
+ createClient("2001:db8::1")));
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(ResolverConfig, queryACLIPv4) {
|
|
|
+ // A simple "accept" query for a specific IPv4 address
|
|
|
+ ElementPtr config(Element::fromJSON(
|
|
|
+ "{ \"query_acl\": "
|
|
|
+ " [ {\"action\": \"ACCEPT\","
|
|
|
+ " \"from\": \"192.0.2.1\"} ] }"));
|
|
|
+ ConstElementPtr result(server.updateConfig(config));
|
|
|
+ EXPECT_EQ(result->toWire(), isc::config::createAnswer()->toWire());
|
|
|
+ EXPECT_EQ(ACCEPT, server.getQueryACL().execute(createClient("192.0.2.1")));
|
|
|
+ EXPECT_EQ(REJECT, server.getQueryACL().execute(
|
|
|
+ createClient("2001:db8::1")));
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(ResolverConfig, queryACLIPv6) {
|
|
|
+ // same for IPv6
|
|
|
+ ElementPtr config(Element::fromJSON(
|
|
|
+ "{ \"query_acl\": "
|
|
|
+ " [ {\"action\": \"ACCEPT\","
|
|
|
+ " \"from\": \"2001:db8::1\"} ] }"));
|
|
|
+ ConstElementPtr result(server.updateConfig(config));
|
|
|
+ EXPECT_EQ(result->toWire(), isc::config::createAnswer()->toWire());
|
|
|
+ EXPECT_EQ(REJECT, server.getQueryACL().execute(createClient("192.0.2.1")));
|
|
|
+ EXPECT_EQ(ACCEPT, server.getQueryACL().execute(
|
|
|
+ createClient("2001:db8::1")));
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(ResolverConfig, compoundQueryACL) {
|
|
|
+ // A bit more complicated one: mixture of IPv4 and IPv6 with 3 rules
|
|
|
+ // in total. We shouldn't have to check so many variations of rules
|
|
|
+ // as it should have been tested in the underlying ACL module. All we
|
|
|
+ // have to do to check is a reasonably complicated ACL configuration is
|
|
|
+ // loaded as expected.
|
|
|
+ ElementPtr config(Element::fromJSON(
|
|
|
+ "{ \"query_acl\": "
|
|
|
+ " [ {\"action\": \"ACCEPT\","
|
|
|
+ " \"from\": \"192.0.2.1\"},"
|
|
|
+ " {\"action\": \"REJECT\","
|
|
|
+ " \"from\": \"192.0.2.0/24\"},"
|
|
|
+ " {\"action\": \"DROP\","
|
|
|
+ " \"from\": \"2001:db8::1\"},"
|
|
|
+ "] }"));
|
|
|
+ ConstElementPtr result(server.updateConfig(config));
|
|
|
+ EXPECT_EQ(result->toWire(), isc::config::createAnswer()->toWire());
|
|
|
+ EXPECT_EQ(ACCEPT, server.getQueryACL().execute(createClient("192.0.2.1")));
|
|
|
+ EXPECT_EQ(REJECT, server.getQueryACL().execute(createClient("192.0.2.2")));
|
|
|
+ EXPECT_EQ(DROP, server.getQueryACL().execute(
|
|
|
+ createClient("2001:db8::1")));
|
|
|
+ EXPECT_EQ(REJECT, server.getQueryACL().execute(
|
|
|
+ createClient("2001:db8::2"))); // match the default rule
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+getResultCode(ConstElementPtr result) {
|
|
|
+ int rcode;
|
|
|
+ isc::config::parseAnswer(rcode, result);
|
|
|
+ return (rcode);
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(ResolverConfig, badQueryACL) {
|
|
|
+ // Most of these cases shouldn't happen in practice because the syntax
|
|
|
+ // check should be performed before updateConfig(). But we check at
|
|
|
+ // least the server code won't crash even if an unexpected input is given.
|
|
|
+
|
|
|
+ // ACL must be a list
|
|
|
+ EXPECT_EQ(1, getResultCode(
|
|
|
+ server.updateConfig(
|
|
|
+ Element::fromJSON("{ \"query_acl\": 1 }"))));
|
|
|
+ // Each rule must have "action" and "from"
|
|
|
+ EXPECT_EQ(1, getResultCode(
|
|
|
+ server.updateConfig(
|
|
|
+ Element::fromJSON("{ \"query_acl\":"
|
|
|
+ " [ {\"from\": \"192.0.2.1\"} ] }"))));
|
|
|
+ EXPECT_EQ(1, getResultCode(
|
|
|
+ server.updateConfig(
|
|
|
+ Element::fromJSON("{ \"query_acl\":"
|
|
|
+ " [ {\"action\": \"DROP\"} ] }"))));
|
|
|
+ // invalid "action"
|
|
|
+ EXPECT_EQ(1, getResultCode(
|
|
|
+ server.updateConfig(
|
|
|
+ Element::fromJSON("{ \"query_acl\":"
|
|
|
+ " [ {\"action\": 1,"
|
|
|
+ " \"from\": \"192.0.2.1\"}]}"))));
|
|
|
+ EXPECT_EQ(1, getResultCode(
|
|
|
+ server.updateConfig(
|
|
|
+ Element::fromJSON("{ \"query_acl\":"
|
|
|
+ " [ {\"action\": \"BADACTION\","
|
|
|
+ " \"from\": \"192.0.2.1\"}]}"))));
|
|
|
+
|
|
|
+ // invalid "from"
|
|
|
+ EXPECT_EQ(1, getResultCode(
|
|
|
+ server.updateConfig(
|
|
|
+ Element::fromJSON("{ \"query_acl\":"
|
|
|
+ " [ {\"action\": \"ACCEPT\","
|
|
|
+ " \"from\": 53}]}"))));
|
|
|
+ EXPECT_EQ(1, getResultCode(
|
|
|
+ server.updateConfig(
|
|
|
+ Element::fromJSON("{ \"query_acl\":"
|
|
|
+ " [ {\"action\": \"ACCEPT\","
|
|
|
+ " \"from\": \"1922.0.2.1\"}]}"))));
|
|
|
+}
|
|
|
+
|
|
|
}
|