/*
- * Copyright 2001-2007 Internet2
- *
+ * Copyright 2001-2009 Internet2
+ *
* 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
/**
* @file shibsp/AccessControl.h
- *
+ *
* Interface to an access control plugin
*/
/**
* Interface to an access control plugin
- *
+ *
* Access control plugins return authorization decisions based on the intersection
* of the resource request and the active session. They can be implemented through
* cross-platform or platform-specific mechanisms.
shib_acl_false,
shib_acl_indeterminate
};
-
+
/**
* Perform an authorization check.
- *
+ *
* @param request SP request information
* @param session active user session, if any
* @return true iff access should be granted
*/
void SHIBSP_API registerAccessControls();
+ /** Chains together multiple plugins. */
+ #define CHAINING_ACCESS_CONTROL "Chaining"
+
/** AccessControl based on rudimentary XML syntax. */
- #define XML_ACCESS_CONTROL "XML"
+ #define XML_ACCESS_CONTROL "XML"
/** Reserved for Apache-style .htaccess support. */
- #define HT_ACCESS_CONTROL "htaccess"
+ #define HT_ACCESS_CONTROL "htaccess"
};
#endif /* __shibsp_acl_h__ */
handler/impl/Shib1SessionInitiator.cpp \
handler/impl/TransformSessionInitiator.cpp \
handler/impl/WAYFSessionInitiator.cpp \
+ impl/ChainingAccessControl.cpp \
impl/StorageServiceSessionCache.cpp \
impl/XMLAccessControl.cpp \
impl/XMLRequestMapper.cpp \
--- /dev/null
+/*\r
+ * Copyright 2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * ChainingAccessControl.cpp\r
+ *\r
+ * Access control plugin that combines other plugins.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "AccessControl.h"\r
+#include "SessionCache.h"\r
+#include "SPRequest.h"\r
+\r
+#include <xmltooling/util/XMLHelper.h>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+\r
+using namespace shibsp;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace {\r
+\r
+ class ChainingAccessControl : public AccessControl\r
+ {\r
+ public:\r
+ ChainingAccessControl(const DOMElement* e);\r
+\r
+ ~ChainingAccessControl() {\r
+ for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
+ }\r
+\r
+ Lockable* lock() {return this;}\r
+ void unlock() {}\r
+\r
+ aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
+\r
+ private:\r
+ enum operator_t { OP_AND, OP_OR } m_op;\r
+ vector<AccessControl*> m_ac;\r
+ };\r
+\r
+ AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)\r
+ {\r
+ return new ChainingAccessControl(e);\r
+ }\r
+\r
+ static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
+ static const XMLCh _operator[] = UNICODE_LITERAL_8(o,p,e,r,a,t,o,r);\r
+ static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);\r
+ static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D);\r
+ static const XMLCh OR[] = UNICODE_LITERAL_2(O,R);\r
+}\r
+\r
+extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e);\r
+\r
+void SHIBSP_API shibsp::registerAccessControls()\r
+{\r
+ SPConfig& conf=SPConfig::getConfig();\r
+ conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);\r
+ conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);\r
+ conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);\r
+}\r
+\r
+ChainingAccessControl::ChainingAccessControl(const DOMElement* e)\r
+{\r
+ const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL;\r
+ if (XMLString::equals(op, AND))\r
+ m_op=OP_AND;\r
+ else if (XMLString::equals(op, OR))\r
+ m_op=OP_OR;\r
+ else\r
+ throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");\r
+\r
+ try {\r
+ e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL;\r
+ while (e) {\r
+ auto_ptr_char type(e->getAttributeNS(NULL, _type));\r
+ if (type.get() && *type.get()) {\r
+ Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get());\r
+ m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e));\r
+ }\r
+ e = XMLHelper::getNextSiblingElement(e, _AccessControl);\r
+ }\r
+ }\r
+ catch (exception&) {\r
+ for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
+ throw;\r
+ }\r
+}\r
+\r
+AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const\r
+{\r
+ switch (m_op) {\r
+ case OP_AND:\r
+ {\r
+ for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
+ if ((*i)->authorized(request, session) != shib_acl_true)\r
+ return shib_acl_false;\r
+ }\r
+ return shib_acl_true;\r
+ }\r
+\r
+ case OP_OR:\r
+ {\r
+ for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
+ if ((*i)->authorized(request,session) == shib_acl_true)\r
+ return shib_acl_true;\r
+ }\r
+ return shib_acl_false;\r
+ }\r
+ }\r
+ request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access");\r
+ return shib_acl_false;\r
+}\r
/*\r
* Copyright 2001-2007 Internet2\r
- * \r
+ *\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
* You may obtain a copy of the License at\r
using namespace std;\r
\r
namespace {\r
- \r
+\r
class Rule : public AccessControl\r
{\r
public:\r
void unlock() {}\r
\r
aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
- \r
+\r
private:\r
string m_alias;\r
vector <string> m_vals;\r
};\r
- \r
+\r
class RuleRegex : public AccessControl\r
{\r
public:\r
~RuleRegex() {\r
delete m_re;\r
}\r
- \r
+\r
Lockable* lock() {return this;}\r
void unlock() {}\r
\r
aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
- \r
+\r
private:\r
string m_alias;\r
auto_arrayptr<char> m_exp;\r
RegularExpression* m_re;\r
};\r
- \r
+\r
class Operator : public AccessControl\r
{\r
public:\r
void unlock() {}\r
\r
aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
- \r
+\r
private:\r
enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;\r
vector<AccessControl*> m_operands;\r
{\r
public:\r
XMLAccessControl(const DOMElement* e)\r
- : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl")), m_rootAuthz(NULL) {\r
+ : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) {\r
load(); // guarantees an exception or the policy is loaded\r
}\r
- \r
+\r
~XMLAccessControl() {\r
delete m_rootAuthz;\r
}\r
static const XMLCh _RuleRegex[] = UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);\r
}\r
\r
-void SHIBSP_API shibsp::registerAccessControls()\r
-{\r
- SPConfig& conf=SPConfig::getConfig();\r
- conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);\r
- conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);\r
-}\r
-\r
Rule::Rule(const DOMElement* e)\r
{\r
auto_ptr_char req(e->getAttributeNS(NULL,require));\r
auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));\r
if (!vals.get())\r
return;\r
- \r
+\r
const XMLCh* flag = e->getAttributeNS(NULL,_list);\r
if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {\r
if (*vals.get())\r
m_vals.push_back(vals.get());\r
return;\r
}\r
- \r
+\r
#ifdef HAVE_STRTOK_R\r
char* pos=NULL;\r
const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);\r
request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
return shib_acl_false;\r
}\r
- \r
+\r
if (m_alias == "valid-user") {\r
if (session) {\r
request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get())\r
throw ConfigurationException("Access control rule missing require attribute or element content.");\r
m_alias=req.get();\r
- \r
+\r
const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);\r
bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));\r
try {\r
- m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull)); \r
+ m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));\r
}\r
catch (XMLException& ex) {\r
auto_ptr_char tmp(ex.getMessage());\r
request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
return shib_acl_false;\r
}\r
- \r
+\r
if (m_alias == "valid-user") {\r
if (session) {\r
request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
auto_ptr_char tmp(ex.getMessage());\r
request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());\r
}\r
- \r
+\r
return shib_acl_false;\r
}\r
\r
m_op=OP_OR;\r
else\r
throw ConfigurationException("Unrecognized operator in access control rule");\r
- \r
+\r
try {\r
e=XMLHelper::getFirstChildElement(e);\r
if (XMLString::equals(e->getLocalName(),_Rule))\r
m_operands.push_back(new RuleRegex(e));\r
else\r
m_operands.push_back(new Operator(e));\r
- \r
+\r
if (m_op==OP_NOT)\r
return;\r
- \r
+\r
e=XMLHelper::getNextSiblingElement(e);\r
while (e) {\r
if (XMLString::equals(e->getLocalName(),_Rule))\r
default:\r
return shib_acl_indeterminate;\r
}\r
- \r
+\r
case OP_AND:\r
{\r
for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
}\r
return shib_acl_true;\r
}\r
- \r
+\r
case OP_OR:\r
{\r
for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
{\r
// Load from source using base class.\r
pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
- \r
+\r
// If we own it, wrap it.\r
XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
\r
// Check for AccessControl wrapper and drop a level.\r
if (XMLString::equals(raw.second->getLocalName(),_AccessControl))\r
raw.second = XMLHelper::getFirstChildElement(raw.second);\r
- \r
+\r
AccessControl* authz;\r
if (XMLString::equals(raw.second->getLocalName(),_Rule))\r
authz=new Rule(raw.second);\r
Name="impl"\r
>\r
<File\r
+ RelativePath=".\impl\ChainingAccessControl.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\impl\StorageServiceSessionCache.cpp"\r
>\r
</File>\r
Name="impl"\r
>\r
<File\r
+ RelativePath=".\impl\ChainingAccessControl.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\impl\StorageServiceSessionCache.cpp"\r
>\r
</File>\r