Code for default security policy, make policyId optional.
[shibboleth/sp.git] / shibsp / impl / XMLSecurityPolicyProvider.cpp
index e0eedc9..ac15595 100644 (file)
@@ -74,6 +74,7 @@ namespace shibsp {
         DOMDocument* m_document;\r
         vector<xstring> m_whitelist,m_blacklist;\r
         map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;\r
+        map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator m_defaultPolicy;\r
 \r
         friend class SHIBSP_DLLLOCAL XMLSecurityPolicyProvider;\r
     };\r
@@ -91,14 +92,18 @@ namespace shibsp {
             delete m_impl;\r
         }\r
 \r
-        const PropertySet* getPolicySettings(const char* id) const {\r
+        const PropertySet* getPolicySettings(const char* id=nullptr) const {\r
+            if (!id || !*id)\r
+                return m_impl->m_defaultPolicy->second.first;\r
             map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);\r
             if (i != m_impl->m_policyMap.end())\r
                 return i->second.first;\r
             throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));\r
         }\r
 \r
-        const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id) const {\r
+        const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id=nullptr) const {\r
+            if (!id || !*id)\r
+                return m_impl->m_defaultPolicy->second.second;\r
             map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);\r
             if (i != m_impl->m_policyMap.end())\r
                 return i->second.second;\r
@@ -172,7 +177,8 @@ SecurityPolicy* SecurityPolicyProvider::createSecurityPolicy(
     return new SecurityPolicy(application, role, (validate.first && validate.second), policyId);\r
 }\r
 \r
-XMLSecurityPolicyProviderImpl::XMLSecurityPolicyProviderImpl(const DOMElement* e, Category& log) : m_document(nullptr)\r
+XMLSecurityPolicyProviderImpl::XMLSecurityPolicyProviderImpl(const DOMElement* e, Category& log)\r
+    : m_document(nullptr), m_defaultPolicy(m_policyMap.end())\r
 {\r
 #ifdef _DEBUG\r
     xmltooling::NDC ndc("XMLSecurityPolicyProviderImpl");\r
@@ -207,22 +213,28 @@ XMLSecurityPolicyProviderImpl::XMLSecurityPolicyProviderImpl(const DOMElement* e
     SAMLConfig& samlConf = SAMLConfig::getConfig();\r
     e = XMLHelper::getFirstChildElement(e, Policy);\r
     while (e) {\r
-        auto_ptr_char id(e->getAttributeNS(nullptr, _id));\r
-        pair< PropertySet*,vector<const SecurityPolicyRule*> >& rules = m_policyMap[id.get()];\r
+        string id(XMLHelper::getAttrString(e, nullptr, _id));\r
+        pair< PropertySet*,vector<const SecurityPolicyRule*> >& rules = m_policyMap[id];\r
         rules.first = nullptr;\r
         auto_ptr<DOMPropertySet> settings(new DOMPropertySet());\r
         settings->load(e, nullptr, &filter);\r
         rules.first = settings.release();\r
 \r
+        // Set default policy if not set, or id is "default".\r
+        if (m_defaultPolicy == m_policyMap.end() || id == "default")\r
+            m_defaultPolicy = m_policyMap.find(id);\r
+\r
         // Process PolicyRule elements.\r
         const DOMElement* rule = XMLHelper::getFirstChildElement(e, PolicyRule);\r
         while (rule) {\r
-            auto_ptr_char type(rule->getAttributeNS(nullptr, _type));\r
-            try {\r
-                rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(), rule));\r
-            }\r
-            catch (exception& ex) {\r
-                log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());\r
+            string t(XMLHelper::getAttrString(rule, nullptr, _type));\r
+            if (!t.empty()) {\r
+                try {\r
+                    rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));\r
+                }\r
+                catch (exception& ex) {\r
+                    log.crit("error instantiating policy rule (%s) in policy (%s): %s", t.c_str(), id.c_str(), ex.what());\r
+                }\r
             }\r
             rule = XMLHelper::getNextSiblingElement(rule, PolicyRule);\r
         }\r
@@ -232,23 +244,28 @@ XMLSecurityPolicyProviderImpl::XMLSecurityPolicyProviderImpl(const DOMElement* e
             log.warn("detected legacy Policy configuration, please convert to new PolicyRule syntax");\r
             rule = XMLHelper::getFirstChildElement(e, Rule);\r
             while (rule) {\r
-                auto_ptr_char type(rule->getAttributeNS(nullptr, _type));\r
-                try {\r
-                    rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(), rule));\r
-                }\r
-                catch (exception& ex) {\r
-                    log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());\r
+                string t(XMLHelper::getAttrString(rule, nullptr, _type));\r
+                if (!t.empty()) {\r
+                    try {\r
+                        rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));\r
+                    }\r
+                    catch (exception& ex) {\r
+                        log.crit("error instantiating policy rule (%s) in policy (%s): %s", t.c_str(), id.c_str(), ex.what());\r
+                    }\r
                 }\r
                 rule = XMLHelper::getNextSiblingElement(rule, Rule);\r
             }\r
 \r
             // Manually add a basic Conditions rule.\r
-            log.info("installing a default Conditions rule in policy (%s) for compatibility with legacy configuration", id.get());\r
+            log.info("installing a default Conditions rule in policy (%s) for compatibility with legacy configuration", id.c_str());\r
             rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, nullptr));\r
         }\r
 \r
         e = XMLHelper::getNextSiblingElement(e, Policy);\r
     }\r
+\r
+    if (m_defaultPolicy == m_policyMap.end())\r
+        throw ConfigurationException("XML SecurityPolicyProvider requires at least one Policy.");\r
 }\r
 \r
 pair<bool,DOMElement*> XMLSecurityPolicyProvider::load(bool backup)\r