https://bugs.internet2.edu/jira/browse/SSPCPP-182
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 21 May 2009 21:13:03 +0000 (21:13 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 21 May 2009 21:13:03 +0000 (21:13 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/branches/REL_2@3000 cb58f699-b61c-0410-a6fe-9272a202ed29

shibsp/AccessControl.h
shibsp/Makefile.am
shibsp/impl/ChainingAccessControl.cpp [new file with mode: 0644]
shibsp/impl/XMLAccessControl.cpp
shibsp/shibsp-lite.vcproj
shibsp/shibsp.vcproj

index 77774b6..59178aa 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/AccessControl.h
- * 
+ *
  * Interface to an access control plugin
  */
 
@@ -33,7 +33,7 @@ namespace shibsp {
 
      /**
      * 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.
@@ -54,10 +54,10 @@ namespace shibsp {
             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
@@ -70,11 +70,14 @@ namespace shibsp {
      */
     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__ */
index 470ecbd..c030944 100644 (file)
@@ -134,6 +134,7 @@ common_sources = \
        handler/impl/Shib1SessionInitiator.cpp \
        handler/impl/TransformSessionInitiator.cpp \
        handler/impl/WAYFSessionInitiator.cpp \
+       impl/ChainingAccessControl.cpp \
     impl/StorageServiceSessionCache.cpp \
        impl/XMLAccessControl.cpp \
        impl/XMLRequestMapper.cpp \
diff --git a/shibsp/impl/ChainingAccessControl.cpp b/shibsp/impl/ChainingAccessControl.cpp
new file mode 100644 (file)
index 0000000..8187471
--- /dev/null
@@ -0,0 +1,129 @@
+/*\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
index 939ea68..c7d29e8 100644 (file)
@@ -1,6 +1,6 @@
 /*\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
@@ -41,7 +41,7 @@ using namespace xmltooling;
 using namespace std;\r
 \r
 namespace {\r
-    \r
+\r
     class Rule : public AccessControl\r
     {\r
     public:\r
@@ -52,12 +52,12 @@ namespace {
         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
@@ -65,18 +65,18 @@ namespace {
         ~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
@@ -87,7 +87,7 @@ namespace {
         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
@@ -102,10 +102,10 @@ namespace {
     {\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
@@ -140,13 +140,6 @@ namespace {
     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
@@ -157,14 +150,14 @@ Rule::Rule(const DOMElement* e)
     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
@@ -191,7 +184,7 @@ AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Sess
         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
@@ -261,11 +254,11 @@ RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e-
     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
@@ -280,7 +273,7 @@ AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const
         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
@@ -335,7 +328,7 @@ AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const
         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
@@ -349,7 +342,7 @@ Operator::Operator(const DOMElement* e)
         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
@@ -358,10 +351,10 @@ Operator::Operator(const DOMElement* e)
             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
@@ -396,7 +389,7 @@ AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const
                 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
@@ -405,7 +398,7 @@ AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const
             }\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
@@ -423,14 +416,14 @@ pair<bool,DOMElement*> XMLAccessControl::load()
 {\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
index 32a8f7e..c8fff06 100644 (file)
                                Name="impl"\r
                                >\r
                                <File\r
+                                       RelativePath=".\impl\ChainingAccessControl.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\impl\StorageServiceSessionCache.cpp"\r
                                        >\r
                                </File>\r
index 2904bce..3ff5b3d 100644 (file)
                                Name="impl"\r
                                >\r
                                <File\r
+                                       RelativePath=".\impl\ChainingAccessControl.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\impl\StorageServiceSessionCache.cpp"\r
                                        >\r
                                </File>\r