[cpp-sp] branch main updated: Merge time-based AC rules back into main class.
Scott Cantor
cantor.2 at osu.edu
Wed Oct 29 13:07:55 UTC 2025
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository cpp-sp.
View the commit online:
https://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=f160d1c6c12dfc0564bc267d1384f0a2b99d7717
The following commit(s) were added to refs/heads/main by this push:
new f160d1c6 Merge time-based AC rules back into main class.
f160d1c6 is described below
commit f160d1c6c12dfc0564bc267d1384f0a2b99d7717
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Oct 29 09:07:46 2025 -0400
Merge time-based AC rules back into main class.
---
Projects/vc22/Tests.vcxproj | 3 +-
Projects/vc22/shibsp.vcxproj | 4 +-
Projects/vc22/shibsp.vcxproj.filters | 8 +-
shibsp/AccessControl.h | 8 +-
shibsp/Makefile.am | 2 -
shibsp/impl/ChainingAccessControl.cpp | 165 -----------
shibsp/impl/TimeAccessControl.cpp | 302 ---------------------
shibsp/impl/XMLAccessControl.cpp | 233 +++++++++++++++-
tests/Makefile.am | 1 -
tests/data/impl/acl/inline-new-time-invalid.xml | 5 +
tests/data/impl/acl/inline-new-time-valid.xml | 6 +
tests/data/impl/acl/inline-old-time-invalid.xml | 6 +
tests/data/impl/acl/inline-old-time-valid.xml | 6 +
tests/data/impl/acl/inline-timesinceauth.xml | 5 +
tests/data/impl/acl/inline-year-invalid.xml | 6 +
tests/data/impl/acl/inline-year-valid.xml | 6 +
tests/data/impl/acl/time/acl-badxml.xml | 1 -
tests/data/impl/acl/time/external-acl-badxml.xml | 1 -
.../data/impl/acl/time/inline-new-time-invalid.xml | 4 -
tests/data/impl/acl/time/inline-new-time-valid.xml | 4 -
.../data/impl/acl/time/inline-old-time-invalid.xml | 4 -
tests/data/impl/acl/time/inline-old-time-valid.xml | 4 -
tests/data/impl/acl/time/inline-timesinceauth.xml | 3 -
tests/data/impl/acl/time/inline-year-invalid.xml | 4 -
tests/data/impl/acl/time/inline-year-valid.xml | 4 -
tests/data/impl/acl/time/internal-acl-invalid2.xml | 3 -
tests/impl/TimeAccessControlTests.cpp | 299 --------------------
tests/impl/XMLAccessControlTests.cpp | 145 ++++++++++
28 files changed, 415 insertions(+), 827 deletions(-)
diff --git a/Projects/vc22/Tests.vcxproj b/Projects/vc22/Tests.vcxproj
index 3be297b2..ef11b149 100644
--- a/Projects/vc22/Tests.vcxproj
+++ b/Projects/vc22/Tests.vcxproj
@@ -30,7 +30,6 @@
<ClCompile Include="..\..\tests\AgentConfigTests.cpp" />
<ClCompile Include="..\..\tests\AgentTestSuite.cpp" />
<ClCompile Include="..\..\tests\attribute\impl\DefaultAttributeConfigurationTests.cpp" />
- <ClCompile Include="..\..\tests\impl\TimeAccessControlTests.cpp" />
<ClCompile Include="..\..\tests\impl\XMLAccessControlTests.cpp" />
<ClCompile Include="..\..\tests\impl\XMLRequestMapperTests.cpp" />
<ClCompile Include="..\..\tests\remoting\impl\SecretSourceTests.cpp">
@@ -341,4 +340,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/Projects/vc22/shibsp.vcxproj b/Projects/vc22/shibsp.vcxproj
index 35889131..0ab66ff9 100644
--- a/Projects/vc22/shibsp.vcxproj
+++ b/Projects/vc22/shibsp.vcxproj
@@ -111,9 +111,7 @@
</ClCompile>
<ClCompile Include="..\..\shibsp\handler\impl\TokenConsumer.cpp" />
<ClCompile Include="..\..\shibsp\impl\AgentConfig.cpp" />
- <ClCompile Include="..\..\shibsp\impl\ChainingAccessControl.cpp" />
<ClCompile Include="..\..\shibsp\impl\DefaultAgent.cpp" />
- <ClCompile Include="..\..\shibsp\impl\TimeAccessControl.cpp" />
<ClCompile Include="..\..\shibsp\impl\XMLAccessControl.cpp" />
<ClCompile Include="..\..\shibsp\impl\XMLRequestMapper.cpp" />
<ClCompile Include="..\..\shibsp\io\impl\CookieManager.cpp" />
@@ -397,4 +395,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/Projects/vc22/shibsp.vcxproj.filters b/Projects/vc22/shibsp.vcxproj.filters
index 00cb30ea..2e50d4ef 100644
--- a/Projects/vc22/shibsp.vcxproj.filters
+++ b/Projects/vc22/shibsp.vcxproj.filters
@@ -263,9 +263,6 @@
<ClCompile Include="..\..\shibsp\impl\AgentConfig.cpp">
<Filter>Source Files\Impl</Filter>
</ClCompile>
- <ClCompile Include="..\..\shibsp\impl\ChainingAccessControl.cpp">
- <Filter>Source Files\Impl</Filter>
- </ClCompile>
<ClCompile Include="..\..\shibsp\impl\XMLAccessControl.cpp">
<Filter>Source Files\Impl</Filter>
</ClCompile>
@@ -389,13 +386,10 @@
<ClCompile Include="..\..\shibsp\csprng\impl\csprng.cpp">
<Filter>Source Files\Impl</Filter>
</ClCompile>
- <ClCompile Include="..\..\shibsp\impl\TimeAccessControl.cpp">
- <Filter>Source Files\Impl</Filter>
- </ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\shibsp\shibsp.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/shibsp/AccessControl.h b/shibsp/AccessControl.h
index e5f675ed..42b6405b 100644
--- a/shibsp/AccessControl.h
+++ b/shibsp/AccessControl.h
@@ -68,15 +68,9 @@ namespace shibsp {
*/
void SHIBSP_API registerAccessControls();
- /** Chains together multiple plugins. */
- #define CHAINING_ACCESS_CONTROL "Chaining"
-
- /** AccessControl based on rudimentary XML syntax. */
+ /** AccessControl based on XML syntax. */
#define XML_ACCESS_CONTROL "XML"
- /** AccessControl with time-based rules. */
- #define TIME_ACCESS_CONTROL "Time"
-
/** Reserved for Apache-style .htaccess support. */
#define HT_ACCESS_CONTROL "htaccess"
};
diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index ab79e9e6..4ac1855e 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -114,8 +114,6 @@ libshibsp_la_SOURCES = \
handler/impl/TokenConsumer.cpp \
impl/AgentConfig.cpp \
impl/DefaultAgent.cpp \
- impl/ChainingAccessControl.cpp \
- impl/TimeAccessControl.cpp \
impl/XMLAccessControl.cpp \
impl/XMLRequestMapper.cpp \
io/impl/CookieManager.cpp \
diff --git a/shibsp/impl/ChainingAccessControl.cpp b/shibsp/impl/ChainingAccessControl.cpp
deleted file mode 100644
index a1919914..00000000
--- a/shibsp/impl/ChainingAccessControl.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * impl/ChainingAccessControl.cpp
- *
- * Access control plugin that combines other plugins.
- */
-
-#include "internal.h"
-#include "exceptions.h"
-
-#include "AccessControl.h"
-#include "AgentConfig.h"
-#include "SPRequest.h"
-#include "logging/Category.h"
-
-#include <algorithm>
-#include <memory>
-#include <vector>
-#include <boost/property_tree/ptree.hpp>
-
-using namespace shibsp;
-using namespace boost::property_tree;
-using namespace std;
-
-namespace shibsp {
- extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(ptree& pt, bool deprecationSupport);
- extern AccessControl* SHIBSP_DLLLOCAL TimeAccessControlFactory(ptree& pt, bool deprecationSupport);
-}
-
-AccessControl::AccessControl()
-{
-}
-
-AccessControl::~AccessControl()
-{
-}
-
-
-namespace {
-
- class ChainingAccessControl : public AccessControl
- {
- public:
- ChainingAccessControl(ptree& pt, bool deprecationSupport);
-
- ~ChainingAccessControl() {}
-
- void lock_shared() {
- for (auto& i : m_ac) {
- i->lock_shared();
- }
- }
- bool try_lock_shared() {
- // This shouldn't be needed, so just fail it.
- return false;
- }
- void unlock_shared() {
- for (auto& i : m_ac) {
- i->unlock_shared();
- }
- }
-
- aclresult_t authorized(const SPRequest& request, const Session* session) const;
-
- private:
- enum operator_t { OP_AND, OP_OR } m_op;
- vector<unique_ptr<AccessControl>> m_ac;
- };
-
- AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(ptree& pt, bool deprecationSupport)
- {
- return new ChainingAccessControl(pt, deprecationSupport);
- }
-}
-
-void SHIBSP_API shibsp::registerAccessControls()
-{
- AgentConfig& conf=AgentConfig::getConfig();
- conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);
- conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);
- conf.AccessControlManager.registerFactory(TIME_ACCESS_CONTROL, TimeAccessControlFactory);
-}
-
-ChainingAccessControl::ChainingAccessControl(ptree& pt, bool deprecationSupport) : m_op(OP_AND)
-{
- static const char OPERATOR_PROP_PATH[] = "<xmlattr>.operator";
- static const char AND_OPERATOR[] = "AND";
- static const char OR_OPERATOR[] = "OR";
- const boost::optional<string> op = pt.get_optional<string>(OPERATOR_PROP_PATH);
- if (!op) {
- throw ConfigurationException("Missing operator in Chaining AccessControl configuration.");
- }
- else if (op.get() == OR_OPERATOR) {
- m_op = OP_OR;
- } else if (op.get() == AND_OPERATOR) {
- m_op = OP_AND;
- } else {
- throw ConfigurationException("Unsupported operator in Chaining AccessControl configuration.");
- }
-
- Category& log = Category::getInstance(SHIBSP_LOGCAT ".AccessControl.Chaining");
-
- static const char ACCESS_CONTROL_PROP_PATH[] = "AccessControl";
- for (const auto& child : pt) {
- if (child.first != ACCESS_CONTROL_PROP_PATH) {
- continue;
- }
-
- static const char TYPE_PROP_PATH[] = "<xmlattr>.type";
- const boost::optional<string> type = child.second.get_optional<string>(TYPE_PROP_PATH);
- if (!type) {
- throw ConfigurationException("Missing type in AccessControl configuration.");
- }
-
- log.info("building AccessControl provider of type (%s)...", type.get().c_str());
- m_ac.push_back(unique_ptr<AccessControl>(
- AgentConfig::getConfig().AccessControlManager.newPlugin(type.get(), pt, deprecationSupport)
- ));
- }
-
- if (m_ac.empty()) {
- throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");
- }
-}
-
-AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const
-{
- switch (m_op) {
- case OP_AND:
- {
- for (const auto& i : m_ac) {
- if (i->authorized(request, session) != shib_acl_true) {
- request.log(Priority::SHIB_DEBUG, "embedded AccessControl plugin unsuccessful, denying access");
- return shib_acl_false;
- }
- }
- return shib_acl_true;
- }
-
- case OP_OR:
- {
- for (const auto& i : m_ac) {
- if (i->authorized(request, session) == shib_acl_true)
- return shib_acl_true;
- }
- request.log(Priority::SHIB_DEBUG, "all embedded AccessControl plugins unsuccessful, denying access");
- return shib_acl_false;
- }
- }
- request.log(Priority::SHIB_DEBUG, "unknown operation in access control policy, denying access");
- return shib_acl_false;
-}
diff --git a/shibsp/impl/TimeAccessControl.cpp b/shibsp/impl/TimeAccessControl.cpp
deleted file mode 100644
index fc34e584..00000000
--- a/shibsp/impl/TimeAccessControl.cpp
+++ /dev/null
@@ -1,302 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * TimeAccessControl.cpp
- *
- * Access control plugin for time-based policies.
- */
-
-#include "internal.h"
-#include "exceptions.h"
-
-#include "AccessControl.h"
-#include "Agent.h"
-#include "SPRequest.h"
-#include "attribute/AttributeConfiguration.h"
-#include "logging/Category.h"
-#include "remoting/ddf.h"
-#include "session/SessionCache.h"
-#include "util/Lockable.h"
-#include "util/Misc.h"
-#include "util/ReloadableXMLFile.h"
-
-#include <algorithm>
-#include <memory>
-#include <set>
-
-#include <boost/algorithm/string.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/property_tree/ptree.hpp>
-
-#ifndef HAVE_STRCASECMP
-# define strcasecmp _stricmp
-#endif
-
-using namespace shibsp;
-using namespace boost::property_tree;
-using namespace std;
-
-namespace {
-
- class Rule : public AccessControl, public NoOpSharedLockable
- {
- public:
- Rule(const string& name, const ptree& pt);
- ~Rule() {}
-
- aclresult_t authorized(const SPRequest& request, const Session* session) const;
-
- private:
- enum { TM_AUTHN, TM_TIME, TM_YEAR, TM_MONTH, TM_DAY, TM_HOUR, TM_MINUTE, TM_SECOND, TM_WDAY } m_type;
- enum { OP_LT, OP_LE, OP_EQ, OP_GE, OP_GT } m_op;
- time_t m_value;
- };
-
- class TimeAccessControl : public AccessControl, public NoOpSharedLockable
- {
- public:
- TimeAccessControl(const ptree& pt);
- ~TimeAccessControl() {}
-
- aclresult_t authorized(const SPRequest& request, const Session* session) const;
-
- private:
- enum { OP_AND, OP_OR } m_op;
- vector<unique_ptr<Rule>> m_rules;
- };
-}
-
-namespace shibsp {
- AccessControl* SHIBSP_DLLLOCAL TimeAccessControlFactory(ptree& pt, bool deprecationSupport)
- {
- return new TimeAccessControl(pt);
- }
-};
-
-Rule::Rule(const string& name, const ptree& pt)
-{
- static const char Day[] = "Day";
- static const char DayOfWeek[] = "DayOfWeek";
- static const char Hour[] = "Hour";
- static const char Minute[] = "Minute";
- static const char Month[] = "Month";
- static const char Second[] = "Second";
- static const char Time[] = "Time";
- static const char TimeSinceAuthn[] = "TimeSinceAuthn";
- static const char Year[] = "Year";
-
- // The TimeSinceAuthn rule operates on a Duration inside the element body,
- // which should be the value of the tree.
-
- if (name == TimeSinceAuthn) {
- m_type = TM_AUTHN;
- if ((m_value = parseISODuration(pt.get_value(""))) < 0) {
- throw ConfigurationException("Unable to parse duration in TimeSinceAuthn rule.");
- }
- return;
- }
-
- // Anything else we have to parse the element body.
- string s = pt.get_value("");
- boost::trim(s);
- vector<string> tokens;
- if (boost::split(tokens, s, boost::is_space(), boost::algorithm::token_compress_on).size() != 2) {
- throw ConfigurationException("Time-based rule requires element content of the form \"LT|LE|EQ|GE|GT value\".");
- }
- string& op = tokens.front();
- if (op == "LT") { m_op = OP_LT; }
- else if (op == "LE") { m_op = OP_LE; }
- else if (op == "EQ") { m_op = OP_EQ; }
- else if (op == "GE") { m_op = OP_GE; }
- else if (op == "GT") { m_op = OP_GT; }
- else {
- throw ConfigurationException("First component of time-based rule must be one of LT, LE, EQ, GE, GT.");
- }
-
- if (name == Time) {
- m_type = TM_TIME;
- if ((m_value = parseISODateTime(tokens.back())) < 0) {
- throw ConfigurationException("Error parsing timestamp in Time rule.");
- }
- return;
- }
-
- m_value = boost::lexical_cast<time_t>(tokens.back());
- if (name == Year) { m_type = TM_YEAR; }
- else if (name == Month) { m_type = TM_MONTH; }
- else if (name == Day) { m_type = TM_DAY; }
- else if (name == Hour) { m_type = TM_HOUR; }
- else if (name == Minute) { m_type = TM_MINUTE; }
- else if (name == Second) { m_type = TM_SECOND; }
- else if (name == DayOfWeek) { m_type = TM_WDAY; }
- else {
- throw ConfigurationException("Unrecognized time-based rule.");
- }
-}
-
-AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const
-{
- time_t operand = 0;
-
- if (m_type == TM_AUTHN) {
- if (session) {
- // Locate the Attribute to be used for accessing the auth timestamp.
- const AttributeConfiguration& config = request.getAgent().getAttributeConfiguration(
- request.getRequestSettings().first->getString(RequestMapper::ATTRIBUTE_CONFIG_ID_PROP_NAME));
- const auto attr = session->getAttributes().find(
- config.getString(AttributeConfiguration::LEGACY_AUTHTIME_ATTRIBUTE_PROP_NAME,
- AttributeConfiguration::LEGACY_AUTHTIME_ATTRIBUTE_PROP_DEFAULT));
- if (attr == session->getAttributes().end()) {
- request.debug("Attribute carrying authentication time unnvailable");
- return shib_acl_false;
- }
-
- DDF val = const_cast<DDF&>(attr->second).first();
- if (val.isstring()) {
- const char* authtime = const_cast<DDF&>(attr->second).first().string();
- if (authtime) {
- if (operand = parseISODateTime(authtime) < 0) {
- request.error("Error parsing authentication time from designated Attribute.");
- return shib_acl_false;
- }
- }
- }
- else if (val.islong()) {
- operand = val.longinteger();
- }
- if (operand > 0) {
- if (time(nullptr) - operand <= m_value) {
- return shib_acl_true;
- }
-
- request.debug("elapsed time since authentication exceeds limit");
- return shib_acl_false;
- }
- else {
- request.debug("Attribute carrying authentication time unnvailable");
- return shib_acl_false;
- }
- }
- else {
- request.debug("session unnvailable");
- return shib_acl_false;
- }
- }
-
- // Extract value from tm struct or time directly.
- operand = time(nullptr);
- if (m_type != TM_TIME) {
-#ifndef HAVE_LOCALTIME_R
- struct tm* ptime = localtime(&operand);
-#else
- struct tm res;
- struct tm* ptime = localtime_r(&operand, &res);
-#endif
- switch (m_type) {
- case TM_YEAR:
- operand = ptime->tm_year + 1900;
- break;
- case TM_MONTH:
- operand = ptime->tm_mon + 1;
- break;
- case TM_DAY:
- operand = ptime->tm_mday;
- break;
- case TM_HOUR:
- operand = ptime->tm_hour;
- break;
- case TM_MINUTE:
- operand = ptime->tm_min;
- break;
- case TM_SECOND:
- operand = ptime->tm_sec;
- break;
- case TM_WDAY:
- operand = ptime->tm_wday;
- break;
- }
- }
-
- // Compare operand to test value in rule using rule operator.
- switch (m_op) {
- case OP_LT:
- return (operand < m_value) ? shib_acl_true : shib_acl_false;
- case OP_LE:
- return (operand <= m_value) ? shib_acl_true : shib_acl_false;
- case OP_EQ:
- return (operand == m_value) ? shib_acl_true : shib_acl_false;
- case OP_GE:
- return (operand >= m_value) ? shib_acl_true : shib_acl_false;
- case OP_GT:
- return (operand > m_value) ? shib_acl_true : shib_acl_false;
- }
- return shib_acl_false;
-}
-
-TimeAccessControl::TimeAccessControl(const ptree& pt) : m_op(OP_AND)
-{
- static const char OPERATOR_PROP_PATH[] = "<xmlattr>.operator";
- static const char OR_OPERATOR_VALUE[] = "OR";
- static const char AND_OPERATOR_VALUE[] = "AND";
-
- string op = pt.get(OPERATOR_PROP_PATH, AND_OPERATOR_VALUE);
- if (op == AND_OPERATOR_VALUE) {
- m_op = OP_AND;
- }
- else if (op == OR_OPERATOR_VALUE) {
- m_op = OP_OR;
- }
- else {
- throw ConfigurationException("Unrecognized operator in Time AccessControl configuration.");
- }
-
- for (const auto& child : pt) {
- if (child.first != "<xmlattr>") {
- m_rules.push_back(unique_ptr<Rule>(new Rule(child.first, child.second)));
- }
- }
-
- if (m_rules.empty())
- throw ConfigurationException("Time AccessControl plugin requires at least one rule.");
-}
-
-
-AccessControl::aclresult_t TimeAccessControl::authorized(const SPRequest& request, const Session* session) const
-{
- switch (m_op) {
- case OP_AND:
- {
- for (auto& rule : m_rules) {
- if (rule->authorized(request, session) != shib_acl_true) {
- request.debug("time-based rule unsuccessful, denying access");
- return shib_acl_false;
- }
- }
- return shib_acl_true;
- }
-
- case OP_OR:
- {
- for (auto& rule : m_rules) {
- if (rule->authorized(request,session) == shib_acl_true)
- return shib_acl_true;
- }
- request.debug("all time-based rules unsuccessful, denying access");
- return shib_acl_false;
- }
- }
- request.warn("unknown operator in access control policy, denying access");
- return shib_acl_false;
-}
diff --git a/shibsp/impl/XMLAccessControl.cpp b/shibsp/impl/XMLAccessControl.cpp
index 5512aaaa..5beabf12 100644
--- a/shibsp/impl/XMLAccessControl.cpp
+++ b/shibsp/impl/XMLAccessControl.cpp
@@ -36,6 +36,8 @@
#include <algorithm>
#include <memory>
#include <set>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
#include <boost/property_tree/ptree.hpp>
#ifdef SHIBSP_USE_BOOST_REGEX
@@ -83,6 +85,23 @@ namespace {
regexp::regex m_re;
};
+ class TimeRule : public AccessControl, public NoOpSharedLockable
+ {
+ public:
+ TimeRule(const string& name, const ptree& pt);
+ ~TimeRule() {}
+
+ aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+ enum time_type_t {
+ TM_AUTHN, TM_TIME, TM_YEAR, TM_MONTH, TM_DAY, TM_HOUR, TM_MINUTE, TM_SECOND, TM_WDAY
+ };
+ private:
+ time_type_t m_type;
+ enum { OP_LT, OP_LE, OP_EQ, OP_GE, OP_GT } m_op;
+ time_t m_value;
+ };
+
class Operator : public AccessControl, public NoOpSharedLockable
{
public:
@@ -96,10 +115,35 @@ namespace {
vector<unique_ptr<AccessControl>> m_operands;
};
- static const char ACCESS_CONTROL_PROP_PATH[] = "AccessControl";
- static const char REQUIRE_PROP_PATH[] = "<xmlattr>.require";
- static const char RULE_PROP_PATH[] = "Rule";
- static const char RULE_REGEX_PROP_PATH[] = "RuleRegex";
+ static const char AND_PROP_PATH[] = "AND";
+ static const char OR_PROP_PATH[] = "OR";
+ static const char NOT_PROP_PATH[] = "NOT";
+ static const char ACCESS_CONTROL_PROP_PATH[] = "AccessControl";
+ static const char REQUIRE_PROP_PATH[] = "<xmlattr>.require";
+ static const char RULE_PROP_PATH[] = "Rule";
+ static const char RULE_REGEX_PROP_PATH[] = "RuleRegex";
+ static const char TIMESINCEAUTHN_PROP_PATH[] = "TimeSinceAuthn";
+ static const char TIME_PROP_PATH[] = "Time";
+ static const char DAY_PROP_PATH[] = "Day";
+ static const char DAYOFWEEK_PROP_PATH[] = "DayOfWeek";
+ static const char HOUR_PROP_PATH[] = "Hour";
+ static const char MINUTE_PROP_PATH[] = "Minute";
+ static const char MONTH_PROP_PATH[] = "Month";
+ static const char SECOND_PROP_PATH[] = "Second";
+ static const char YEAR_PROP_PATH[] = "Year";
+
+ // Indexed time rules for comparison/lookup in constructors.
+ static map<string,TimeRule::time_type_t> g_timeRules = {
+ { TIMESINCEAUTHN_PROP_PATH, TimeRule::TM_AUTHN },
+ { TIME_PROP_PATH, TimeRule::TM_TIME },
+ { DAY_PROP_PATH, TimeRule::TM_DAY },
+ { DAYOFWEEK_PROP_PATH, TimeRule::TM_WDAY },
+ { HOUR_PROP_PATH, TimeRule::TM_HOUR },
+ { MINUTE_PROP_PATH, TimeRule::TM_MINUTE },
+ { MONTH_PROP_PATH, TimeRule::TM_MONTH },
+ { SECOND_PROP_PATH, TimeRule::TM_SECOND },
+ { YEAR_PROP_PATH, TimeRule::TM_YEAR }
+ };
#if defined (_MSC_VER)
#pragma warning( push )
@@ -140,6 +184,20 @@ namespace shibsp {
}
};
+void SHIBSP_API shibsp::registerAccessControls()
+{
+ AgentConfig& conf=AgentConfig::getConfig();
+ conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);
+}
+
+AccessControl::AccessControl()
+{
+}
+
+AccessControl::~AccessControl()
+{
+}
+
Rule::Rule(const ptree& pt) : m_alias(pt.get(REQUIRE_PROP_PATH, ""))
{
if (m_alias.empty()) {
@@ -236,7 +294,7 @@ RuleRegex::RuleRegex(const ptree& pt)
if (m_alias == "authnContextClassRef") {
AgentConfig::getConfig().deprecation().warn(
- "RuleRegex specifying authnContextClassRef is deprecated and will be removed from a future version");
+ "Rule specifying authnContextClassRef is deprecated and will be removed from a future version");
}
static const char CASE_SENSITIVE_PROP_PATH[] = "caseSensitive";
@@ -308,6 +366,154 @@ AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const
return shib_acl_false;
}
+TimeRule::TimeRule(const string& name, const ptree& pt)
+{
+ // The TimeSinceAuthn rule operates on a Duration inside the element body,
+ // which should be the value of the tree.
+
+ if (name == TIMESINCEAUTHN_PROP_PATH) {
+ m_type = TM_AUTHN;
+ if ((m_value = parseISODuration(pt.get_value(""))) < 0) {
+ throw ConfigurationException("Unable to parse duration in TimeSinceAuthn rule.");
+ }
+ return;
+ }
+
+ // Anything else we have to parse the element body.
+ string s = pt.get_value("");
+ boost::trim(s);
+ vector<string> tokens;
+ if (boost::split(tokens, s, boost::is_space(), boost::algorithm::token_compress_on).size() != 2) {
+ throw ConfigurationException("Time-based rule requires element content of the form \"LT|LE|EQ|GE|GT value\".");
+ }
+ string& op = tokens.front();
+ if (op == "LT") { m_op = OP_LT; }
+ else if (op == "LE") { m_op = OP_LE; }
+ else if (op == "EQ") { m_op = OP_EQ; }
+ else if (op == "GE") { m_op = OP_GE; }
+ else if (op == "GT") { m_op = OP_GT; }
+ else {
+ throw ConfigurationException("First component of time-based rule must be one of LT, LE, EQ, GE, GT.");
+ }
+
+ if (name == TIME_PROP_PATH) {
+ m_type = g_timeRules[name];
+ if ((m_value = parseISODateTime(tokens.back())) < 0) {
+ throw ConfigurationException("Error parsing timestamp in Time rule.");
+ }
+ return;
+ }
+
+ const auto i = g_timeRules.find(name);
+ if (i != g_timeRules.end()) {
+ m_type = i->second;
+ m_value = boost::lexical_cast<time_t>(tokens.back());
+ }
+ else {
+ throw ConfigurationException("Unrecognized time-based rule.");
+ }
+}
+
+AccessControl::aclresult_t TimeRule::authorized(const SPRequest& request, const Session* session) const
+{
+ time_t operand = 0;
+
+ if (m_type == TM_AUTHN) {
+ if (session) {
+ // Locate the Attribute to be used for accessing the auth timestamp.
+ const AttributeConfiguration& config = request.getAgent().getAttributeConfiguration(
+ request.getRequestSettings().first->getString(RequestMapper::ATTRIBUTE_CONFIG_ID_PROP_NAME));
+ const auto attr = session->getAttributes().find(
+ config.getString(AttributeConfiguration::LEGACY_AUTHTIME_ATTRIBUTE_PROP_NAME,
+ AttributeConfiguration::LEGACY_AUTHTIME_ATTRIBUTE_PROP_DEFAULT));
+ if (attr == session->getAttributes().end()) {
+ request.debug("Attribute carrying authentication time unnvailable");
+ return shib_acl_false;
+ }
+
+ DDF val = const_cast<DDF&>(attr->second).first();
+ if (val.isstring()) {
+ const char* authtime = const_cast<DDF&>(attr->second).first().string();
+ if (authtime) {
+ if ((operand = parseISODateTime(authtime)) < 0) {
+ request.error("Error parsing authentication time from designated Attribute.");
+ return shib_acl_false;
+ }
+ }
+ }
+ else if (val.islong()) {
+ operand = val.longinteger();
+ }
+
+ if (operand > 0) {
+ if (time(nullptr) - operand <= m_value) {
+ return shib_acl_true;
+ }
+
+ request.debug("elapsed time since authentication exceeds limit");
+ return shib_acl_false;
+ }
+ else {
+ request.debug("Attribute carrying authentication time unnvailable");
+ return shib_acl_false;
+ }
+ }
+ else {
+ request.debug("session unnvailable");
+ return shib_acl_false;
+ }
+ }
+
+ // Extract value from tm struct or time directly.
+ operand = time(nullptr);
+ if (m_type != TM_TIME) {
+#ifndef HAVE_LOCALTIME_R
+ struct tm* ptime = localtime(&operand);
+#else
+ struct tm res;
+ struct tm* ptime = localtime_r(&operand, &res);
+#endif
+ switch (m_type) {
+ case TM_YEAR:
+ operand = ptime->tm_year + 1900;
+ break;
+ case TM_MONTH:
+ operand = ptime->tm_mon + 1;
+ break;
+ case TM_DAY:
+ operand = ptime->tm_mday;
+ break;
+ case TM_HOUR:
+ operand = ptime->tm_hour;
+ break;
+ case TM_MINUTE:
+ operand = ptime->tm_min;
+ break;
+ case TM_SECOND:
+ operand = ptime->tm_sec;
+ break;
+ case TM_WDAY:
+ operand = ptime->tm_wday;
+ break;
+ }
+ }
+
+ // Compare operand to test value in rule using rule operator.
+ switch (m_op) {
+ case OP_LT:
+ return (operand < m_value) ? shib_acl_true : shib_acl_false;
+ case OP_LE:
+ return (operand <= m_value) ? shib_acl_true : shib_acl_false;
+ case OP_EQ:
+ return (operand == m_value) ? shib_acl_true : shib_acl_false;
+ case OP_GE:
+ return (operand >= m_value) ? shib_acl_true : shib_acl_false;
+ case OP_GT:
+ return (operand > m_value) ? shib_acl_true : shib_acl_false;
+ }
+ return shib_acl_false;
+}
+
Operator::Operator(const string& name, const ptree& pt)
{
if (name == "NOT") {
@@ -330,9 +536,18 @@ Operator::Operator(const string& name, const ptree& pt)
else if (child.first == RULE_REGEX_PROP_PATH) {
m_operands.push_back(unique_ptr<AccessControl>(new RuleRegex(child.second)));
}
- else if (child.first != "<xmlattr>") {
+ else if (child.first == AND_PROP_PATH || child.first == OR_PROP_PATH || child.first == NOT_PROP_PATH) {
m_operands.push_back(unique_ptr<AccessControl>(new Operator(child.first, child.second)));
}
+ else if (g_timeRules.find(child.first) != g_timeRules.end()) {
+ m_operands.push_back(unique_ptr<AccessControl>(new TimeRule(child.first, child.second)));
+ }
+ else if (child.first == "<xmlattr>") {
+ continue;
+ }
+ else {
+ throw ConfigurationException("Unrecognized child element in policy.");
+ }
}
if (m_op == OP_NOT && m_operands.size() != 1) {
@@ -385,9 +600,13 @@ unique_ptr<AccessControl> XMLAccessControl::processChild(const string& name, con
else if (name == RULE_REGEX_PROP_PATH) {
return unique_ptr<AccessControl>(new RuleRegex(pt));
}
- else {
+ else if (name == AND_PROP_PATH || name == OR_PROP_PATH || name == NOT_PROP_PATH) {
return unique_ptr<AccessControl>(new Operator(name, pt));
}
+ else if (g_timeRules.find(name) != g_timeRules.end()) {
+ return unique_ptr<AccessControl>(new TimeRule(name, pt));
+ }
+ throw ConfigurationException("Unrecognized child element in policy.");
}
pair<bool,ptree*> XMLAccessControl::load() noexcept
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ae6ae700..087c32d3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -16,7 +16,6 @@ shibsptest_SOURCES = \
AgentTestSuite.cpp \
AgentConfigTests.cpp \
attribute/impl/DefaultAttributeConfigurationtests.cpp \
- impl/TimeAccessControlTests.cpp \
impl/XMLAccessControlTests.cpp \
impl/XMLRequestMapperTests.cpp \
platform/iis/ModuleConfigTests.cpp \
diff --git a/tests/data/impl/acl/inline-new-time-invalid.xml b/tests/data/impl/acl/inline-new-time-invalid.xml
new file mode 100644
index 00000000..3e569149
--- /dev/null
+++ b/tests/data/impl/acl/inline-new-time-invalid.xml
@@ -0,0 +1,5 @@
+<AccessControlProvider type="XML">
+ <AccessControl>
+ <Time>GT 3000-01-22T03:00:00Z</Time>
+ </AccessControl>
+</AccessControlProvider>
diff --git a/tests/data/impl/acl/inline-new-time-valid.xml b/tests/data/impl/acl/inline-new-time-valid.xml
new file mode 100644
index 00000000..21d23c4b
--- /dev/null
+++ b/tests/data/impl/acl/inline-new-time-valid.xml
@@ -0,0 +1,6 @@
+<AccessControlProvider type="XML">
+ <AccessControl>
+ <Time>LE 3000-01-22T03:00:00Z</Time>
+ </AccessControl>
+</AccessControlProvider>
+
diff --git a/tests/data/impl/acl/inline-old-time-invalid.xml b/tests/data/impl/acl/inline-old-time-invalid.xml
new file mode 100644
index 00000000..b8e68eb2
--- /dev/null
+++ b/tests/data/impl/acl/inline-old-time-invalid.xml
@@ -0,0 +1,6 @@
+<AccessControlProvider type="XML">
+ <AccessControl>
+ <Time>LE 2025-01-22T03:00:00Z</Time>
+ </AccessControl>
+</AccessControlProvider>
+
diff --git a/tests/data/impl/acl/inline-old-time-valid.xml b/tests/data/impl/acl/inline-old-time-valid.xml
new file mode 100644
index 00000000..12ee9967
--- /dev/null
+++ b/tests/data/impl/acl/inline-old-time-valid.xml
@@ -0,0 +1,6 @@
+<AccessControlProvider type="XML">
+ <AccessControl>
+ <Time>GT 2025-01-22T03:00:00Z</Time>
+ </AccessControl>
+</AccessControlProvider>
+
diff --git a/tests/data/impl/acl/inline-timesinceauth.xml b/tests/data/impl/acl/inline-timesinceauth.xml
new file mode 100644
index 00000000..f0952116
--- /dev/null
+++ b/tests/data/impl/acl/inline-timesinceauth.xml
@@ -0,0 +1,5 @@
+<AccessControlProvider type="XML">
+ <AccessControl>
+ <TimeSinceAuthn>PT1H</TimeSinceAuthn>
+ </AccessControl>
+</AccessControlProvider>
diff --git a/tests/data/impl/acl/inline-year-invalid.xml b/tests/data/impl/acl/inline-year-invalid.xml
new file mode 100644
index 00000000..fd4f1098
--- /dev/null
+++ b/tests/data/impl/acl/inline-year-invalid.xml
@@ -0,0 +1,6 @@
+<AccessControlProvider type="XML">
+ <AccessControl>
+ <Year>LT 2000</Year>
+ </AccessControl>
+</AccessControlProvider>
+
diff --git a/tests/data/impl/acl/inline-year-valid.xml b/tests/data/impl/acl/inline-year-valid.xml
new file mode 100644
index 00000000..fe5f7a2f
--- /dev/null
+++ b/tests/data/impl/acl/inline-year-valid.xml
@@ -0,0 +1,6 @@
+<AccessControlProvider type="XML">
+ <AccessControl>
+ <Year>LT 3000</Year>
+ </AccessControl>
+</AccessControlProvider>
+
diff --git a/tests/data/impl/acl/time/acl-badxml.xml b/tests/data/impl/acl/time/acl-badxml.xml
deleted file mode 100644
index 46663ff5..00000000
--- a/tests/data/impl/acl/time/acl-badxml.xml
+++ /dev/null
@@ -1 +0,0 @@
-<AccessControlProvider type="Time">
diff --git a/tests/data/impl/acl/time/external-acl-badxml.xml b/tests/data/impl/acl/time/external-acl-badxml.xml
deleted file mode 100644
index e647978b..00000000
--- a/tests/data/impl/acl/time/external-acl-badxml.xml
+++ /dev/null
@@ -1 +0,0 @@
-<AccessControlProvider type="XML" path="./data/impl/acl/time/acl-badxml.xml" />
diff --git a/tests/data/impl/acl/time/inline-new-time-invalid.xml b/tests/data/impl/acl/time/inline-new-time-invalid.xml
deleted file mode 100644
index 7dc1a3bd..00000000
--- a/tests/data/impl/acl/time/inline-new-time-invalid.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<AccessControlProvider type="Time">
- <Time>GT 3000-01-22T03:00:00Z</Time>
-</AccessControlProvider>
-
diff --git a/tests/data/impl/acl/time/inline-new-time-valid.xml b/tests/data/impl/acl/time/inline-new-time-valid.xml
deleted file mode 100644
index ab0158ba..00000000
--- a/tests/data/impl/acl/time/inline-new-time-valid.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<AccessControlProvider type="Time">
- <Time>LE 3000-01-22T03:00:00Z</Time>
-</AccessControlProvider>
-
diff --git a/tests/data/impl/acl/time/inline-old-time-invalid.xml b/tests/data/impl/acl/time/inline-old-time-invalid.xml
deleted file mode 100644
index 5fa20340..00000000
--- a/tests/data/impl/acl/time/inline-old-time-invalid.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<AccessControlProvider type="Time">
- <Time>LE 2025-01-22T03:00:00Z</Time>
-</AccessControlProvider>
-
diff --git a/tests/data/impl/acl/time/inline-old-time-valid.xml b/tests/data/impl/acl/time/inline-old-time-valid.xml
deleted file mode 100644
index 9b826675..00000000
--- a/tests/data/impl/acl/time/inline-old-time-valid.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<AccessControlProvider type="Time">
- <Time>GT 2025-01-22T03:00:00Z</Time>
-</AccessControlProvider>
-
diff --git a/tests/data/impl/acl/time/inline-timesinceauth.xml b/tests/data/impl/acl/time/inline-timesinceauth.xml
deleted file mode 100644
index 2b3c69fe..00000000
--- a/tests/data/impl/acl/time/inline-timesinceauth.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<AccessControlProvider type="Time">
- <TimeSinceAuthn>PT1H</TimeSinceAuthn>
-</AccessControlProvider>
diff --git a/tests/data/impl/acl/time/inline-year-invalid.xml b/tests/data/impl/acl/time/inline-year-invalid.xml
deleted file mode 100644
index 92262ba0..00000000
--- a/tests/data/impl/acl/time/inline-year-invalid.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<AccessControlProvider type="Time" operator="AND">
- <Year>LT 2000</Year>
-</AccessControlProvider>
-
diff --git a/tests/data/impl/acl/time/inline-year-valid.xml b/tests/data/impl/acl/time/inline-year-valid.xml
deleted file mode 100644
index e07754f6..00000000
--- a/tests/data/impl/acl/time/inline-year-valid.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<AccessControlProvider type="Time" operator="AND">
- <Year>LT 3000</Year>
-</AccessControlProvider>
-
diff --git a/tests/data/impl/acl/time/internal-acl-invalid2.xml b/tests/data/impl/acl/time/internal-acl-invalid2.xml
deleted file mode 100644
index cd1c2466..00000000
--- a/tests/data/impl/acl/time/internal-acl-invalid2.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<AccessControlProvider type="Time">
- <Foo/>
-</AccessControlProvider>
diff --git a/tests/impl/TimeAccessControlTests.cpp b/tests/impl/TimeAccessControlTests.cpp
deleted file mode 100644
index c82d1706..00000000
--- a/tests/impl/TimeAccessControlTests.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * TimeAccessControlTests.cpp
- *
- * Unit tests for Time AccessControl implementation.
- */
-
-#include "exceptions.h"
-#include "AbstractSPRequest.h"
-#include "AccessControl.h"
-#include "AgentConfig.h"
-#include "logging/Category.h"
-#include "remoting/ddf.h"
-#include "session/SessionCache.h"
-#include "util/BoostPropertySet.h"
-
-#include "DummyRequest.h"
-
-#ifdef HAVE_CXX14
-# include <shared_mutex>
-#endif
-
-#include <boost/test/unit_test.hpp>
-#include <boost/property_tree/xml_parser.hpp>
-
-using namespace shibsp;
-using namespace boost::property_tree;
-using namespace std;
-
-#define DATA_PATH "./data/impl/acl/time/"
-
-namespace {
-
-/** Open structure for testing manipulation. */
-struct DummySession : public Session, public NoOpBasicLockable {
-public:
- DummySession() {}
- ~DummySession() {
- for (auto& a : m_attributes) {
- a.second.destroy();
- }
- }
-
- const char* getID() const {
- return nullptr;
- }
- unsigned int getVersion() const {
- return 1;
- }
- const char* getApplicationID() const {
- return nullptr;
- }
- time_t getCreation() const {
- return 0;
- }
- time_t getLastAccess() const {
- return 0;
- }
- const map<string,DDF>& getAttributes() const {
- return m_attributes;
- }
- DDF getOpaqueData() const {
- return DDF();
- }
-
- map<string,DDF> m_attributes;
-};
-
-class MappableDummyRequest : public DummyRequest {
-public:
- MappableDummyRequest() {}
- ~MappableDummyRequest() {}
- RequestMapper::Settings getRequestSettings() const { return make_pair(&m_map, nullptr); }
-
- BoostPropertySet m_map;
-};
-
-class exceptionCheck {
-public:
- exceptionCheck(const string& msg) : m_msg(msg) {}
- bool check_message(const exception& e) {
- if (m_msg.compare(e.what()) == 0) {
- return true;
- }
- else {
- cout << "Non-matching message: " << e.what() << endl;
- return false;
- }
- }
-private:
- string m_msg;
-};
-
-struct TimeAccessControlFixture
-{
- TimeAccessControlFixture() : data_path(DATA_PATH) {
- AgentConfig::getConfig().init(nullptr, (data_path + "../../console-agent.ini").c_str(), true);
- }
- ~TimeAccessControlFixture() {
- AgentConfig::getConfig().term();
- }
-
- void parse(const string& filename) {
- xml_parser::read_xml(data_path + filename, tree, xml_parser::no_comments|xml_parser::trim_whitespace);
- }
-
- ptree tree;
- string data_path;
-};
-
-/////////////
-// File pointing to external ACL file that's invalid XML.
-/////////////
-
-BOOST_FIXTURE_TEST_CASE(TimeAccessControl_external_invalid, TimeAccessControlFixture)
-{
- parse("external-acl-badxml.xml");
- BOOST_CHECK_EQUAL(tree.size(), 1);
-
- exceptionCheck checker("Initial AccessControl configuration was invalid.");
- BOOST_CHECK_EXCEPTION(AgentConfig::getConfig().AccessControlManager.newPlugin(
- tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true),
- ConfigurationException, checker.check_message);
-}
-
-/////////////
-// Inline ACL content that has a bad internal element.
-/////////////
-
-BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_invalid_internal, TimeAccessControlFixture)
-{
- parse("internal-acl-invalid2.xml");
- BOOST_CHECK_EQUAL(tree.size(), 1);
-
- exceptionCheck checker("Time-based rule requires element content of the form \"LT|LE|EQ|GE|GT value\".");
- BOOST_CHECK_EXCEPTION(AgentConfig::getConfig().AccessControlManager.newPlugin(
- tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true),
- ConfigurationException, checker.check_message);
-}
-
-/////////////
-// Inline ACL test for TimeSinceAuthn rule.
-/////////////
-
-BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_TimeSinceAuthn, TimeAccessControlFixture)
-{
- parse("inline-timesinceauth.xml");
- BOOST_CHECK_EQUAL(tree.size(), 1);
-
- unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
- tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
-
-#ifdef HAVE_CXX14
- shared_lock locker(*acl);
-#endif
-
- MappableDummyRequest request;
- DummySession session;
-
- // No attribute available.
- BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
-
- DDF ac("Shib-Authentication-Instant");
- ac.list();
- ac.add(DDF(nullptr).longinteger(time(nullptr) - 300));
- session.m_attributes[ac.name()] = ac;
-
- BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
-
- ac.first().longinteger(time(nullptr) - 7200);
- BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
-}
-
-/////////////
-// Inline ACL tests for absolute Time rule.
-/////////////
-
-BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_OldTimeValid, TimeAccessControlFixture)
-{
- parse("inline-old-time-valid.xml");
- BOOST_CHECK_EQUAL(tree.size(), 1);
-
- unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
- tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
-
-#ifdef HAVE_CXX14
- shared_lock locker(*acl);
-#endif
-
- MappableDummyRequest request;
- DummySession session;
-
- BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
-}
-
-BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_OldTimeInvalid, TimeAccessControlFixture)
-{
- parse("inline-old-time-invalid.xml");
- BOOST_CHECK_EQUAL(tree.size(), 1);
-
- unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
- tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
-
-#ifdef HAVE_CXX14
- shared_lock locker(*acl);
-#endif
-
- MappableDummyRequest request;
- DummySession session;
-
- BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
-}
-
-BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_NewTimeValid, TimeAccessControlFixture)
-{
- parse("inline-new-time-valid.xml");
- BOOST_CHECK_EQUAL(tree.size(), 1);
-
- unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
- tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
-
-#ifdef HAVE_CXX14
- shared_lock locker(*acl);
-#endif
-
- MappableDummyRequest request;
- DummySession session;
-
- BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
-}
-
-BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_NewTimeInvalid, TimeAccessControlFixture)
-{
- parse("inline-new-time-invalid.xml");
- BOOST_CHECK_EQUAL(tree.size(), 1);
-
- unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
- tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
-
-#ifdef HAVE_CXX14
- shared_lock locker(*acl);
-#endif
-
- MappableDummyRequest request;
- DummySession session;
-
- BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
-}
-
-BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_YearValid, TimeAccessControlFixture)
-{
- parse("inline-year-valid.xml");
- BOOST_CHECK_EQUAL(tree.size(), 1);
-
- unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
- tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
-
-#ifdef HAVE_CXX14
- shared_lock locker(*acl);
-#endif
-
- MappableDummyRequest request;
- DummySession session;
-
- BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
-}
-
-BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_YearInvalid, TimeAccessControlFixture)
-{
- parse("inline-year-invalid.xml");
- BOOST_CHECK_EQUAL(tree.size(), 1);
-
- unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
- tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
-
-#ifdef HAVE_CXX14
- shared_lock locker(*acl);
-#endif
-
- MappableDummyRequest request;
- DummySession session;
-
- BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
-}
-
-};
diff --git a/tests/impl/XMLAccessControlTests.cpp b/tests/impl/XMLAccessControlTests.cpp
index 2eb960a4..957a59e3 100644
--- a/tests/impl/XMLAccessControlTests.cpp
+++ b/tests/impl/XMLAccessControlTests.cpp
@@ -460,4 +460,149 @@ BOOST_FIXTURE_TEST_CASE(XMLAccessControl_external_NOT, XMLAccessControlFixture)
BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
}
+/////////////
+// Inline ACL test for TimeSinceAuthn rule.
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_TimeSinceAuthn, XMLAccessControlFixture)
+{
+ parse("inline-timesinceauth.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ // No attribute available.
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+
+ DDF ac("Shib-Authentication-Instant");
+ ac.list();
+ ac.add(DDF(nullptr).longinteger(time(nullptr) - 300));
+ session.m_attributes[ac.name()] = ac;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+
+ ac.first().longinteger(time(nullptr) - 7200);
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+}
+
+/////////////
+// Inline ACL tests for absolute Time rule.
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_OldTimeValid, XMLAccessControlFixture)
+{
+ parse("inline-old-time-valid.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+}
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_OldTimeInvalid, XMLAccessControlFixture)
+{
+ parse("inline-old-time-invalid.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+}
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_NewTimeValid, XMLAccessControlFixture)
+{
+ parse("inline-new-time-valid.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+}
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_NewTimeInvalid, XMLAccessControlFixture)
+{
+ parse("inline-new-time-invalid.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+}
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_YearValid, XMLAccessControlFixture)
+{
+ parse("inline-year-valid.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+}
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_YearInvalid, XMLAccessControlFixture)
+{
+ parse("inline-year-invalid.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+}
+
};
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list