Commit 7203d420 authored by Michal 'vorner' Vaner's avatar Michal 'vorner' Vaner
Browse files

Merge branch 'work/not'

Conflicts:
	src/lib/acl/dns.cc
parents 78763269 b250ca76
......@@ -25,6 +25,7 @@
#include <acl/dns.h>
#include <acl/ip_check.h>
#include <acl/loader.h>
#include <acl/logic_check.h>
using namespace std;
using boost::shared_ptr;
......@@ -98,6 +99,15 @@ getRequestLoader() {
// Register default check creator(s)
loader_ptr->registerCreator(shared_ptr<internal::RequestCheckCreator>(
new internal::RequestCheckCreator()));
loader_ptr->registerCreator(
shared_ptr<NotCreator<RequestContext> >(
new NotCreator<RequestContext>("NOT")));
loader_ptr->registerCreator(
shared_ptr<LogicCreator<AnyOfSpec, RequestContext> >(
new LogicCreator<AnyOfSpec, RequestContext>("ANY")));
loader_ptr->registerCreator(
shared_ptr<LogicCreator<AllOfSpec, RequestContext> >(
new LogicCreator<AllOfSpec, RequestContext>("ALL")));
// From this point there shouldn't be any exception thrown
loader = loader_ptr.release();
......
......@@ -200,6 +200,86 @@ private:
const std::string name_;
};
/**
* \brief The NOT operator for ACLs.
*
* This simply returns the negation of whatever returns the subexpression.
*/
template<typename Context>
class NotOperator : public CompoundCheck<Context> {
public:
/**
* \brief Constructor
*
* \param expr The subexpression to be negated by this NOT.
*/
NotOperator(const boost::shared_ptr<Check<Context> >& expr) :
expr_(expr)
{ }
/**
* \brief The list of subexpressions
*
* \return The vector will contain single value and it is the expression
* passed by constructor.
*/
virtual typename CompoundCheck<Context>::Checks getSubexpressions() const {
typename CompoundCheck<Context>::Checks result;
result.push_back(expr_.get());
return (result);
}
/// \brief The matching function
virtual bool matches(const Context& context) const {
return (!expr_->matches(context));
}
private:
/// \brief The subexpression
const boost::shared_ptr<Check<Context> > expr_;
};
template<typename Context, typename Action = BasicAction>
class NotCreator : public Loader<Context, Action>::CheckCreator {
public:
/**
* \brief Constructor
*
* \param name The name of the NOT operator to be loaded as.
*/
NotCreator(const std::string& name) :
name_(name)
{ }
/**
* \brief List of the names this loads
*
* \return Single-value vector containing the name passed to the
* constructor.
*/
virtual std::vector<std::string> names() const {
std::vector<std::string> result;
result.push_back(name_);
return (result);
}
/// \brief Create the check.
virtual boost::shared_ptr<Check<Context> > create(const std::string&,
data::ConstElementPtr
definition,
const Loader<Context,
Action>& loader)
{
return (boost::shared_ptr<Check<Context> >(new NotOperator<Context>(
loader.loadCheck(definition))));
}
/**
* \brief Or-abbreviated form.
*
* This returns false. In theory, the NOT operator could be used with
* the abbreviated form, but it would be confusing. Such syntax is
* therefore explicitly forbidden.
*/
virtual bool allowListAbbreviation() const { return (false); }
public:
const std::string name_;
};
}
}
......
......@@ -184,4 +184,22 @@ TEST_F(RequestCheckTest, checkIPv6) {
EXPECT_FALSE(createIPCheck("32.1.13.184")->matches(getRequest6()));
}
// The following tests test only the creators are registered, they are tested
// elsewhere
TEST(DNSACL, notLoad) {
EXPECT_NO_THROW(getRequestLoader().loadCheck(isc::data::Element::fromJSON(
"{\"NOT\": {\"from\": \"192.0.2.1\"}}")));
}
TEST(DNSACL, allLoad) {
EXPECT_NO_THROW(getRequestLoader().loadCheck(isc::data::Element::fromJSON(
"{\"ALL\": [{\"from\": \"192.0.2.1\"}]}")));
}
TEST(DNSACL, anyLoad) {
EXPECT_NO_THROW(getRequestLoader().loadCheck(isc::data::Element::fromJSON(
"{\"ANY\": [{\"from\": \"192.0.2.1\"}]}")));
}
}
......@@ -93,6 +93,7 @@ public:
LogicCreator<AllOfSpec, Log>("ALL")));
loader_.registerCreator(CreatorPtr(new ThrowCreator));
loader_.registerCreator(CreatorPtr(new LogCreator));
loader_.registerCreator(CreatorPtr(new NotCreator<Log>("NOT")));
}
// To mark which parts of the check did run
Log log_;
......@@ -242,4 +243,49 @@ TEST_F(LogicCreatorTest, nested) {
log_.checkFirst(2);
}
void notTest(bool value) {
NotOperator<Log> notOp(shared_ptr<Check<Log> >(new ConstCheck(value, 0)));
Log log;
// It returns negated value
EXPECT_EQ(!value, notOp.matches(log));
// And runs the only one thing there
log.checkFirst(1);
// Check the getSubexpressions does sane things
ASSERT_EQ(1, notOp.getSubexpressions().size());
EXPECT_EQ(value, notOp.getSubexpressions()[0]->matches(log));
}
TEST(Not, trueValue) {
notTest(true);
}
TEST(Not, falseValue) {
notTest(false);
}
TEST_F(LogicCreatorTest, notInvalid) {
EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"NOT\": null}")),
LoaderError);
EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"NOT\": \"hello\"}")),
LoaderError);
EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"NOT\": true}")),
LoaderError);
EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"NOT\": 42}")),
LoaderError);
EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"NOT\": []}")),
LoaderError);
EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"NOT\": [{"
"\"logcheck\": [0, true]"
"}]}")),
LoaderError);
}
TEST_F(LogicCreatorTest, notValid) {
shared_ptr<NotOperator<Log> > notOp(load<NotOperator<Log> >("{\"NOT\":"
" {\"logcheck\":"
" [0, true]}}"));
EXPECT_FALSE(notOp->matches(log_));
log_.checkFirst(1);
}
}
......@@ -41,6 +41,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/acl/libacl.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment