Commit 900a3c58 authored by Dima Volodin's avatar Dima Volodin
Browse files

Merge branch 'master' into trac1155

parents af698f41 0711c996
275. [func] jinmei
Added support for TSIG key matching in ACLs. The xfrout ACL can
now refer to TSIG key names using the "key" attribute. For
example, the following specifies an ACL that allows zone transfer
if and only if the request is signed with a TSIG of a key name
"key.example":
> config set Xfrout/query_acl[0] {"action": "ACCEPT", \
"key": "key.example"}
(Trac #1104, git 9b2e89cabb6191db86f88ee717f7abc4171fa979)
274. [bug] naokikambe
add unittests for functions xml_handler, xsd_handler and xsl_handler
respectively to make sure their behaviors are correct, regardless of
......
......@@ -23,14 +23,14 @@ BIND10_PATH=@abs_top_builddir@/src/bin/bind10
PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/resolver:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:@abs_top_builddir@/src/bin/dhcp6:$PATH
export PATH
PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/python/isc/config
PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/python/isc/config:@abs_top_builddir@/src/lib/python/isc/acl/.libs:
export PYTHONPATH
# If necessary (rare cases), explicitly specify paths to dynamic libraries
# required by loadable python modules.
SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
if test $SET_ENV_LIBRARY_PATH = yes; then
@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/acl/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
export @ENV_LIBRARY_PATH@
fi
......
......@@ -520,7 +520,8 @@ ResolverImpl::processNormalQuery(const IOMessage& io_message,
const Client client(io_message);
const BasicAction query_action(
getQueryACL().execute(acl::dns::RequestContext(
client.getRequestSourceIPAddress())));
client.getRequestSourceIPAddress(),
query_message->getTSIGRecord())));
if (query_action == isc::acl::REJECT) {
LOG_INFO(resolver_logger, RESOLVER_QUERY_REJECTED)
.arg(question->getName()).arg(qtype).arg(qclass).arg(client);
......
......@@ -72,7 +72,8 @@ protected:
IOSocket::getDummyUDPSocket(),
*endpoint));
client.reset(new Client(*query_message));
request.reset(new RequestContext(client->getRequestSourceIPAddress()));
request.reset(new RequestContext(client->getRequestSourceIPAddress(),
NULL));
return (*request);
}
void invalidTest(const string &JSON, const string& name);
......
......@@ -137,7 +137,8 @@ class TestXfroutSession(unittest.TestCase):
self.assertEqual(rcode.to_text(), "NOTAUTH")
self.assertTrue(self.xfrsess._tsig_ctx is not None)
# NOERROR
self.xfrsess._tsig_key_ring.add(TSIG_KEY)
self.assertEqual(TSIGKeyRing.SUCCESS,
self.xfrsess._tsig_key_ring.add(TSIG_KEY))
[rcode, msg] = self.xfrsess._parse_query_message(request_data)
self.assertEqual(rcode.to_text(), "NOERROR")
self.assertTrue(self.xfrsess._tsig_ctx is not None)
......@@ -172,6 +173,54 @@ class TestXfroutSession(unittest.TestCase):
self.assertEqual(rcode.to_text(), "NOTAUTH")
self.assertTrue(self.xfrsess._tsig_ctx is not None)
# ACL using TSIG: successful case
self.xfrsess._acl = isc.acl.dns.REQUEST_LOADER.load([
{"key": "example.com", "action": "ACCEPT"}, {"action": "REJECT"}
])
self.assertEqual(TSIGKeyRing.SUCCESS,
self.xfrsess._tsig_key_ring.add(TSIG_KEY))
[rcode, msg] = self.xfrsess._parse_query_message(request_data)
self.assertEqual(rcode.to_text(), "NOERROR")
# ACL using TSIG: key name doesn't match; should be rejected
self.xfrsess._acl = isc.acl.dns.REQUEST_LOADER.load([
{"key": "example.org", "action": "ACCEPT"}, {"action": "REJECT"}
])
[rcode, msg] = self.xfrsess._parse_query_message(request_data)
self.assertEqual(rcode.to_text(), "REFUSED")
# ACL using TSIG: no TSIG; should be rejected
self.xfrsess._acl = isc.acl.dns.REQUEST_LOADER.load([
{"key": "example.org", "action": "ACCEPT"}, {"action": "REJECT"}
])
[rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
self.assertEqual(rcode.to_text(), "REFUSED")
#
# ACL using IP + TSIG: both should match
#
self.xfrsess._acl = isc.acl.dns.REQUEST_LOADER.load([
{"ALL": [{"key": "example.com"}, {"from": "192.0.2.1"}],
"action": "ACCEPT"},
{"action": "REJECT"}
])
# both matches
self.xfrsess._remote = ('192.0.2.1', 12345)
[rcode, msg] = self.xfrsess._parse_query_message(request_data)
self.assertEqual(rcode.to_text(), "NOERROR")
# TSIG matches, but address doesn't
self.xfrsess._remote = ('192.0.2.2', 12345)
[rcode, msg] = self.xfrsess._parse_query_message(request_data)
self.assertEqual(rcode.to_text(), "REFUSED")
# Address matches, but TSIG doesn't (not included)
self.xfrsess._remote = ('192.0.2.1', 12345)
[rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
self.assertEqual(rcode.to_text(), "REFUSED")
# Neither address nor TSIG matches
self.xfrsess._remote = ('192.0.2.2', 12345)
[rcode, msg] = self.xfrsess._parse_query_message(self.mdata)
self.assertEqual(rcode.to_text(), "REFUSED")
def test_get_query_zone_name(self):
msg = self.getmsg()
self.assertEqual(self.xfrsess._get_query_zone_name(msg), "example.com.")
......
......@@ -147,7 +147,8 @@ class XfroutSession():
if rcode == Rcode.NOERROR():
# ACL checks
acl_result = self._acl.execute(
isc.acl.dns.RequestContext(self._remote))
isc.acl.dns.RequestContext(self._remote,
msg.get_tsig_record()))
if acl_result == DROP:
logger.info(XFROUT_QUERY_DROPPED,
self._get_query_zone_name(msg),
......
......@@ -19,7 +19,7 @@ libacl_la_LIBADD += $(top_builddir)/src/lib/util/libutil.la
# DNS specialized one
lib_LTLIBRARIES += libdnsacl.la
libdnsacl_la_SOURCES = dns.h dns.cc
libdnsacl_la_SOURCES = dns.h dns.cc dnsname_check.h
libdnsacl_la_LIBADD = libacl.la
libdnsacl_la_LIBADD += $(top_builddir)/src/lib/dns/libdns++.la
......
......@@ -20,15 +20,20 @@
#include <exceptions/exceptions.h>
#include <dns/name.h>
#include <dns/tsigrecord.h>
#include <cc/data.h>
#include <acl/dns.h>
#include <acl/ip_check.h>
#include <acl/dnsname_check.h>
#include <acl/loader.h>
#include <acl/logic_check.h>
using namespace std;
using boost::shared_ptr;
using namespace isc::dns;
using namespace isc::data;
namespace isc {
......@@ -39,9 +44,6 @@ namespace acl {
/// It returns \c true if the remote (source) IP address of the request
/// matches the expression encapsulated in the \c IPCheck, and returns
/// \c false if not.
///
/// \note The match logic is expected to be extended as we add
/// more match parameters (at least there's a plan for TSIG key).
template <>
bool
IPCheck<dns::RequestContext>::matches(
......@@ -53,6 +55,18 @@ IPCheck<dns::RequestContext>::matches(
namespace dns {
/// The specialization of \c NameCheck for access control with
/// \c RequestContext.
///
/// It returns \c true if the request contains a TSIG record and its key
/// (owner) name is equal to the name stored in the check; otherwise
/// it returns \c false.
template<>
bool
NameCheck<RequestContext>::matches(const RequestContext& request) const {
return (request.tsig != NULL && request.tsig->getName() == name_);
}
vector<string>
internal::RequestCheckCreator::names() const {
// Probably we should eventually build this vector in a more
......@@ -60,6 +74,7 @@ internal::RequestCheckCreator::names() const {
// everything.
vector<string> supported_names;
supported_names.push_back("from");
supported_names.push_back("key");
return (supported_names);
}
......@@ -77,6 +92,10 @@ internal::RequestCheckCreator::create(const string& name,
if (name == "from") {
return (shared_ptr<internal::RequestIPCheck>(
new internal::RequestIPCheck(definition->stringValue())));
} else if (name == "key") {
return (shared_ptr<internal::RequestKeyCheck>(
new internal::RequestKeyCheck(
Name(definition->stringValue()))));
} else {
// This case shouldn't happen (normally) as it should have been
// rejected at the loader level. But we explicitly catch the case
......
......@@ -23,9 +23,13 @@
#include <cc/data.h>
#include <acl/ip_check.h>
#include <acl/dnsname_check.h>
#include <acl/loader.h>
namespace isc {
namespace dns {
class TSIGRecord;
}
namespace acl {
namespace dns {
......@@ -53,9 +57,9 @@ namespace dns {
* used only for a very short period as stated above.
*
* Based on the minimalist philosophy, the initial implementation only
* maintains the remote (source) IP address of the request. The plan is
* to add more parameters of the request. A scheduled next step is to
* support the TSIG key (if it's included in the request). Other possibilities
* maintains the remote (source) IP address of the request and (optionally)
* the TSIG record included in the request. We may add more parameters of
* the request as we see the need for them. Possible additional parameters
* are the local (destination) IP address, the remote and local port numbers,
* various fields of the DNS request (e.g. a particular header flag value).
*/
......@@ -68,8 +72,12 @@ struct RequestContext {
/// \exception None
///
/// \parameter remote_address_param The remote IP address
explicit RequestContext(const IPAddress& remote_address_param) :
remote_address(remote_address_param)
/// \parameter tsig_param A valid pointer to the TSIG record included in
/// the request or NULL if the request doesn't contain a TSIG.
RequestContext(const IPAddress& remote_address_param,
const isc::dns::TSIGRecord* tsig_param) :
remote_address(remote_address_param),
tsig(tsig_param)
{}
///
......@@ -83,6 +91,11 @@ struct RequestContext {
//@{
/// \brief The remote IP address (eg. the client's IP address).
const IPAddress& remote_address;
/// \brief The TSIG record included in the request message, if any.
///
/// If the request doesn't include a TSIG, this member will be NULL.
const isc::dns::TSIGRecord* const tsig;
//@}
};
......@@ -114,6 +127,7 @@ namespace internal {
// Shortcut typedef
typedef isc::acl::IPCheck<RequestContext> RequestIPCheck;
typedef isc::acl::dns::NameCheck<RequestContext> RequestKeyCheck;
class RequestCheckCreator : public acl::Loader<RequestContext>::CheckCreator {
public:
......
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __DNSNAME_CHECK_H
#define __DNSNAME_CHECK_H 1
#include <dns/name.h>
#include <acl/check.h>
namespace isc {
namespace acl {
namespace dns {
/// ACL check for DNS names
///
/// This class is intended to perform a match between a domain name
/// specified in an ACL and a given name. The primary usage of this class
/// is an ACL match for TSIG keys, where an ACL would contain a list of
/// acceptable key names and the \c match() method would compare the owner
/// name of a TSIG record against the specified names.
///
/// This class could be used for other kinds of names such as the query name
/// of normal DNS queries.
///
/// The class is templated on the type of a context structure passed to the
/// matches() method, and a template specialisation for that method must be
/// supplied for the class to be used.
template <typename Context>
class NameCheck : public Check<Context> {
public:
/// The constructor
///
/// \exception std::bad_alloc Resource allocation fails in copying the
/// name
///
/// \param name The domain name to be matched in \c matches().
NameCheck(const isc::dns::Name& name) : name_(name) {}
/// Destructor
virtual ~NameCheck() {}
/// The check method
///
/// Matches the passed argument to the condition stored here. Different
/// specializations must be provided for different argument types, and the
/// program will fail to compile if a required specialisation is not
/// provided.
///
/// \param context Information to be matched
virtual bool matches(const Context& context) const;
/// Returns the name specified on construction.
///
/// This is mainly for testing purposes.
///
/// \exception None
const isc::dns::Name& getName() const { return (name_); }
private:
const isc::dns::Name name_;
};
} // namespace dns
} // namespace acl
} // namespace isc
#endif // __DNSNAME_CHECK_H
// Local Variables:
// mode: c++
// End:
......@@ -16,6 +16,7 @@ run_unittests_SOURCES += acl_test.cc
run_unittests_SOURCES += check_test.cc
run_unittests_SOURCES += dns_test.cc
run_unittests_SOURCES += ip_check_unittest.cc
run_unittests_SOURCES += dnsname_check_unittest.cc
run_unittests_SOURCES += loader_test.cc
run_unittests_SOURCES += logcheck.h
run_unittests_SOURCES += creators.h
......
......@@ -23,6 +23,11 @@
#include <exceptions/exceptions.h>
#include <dns/name.h>
#include <dns/tsigkey.h>
#include <dns/tsigrecord.h>
#include <dns/rdataclass.h>
#include <cc/data.h>
#include <acl/dns.h>
#include <acl/loader.h>
......@@ -35,6 +40,8 @@
using namespace std;
using boost::scoped_ptr;
using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace isc::data;
using namespace isc::acl;
using namespace isc::acl::dns;
......@@ -64,8 +71,10 @@ protected:
};
TEST_F(RequestCheckCreatorTest, names) {
ASSERT_EQ(1, creator_.names().size());
EXPECT_EQ("from", creator_.names()[0]);
const vector<string> names = creator_.names();
EXPECT_EQ(2, names.size());
EXPECT_TRUE(find(names.begin(), names.end(), "from") != names.end());
EXPECT_TRUE(find(names.begin(), names.end(), "key") != names.end());
}
TEST_F(RequestCheckCreatorTest, allowListAbbreviation) {
......@@ -93,11 +102,11 @@ TEST_F(RequestCheckCreatorTest, createIPv6Check) {
check_ = creator_.create("from",
Element::fromJSON("\"2001:db8::5300/120\""),
getRequestLoader());
const dns::internal::RequestIPCheck& ipcheck_ =
const dns::internal::RequestIPCheck& ipcheck =
dynamic_cast<const dns::internal::RequestIPCheck&>(*check_);
EXPECT_EQ(AF_INET6, ipcheck_.getFamily());
EXPECT_EQ(120, ipcheck_.getPrefixlen());
const vector<uint8_t> check_address(ipcheck_.getAddress());
EXPECT_EQ(AF_INET6, ipcheck.getFamily());
EXPECT_EQ(120, ipcheck.getPrefixlen());
const vector<uint8_t> check_address(ipcheck.getAddress());
ASSERT_EQ(16, check_address.size());
const uint8_t expected_address[] = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
......@@ -106,6 +115,14 @@ TEST_F(RequestCheckCreatorTest, createIPv6Check) {
expected_address));
}
TEST_F(RequestCheckCreatorTest, createTSIGKeyCheck) {
check_ = creator_.create("key", Element::fromJSON("\"key.example.com\""),
getRequestLoader());
const dns::internal::RequestKeyCheck& keycheck =
dynamic_cast<const dns::internal::RequestKeyCheck&>(*check_);
EXPECT_EQ(Name("key.example.com"), keycheck.getName());
}
TEST_F(RequestCheckCreatorTest, badCreate) {
// Invalid name
EXPECT_THROW(creator_.create("bad", Element::fromJSON("\"192.0.2.1\""),
......@@ -118,12 +135,23 @@ TEST_F(RequestCheckCreatorTest, badCreate) {
EXPECT_THROW(creator_.create("from", Element::fromJSON("[]"),
getRequestLoader()),
isc::data::TypeError);
EXPECT_THROW(creator_.create("key", Element::fromJSON("1"),
getRequestLoader()),
isc::data::TypeError);
EXPECT_THROW(creator_.create("key", Element::fromJSON("{}"),
getRequestLoader()),
isc::data::TypeError);
// Syntax error for IPCheck
EXPECT_THROW(creator_.create("from", Element::fromJSON("\"bad\""),
getRequestLoader()),
isc::InvalidParameter);
// Syntax error for Name (key) Check
EXPECT_THROW(creator_.create("key", Element::fromJSON("\"bad..name\""),
getRequestLoader()),
EmptyLabel);
// NULL pointer
EXPECT_THROW(creator_.create("from", ConstElementPtr(), getRequestLoader()),
LoaderError);
......@@ -140,23 +168,43 @@ protected:
getRequestLoader()));
}
// A helper shortcut to create a single Name (key) check for the given
// name.
ConstRequestCheckPtr createKeyCheck(const string& key_name) {
return (creator_.create("key", Element::fromJSON(
string("\"") + key_name + string("\"")),
getRequestLoader()));
}
// create a one time request context for a specific test. Note that
// getSockaddr() uses a static storage, so it cannot be called more than
// once in a single test.
const dns::RequestContext& getRequest4() {
const dns::RequestContext& getRequest4(const TSIGRecord* tsig = NULL) {
ipaddr.reset(new IPAddress(tests::getSockAddr("192.0.2.1")));
request.reset(new dns::RequestContext(*ipaddr));
request.reset(new dns::RequestContext(*ipaddr, tsig));
return (*request);
}
const dns::RequestContext& getRequest6() {
const dns::RequestContext& getRequest6(const TSIGRecord* tsig = NULL) {
ipaddr.reset(new IPAddress(tests::getSockAddr("2001:db8::1")));
request.reset(new dns::RequestContext(*ipaddr));
request.reset(new dns::RequestContext(*ipaddr, tsig));
return (*request);
}
// create a one time TSIG Record for a specific test. The only parameter
// of the record that matters is the key name; others are hardcoded with
// arbitrarily chosen values.
const TSIGRecord* getTSIGRecord(const string& key_name) {
tsig_rdata.reset(new any::TSIG(TSIGKey::HMACMD5_NAME(), 0, 0, 0, NULL,
0, 0, 0, NULL));
tsig.reset(new TSIGRecord(Name(key_name), *tsig_rdata));
return (tsig.get());
}
private:
scoped_ptr<IPAddress> ipaddr;
scoped_ptr<dns::RequestContext> request;
scoped_ptr<any::TSIG> tsig_rdata;
scoped_ptr<TSIGRecord> tsig;
dns::internal::RequestCheckCreator creator_;
};
......@@ -184,6 +232,24 @@ TEST_F(RequestCheckTest, checkIPv6) {
EXPECT_FALSE(createIPCheck("32.1.13.184")->matches(getRequest6()));
}
TEST_F(RequestCheckTest, checkTSIGKey) {
EXPECT_TRUE(createKeyCheck("key.example.com")->matches(
getRequest4(getTSIGRecord("key.example.com"))));
EXPECT_FALSE(createKeyCheck("key.example.com")->matches(
getRequest4(getTSIGRecord("badkey.example.com"))));
// Same for IPv6 (which shouldn't matter)
EXPECT_TRUE(createKeyCheck("key.example.com")->matches(
getRequest6(getTSIGRecord("key.example.com"))));
EXPECT_FALSE(createKeyCheck("key.example.com")->matches(
getRequest6(getTSIGRecord("badkey.example.com"))));
// by default the test request doesn't have a TSIG key, which shouldn't
// match any key checks.
EXPECT_FALSE(createKeyCheck("key.example.com")->matches(getRequest4()));
EXPECT_FALSE(createKeyCheck("key.example.com")->matches(getRequest6()));
}
// The following tests test only the creators are registered, they are tested
// elsewhere
......
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <gtest/gtest.h>
#include <dns/name.h>
#include <acl/dnsname_check.h>
using namespace isc::dns;
using namespace isc::acl::dns;
// Provide a specialization of the DNSNameCheck::matches() method.
namespace isc {
namespace acl {
namespace dns {
template <>
bool NameCheck<Name>::matches(const Name& name) const {
return (name_ == name);
}
} // namespace dns
} // namespace acl
} // namespace isc
namespace {
TEST(DNSNameCheck, construct) {
EXPECT_EQ(Name("example.com"),
NameCheck<Name>(Name("example.com")).getName());
// Construct the same check with an explicit trailing dot. Should result
// in the same result.
EXPECT_EQ(Name("example.com"),
NameCheck<Name>(Name("example.com.")).getName());
}
TEST(DNSNameCheck, match) {
NameCheck<Name> check(Name("example.com"));
EXPECT_TRUE(check.matches(Name("example.com")));
EXPECT_FALSE(check.matches(Name("example.org")));
// comparison is case insensitive
EXPECT_TRUE(check.matches(Name("EXAMPLE.COM")));
// this is exact match. so super/sub domains don't match
EXPECT_FALSE(check.matches(Name("com")));
EXPECT_FALSE(check.matches(Name("www.example.com")));
}
} // Unnamed namespace
......@@ -4,10 +4,10 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(B10_CXXFLAGS)
python_PYTHON = __init__.py
python_PYTHON = __init__.py dns.py
pythondir = $(PYTHON_SITEPKG_DIR)/isc/acl
pyexec_LTLIBRARIES = acl.la dns.la
pyexec_LTLIBRARIES = acl.la _dns.la
pyexecdir = $(PYTHON_SITEPKG_DIR)/isc/acl
acl_la_SOURCES = acl.cc
......@@ -15,14 +15,14 @@ acl_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
acl_la_LDFLAGS = $(PYTHON_LDFLAGS)
acl_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
dns_la_SOURCES = dns.h dns.cc dns_requestacl_python.h dns_requestacl_python.cc
dns_la_SOURCES += dns_requestcontext_python.h dns_requestcontext_python.cc
dns_la_SOURCES += dns_requestloader_python.h dns_requestloader_python.cc
dns_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
dns_la_LDFLAGS = $(PYTHON_LDFLAGS)
_dns_la_SOURCES = dns.h dns.cc dns_requestacl_python.h dns_requestacl_python.cc
_dns_la_SOURCES += dns_requestcontext_python.h dns_requestcontext_python.cc
_dns_la_SOURCES += dns_requestloader_python.h dns_requestloader_python.cc
_dns_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
_dns_la_LDFLAGS = $(PYTHON_LDFLAGS)
# Note: PYTHON_CXXFLAGS may have some -Wno... workaround, which must be
# placed after -Wextra defined in AM_CXXFLAGS
dns_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
_dns_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
# Python prefers .so, while some OSes (specifically MacOS) use a different
# suffix for dynamic objects. -module is necessary to work this around.
......@@ -30,11 +30,11 @@ acl_la_LDFLAGS += -module
acl_la_LIBADD = $(top_builddir)/src/lib/acl/libacl.la
acl_la_LIBADD += $(PYTHON_LIB)
dns_la_LDFLAGS += -module
dns_la_LIBADD = $(top_builddir)/src/lib/acl/libdnsacl.la
dns_la_LIBADD += $(PYTHON_LIB)