[cpp-sp] branch master updated: SSPCPP-778 - Fork configuration and address backward compatibility

Scott Cantor cantor.2 at osu.edu
Wed Feb 14 14:19:29 EST 2018


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch master
in repository cpp-sp.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=7dd857a88e0cce727f758167c7cd7085639c8e7c

The following commit(s) were added to refs/heads/master by this push:
       new  7dd857a   SSPCPP-778 - Fork configuration and address backward compatibility
7dd857a is described below

commit 7dd857a88e0cce727f758167c7cd7085639c8e7c
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Feb 14 14:17:23 2018 -0500

    SSPCPP-778 - Fork configuration and address backward compatibility
    
    https://issues.shibboleth.net/jira/browse/SSPCPP-778
---
 adfs/adfs.cpp                                      |  4 +-
 apache/mod_shib.cpp                                |  2 +-
 nsapi_shib/nsapi_shib.cpp                          |  2 +-
 shibsp/SPConfig.cpp                                |  2 +-
 shibsp/ServiceProvider.h                           |  9 +++
 .../resolver/impl/MetadataAttributeExtractor.cpp   | 24 +++----
 shibsp/handler/AbstractHandler.h                   |  7 +-
 shibsp/handler/AssertionConsumerService.h          |  4 +-
 shibsp/handler/SecuredHandler.h                    |  4 +-
 shibsp/handler/SessionInitiator.h                  |  8 +--
 shibsp/handler/impl/AbstractHandler.cpp            |  8 +--
 shibsp/handler/impl/AssertionConsumerService.cpp   | 14 ++--
 shibsp/handler/impl/ChainingLogoutInitiator.cpp    |  2 +-
 shibsp/handler/impl/ChainingSessionInitiator.cpp   |  2 +-
 shibsp/handler/impl/SAML2ArtifactResolution.cpp    | 20 ++----
 shibsp/handler/impl/SAML2Logout.cpp                | 18 ++----
 shibsp/handler/impl/SAML2LogoutInitiator.cpp       |  4 +-
 shibsp/handler/impl/SAML2NameIDMgmt.cpp            | 18 ++----
 shibsp/handler/impl/SAML2SessionInitiator.cpp      | 16 ++---
 shibsp/handler/impl/SecuredHandler.cpp             |  2 +-
 shibsp/handler/impl/SessionInitiator.cpp           | 15 +++--
 shibsp/handler/impl/Shib1SessionInitiator.cpp      |  2 +-
 shibsp/handler/impl/WAYFSessionInitiator.cpp       |  2 +-
 shibsp/impl/XMLRequestMapper.cpp                   | 11 +++-
 shibsp/impl/XMLSecurityPolicyProvider.cpp          |  9 ++-
 shibsp/impl/XMLServiceProvider.cpp                 | 46 ++++++++-----
 shibsp/util/DOMPropertySet.cpp                     | 75 +++++++++++++++-------
 shibsp/util/DOMPropertySet.h                       | 49 +++++++++++++-
 shibsp/util/PropertySet.h                          |  2 +-
 shibsp/util/SPConstants.cpp                        | 13 ++++
 shibsp/util/SPConstants.h                          | 12 ++++
 unittests/TestApplication.h                        |  2 +-
 32 files changed, 251 insertions(+), 157 deletions(-)

diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp
index cc1e51f..0bac60c 100644
--- a/adfs/adfs.cpp
+++ b/adfs/adfs.cpp
@@ -108,7 +108,7 @@ namespace {
         }
     };
 
-    MessageDecoder* ADFSDecoderFactory(const pair<const DOMElement*,const XMLCh*>& p)
+    MessageDecoder* ADFSDecoderFactory(const DOMElement* const &)
     {
         return new ADFSDecoder();
     }
@@ -123,7 +123,7 @@ namespace {
     {
     public:
         ADFSSessionInitiator(const DOMElement* e, const char* appId)
-            : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.ADFS"), nullptr, &m_remapper), m_appId(appId), m_binding(WSFED_NS) {
+            : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.ADFS"), nullptr, this), m_appId(appId), m_binding(WSFED_NS) {
             // If Location isn't set, defer address registration until the setParent call.
             pair<bool,const char*> loc = getString("Location");
             if (loc.first) {
diff --git a/apache/mod_shib.cpp b/apache/mod_shib.cpp
index 9bd6c18..61e084e 100644
--- a/apache/mod_shib.cpp
+++ b/apache/mod_shib.cpp
@@ -1395,7 +1395,7 @@ public:
     pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const;
     pair<bool,int> getInt(const char* name, const char* ns=nullptr) const;
     void getAll(map<string,const char*>& properties) const;
-    const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIB2SPCONFIG_NS) const;
+    const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const;
     const xercesc::DOMElement* getElement() const;
 
     const htAccessControl& getHTAccessControl() const { return m_htaccess; }
diff --git a/nsapi_shib/nsapi_shib.cpp b/nsapi_shib/nsapi_shib.cpp
index bbceda7..200fd07 100644
--- a/nsapi_shib/nsapi_shib.cpp
+++ b/nsapi_shib/nsapi_shib.cpp
@@ -571,7 +571,7 @@ public:
     pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const;
     pair<bool,int> getInt(const char* name, const char* ns=nullptr) const;
     void getAll(map<string,const char*>& properties) const;
-    const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIB2SPCONFIG_NS) const;
+    const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const;
     const xercesc::DOMElement* getElement() const;
 
 private:
diff --git a/shibsp/SPConfig.cpp b/shibsp/SPConfig.cpp
index 3184176..bd93ca8 100644
--- a/shibsp/SPConfig.cpp
+++ b/shibsp/SPConfig.cpp
@@ -447,7 +447,7 @@ bool SPConfig::instantiate(const char* config, bool rethrow)
         getServiceProvider()->init();
         return true;
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         if (rethrow)
             throw;
         Category::getInstance(SHIBSP_LOGCAT ".Config").fatal("caught exception while loading configuration: %s", ex.what());
diff --git a/shibsp/ServiceProvider.h b/shibsp/ServiceProvider.h
index ca74573..d386c88 100644
--- a/shibsp/ServiceProvider.h
+++ b/shibsp/ServiceProvider.h
@@ -87,6 +87,15 @@ namespace shibsp {
          */
         virtual void init()=0;
 
+        /**
+         * Get the "active" XML namespace of the underlying configuration.
+         *
+         * <p>This accomodates multiple supported configuration schemas at runtime
+         * by allowing components to tailor their behavior to the specific format in
+         * use.</p>
+         */
+        virtual const XMLCh* getConfigurationNamespace() const=0;
+
 #ifndef SHIBSP_LITE
         /**
          * Returns a TransactionLog instance.
diff --git a/shibsp/attribute/resolver/impl/MetadataAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/MetadataAttributeExtractor.cpp
index 3a4ed59..208c853 100644
--- a/shibsp/attribute/resolver/impl/MetadataAttributeExtractor.cpp
+++ b/shibsp/attribute/resolver/impl/MetadataAttributeExtractor.cpp
@@ -130,26 +130,26 @@ MetadataExtractor::MetadataExtractor(const DOMElement* e)
         m_orgDisplayName(XMLHelper::getAttrString(e, nullptr, OrganizationDisplayName::LOCAL_NAME)),
         m_orgURL(XMLHelper::getAttrString(e, nullptr, OrganizationURL::LOCAL_NAME))
 {
-    e = e ? XMLHelper::getFirstChildElement(e) : nullptr;
-    while (e) {
-        if (XMLHelper::isNodeNamed(e, shibspconstants::SHIB2SPCONFIG_NS, ContactPerson::LOCAL_NAME)) {
-            string id(XMLHelper::getAttrString(e, nullptr, _id));
-            const XMLCh* type = e->getAttributeNS(nullptr, ContactPerson::CONTACTTYPE_ATTRIB_NAME);
+    const DOMElement* child = e ? XMLHelper::getFirstChildElement(e) : nullptr;
+    while (child) {
+        if (XMLHelper::isNodeNamed(child, e->getNamespaceURI(), ContactPerson::LOCAL_NAME)) {
+            string id(XMLHelper::getAttrString(child, nullptr, _id));
+            const XMLCh* type = child->getAttributeNS(nullptr, ContactPerson::CONTACTTYPE_ATTRIB_NAME);
             if (!id.empty() && type && *type) {
-                boost::shared_ptr<AttributeDecoder> decoder(SPConfig::getConfig().AttributeDecoderManager.newPlugin(DOMAttributeDecoderType, e));
+                boost::shared_ptr<AttributeDecoder> decoder(SPConfig::getConfig().AttributeDecoderManager.newPlugin(DOMAttributeDecoderType, child));
                 m_contacts.push_back(contact_tuple_t(id, type, decoder));
             }
         }
-        else if (XMLHelper::isNodeNamed(e, shibspconstants::SHIB2SPCONFIG_NS, Logo::LOCAL_NAME)) {
-            string id(XMLHelper::getAttrString(e, nullptr, _id));
-            int h(XMLHelper::getAttrInt(e, 0, Logo::HEIGHT_ATTRIB_NAME));
-            int w(XMLHelper::getAttrInt(e, 0, Logo::WIDTH_ATTRIB_NAME));
+        else if (XMLHelper::isNodeNamed(child, e->getNamespaceURI(), Logo::LOCAL_NAME)) {
+            string id(XMLHelper::getAttrString(child, nullptr, _id));
+            int h(XMLHelper::getAttrInt(child, 0, Logo::HEIGHT_ATTRIB_NAME));
+            int w(XMLHelper::getAttrInt(child, 0, Logo::WIDTH_ATTRIB_NAME));
             if (!id.empty()) {
-                boost::shared_ptr<AttributeDecoder> decoder(SPConfig::getConfig().AttributeDecoderManager.newPlugin(DOMAttributeDecoderType, e));
+                boost::shared_ptr<AttributeDecoder> decoder(SPConfig::getConfig().AttributeDecoderManager.newPlugin(DOMAttributeDecoderType, child));
                 m_logos.push_back(logo_tuple_t(id, h, w, decoder));
             }
         }
-        e = XMLHelper::getNextSiblingElement(e);
+        child = XMLHelper::getNextSiblingElement(child);
     }
 }
 
diff --git a/shibsp/handler/AbstractHandler.h b/shibsp/handler/AbstractHandler.h
index ee5fa95..5152f9b 100644
--- a/shibsp/handler/AbstractHandler.h
+++ b/shibsp/handler/AbstractHandler.h
@@ -72,13 +72,13 @@ namespace shibsp {
          * @param e         DOM element to load as property set.
          * @param log       logging category to use
          * @param filter    optional filter controls what child elements to include as nested PropertySets
-         * @param remapper  optional map of property rename rules for legacy property support
+         * @param remapper  optional property rename mapper for legacy property support
          */
         AbstractHandler(
             const xercesc::DOMElement* e,
             xmltooling::logging::Category& log,
             xercesc::DOMNodeFilter* filter=nullptr,
-            const std::map<std::string,std::string>* remapper=nullptr
+            const Remapper* remapper=nullptr
             );
 
         void log(SPRequest::SPLogLevel level, const std::string& msg) const;
@@ -270,9 +270,6 @@ namespace shibsp {
 
         /** Logging object. */
         xmltooling::logging::Category& m_log;
-        
-        /** Configuration namespace for custom properties. */
-        xmltooling::auto_ptr_char m_configNS;
 
     public:
         virtual ~AbstractHandler();
diff --git a/shibsp/handler/AssertionConsumerService.h b/shibsp/handler/AssertionConsumerService.h
index a775f91..97abda9 100644
--- a/shibsp/handler/AssertionConsumerService.h
+++ b/shibsp/handler/AssertionConsumerService.h
@@ -80,14 +80,14 @@ namespace shibsp {
          * @param appId     ID of application that "owns" the handler
          * @param log       a logging object to use
          * @param filter    optional filter controls what child elements to include as nested PropertySets
-         * @param remapper  optional map of property rename rules for legacy property support
+         * @param remapper  optional property rename mapper for legacy property support
          */
         AssertionConsumerService(
             const xercesc::DOMElement* e,
             const char* appId,
             xmltooling::logging::Category& log,
             xercesc::DOMNodeFilter* filter=nullptr,
-            const std::map<std::string,std::string>* remapper=nullptr
+            const Remapper* remapper=nullptr
             );
 
         /**
diff --git a/shibsp/handler/SecuredHandler.h b/shibsp/handler/SecuredHandler.h
index df31561..bae9547 100644
--- a/shibsp/handler/SecuredHandler.h
+++ b/shibsp/handler/SecuredHandler.h
@@ -53,7 +53,7 @@ namespace shibsp {
          * @param aclProperty   name of IP/CIDR ACL property
          * @param defaultACL    IP/CIDR ACL to apply if no acl property is set
          * @param filter        optional filter controls what child elements to include as nested PropertySets
-         * @param remapper      optional map of property rename rules for legacy property support
+         * @param remapper      optional property rename mapper for legacy property support
          */
         SecuredHandler(
             const xercesc::DOMElement* e,
@@ -61,7 +61,7 @@ namespace shibsp {
             const char* aclProperty="acl",
             const char* defaultACL=nullptr,
             xercesc::DOMNodeFilter* filter=nullptr,
-            const std::map<std::string,std::string>* remapper=nullptr
+            const Remapper* remapper=nullptr
             );
 
     public:
diff --git a/shibsp/handler/SessionInitiator.h b/shibsp/handler/SessionInitiator.h
index c4e8c05..e01d1c0 100644
--- a/shibsp/handler/SessionInitiator.h
+++ b/shibsp/handler/SessionInitiator.h
@@ -28,8 +28,8 @@
 #define __shibsp_sesinitiator_h__
 
 #include <shibsp/handler/Handler.h>
+#include <shibsp/util/DOMPropertySet.h>
 
-#include <map>
 #include <set>
 #include <string>
 
@@ -43,12 +43,10 @@ namespace shibsp {
      * <p>By default, SessionInitiators look for an entityID on the incoming request
      * and pass control to the specialized run method.
      */
-    class SHIBSP_API SessionInitiator : public virtual Handler
+    class SHIBSP_API SessionInitiator : public virtual Handler, public DOMPropertySet::Remapper
     {
         friend void SHIBSP_API registerSessionInitiators();
     protected:
-        /** Property remapper for configuration compatibility. */
-        static std::map<std::string,std::string> m_remapper;
 
         /** Set of optional settings supported by handler. */
         std::set<std::string> m_supportedOptions;
@@ -105,6 +103,8 @@ namespace shibsp {
 
         std::pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
+        const char* remap(const char* src, xmltooling::logging::Category& log) const;
+
 #ifndef SHIBSP_LITE
         const char* getType() const;
         void generateMetadata(opensaml::saml2md::SPSSODescriptor& role, const char* handlerURL) const;
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index 37c07bd..24ab894 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -418,8 +418,8 @@ void Handler::recoverRelayState(
 }
 
 AbstractHandler::AbstractHandler(
-    const DOMElement* e, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
-    ) : m_log(log), m_configNS(shibspconstants::SHIB2SPCONFIG_NS) {
+    const DOMElement* e, Category& log, DOMNodeFilter* filter, const Remapper* remapper
+    ) : m_log(log) {
     load(e, nullptr, filter, remapper);
 }
 
@@ -486,7 +486,7 @@ void AbstractHandler::fillStatus(saml2p::StatusResponseType& response, const XML
         ssubcode->setValue(subcode);
     }
     if (msg) {
-        pair<bool,bool> flag = getBool("detailedErrors", m_configNS.get());
+        pair<bool,bool> flag = getBool("detailedErrors", shibspconstants::ASCII_SHIBSPCONFIG_NS);
         auto_ptr_XMLCh widemsg((flag.first && flag.second) ? msg : "Error processing request.");
         saml2p::StatusMessage* sm = saml2p::StatusMessageBuilder::buildStatusMessage();
         status->setStatusMessage(sm);
@@ -523,7 +523,7 @@ long AbstractHandler::sendMessage(
     const EntityDescriptor* entity = role ? dynamic_cast<const EntityDescriptor*>(role->getParent()) : nullptr;
     const PropertySet* relyingParty = application.getRelyingParty(entity);
     pair<bool,const char*> flag = getString("signing",
-        !getElement() || XMLString::equals(getElement()->getNamespaceURI(), shibspconstants::SHIB2SPCONFIG_NS) ? nullptr : m_configNS.get());
+        !getElement() || XMLString::equals(getElement()->getNamespaceURI(), shibspconstants::SHIBSPCONFIG_NS) ? nullptr : shibspconstants::ASCII_SHIBSPCONFIG_NS);
     if (!flag.first)
         flag = relyingParty->getString("signing");
     if (SPConfig::shouldSignOrEncrypt(flag.first ? flag.second : defaultSigningProperty, destination, encoder.isUserAgentPresent())) {
diff --git a/shibsp/handler/impl/AssertionConsumerService.cpp b/shibsp/handler/impl/AssertionConsumerService.cpp
index 6e18f90..2ded160 100644
--- a/shibsp/handler/impl/AssertionConsumerService.cpp
+++ b/shibsp/handler/impl/AssertionConsumerService.cpp
@@ -74,7 +74,7 @@ using namespace boost;
 using namespace std;
 
 AssertionConsumerService::AssertionConsumerService(
-    const DOMElement* e, const char* appId, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
+    const DOMElement* e, const char* appId, Category& log, DOMNodeFilter* filter, const Remapper* remapper
     ) : AbstractHandler(e, log, filter, remapper)
 {
     if (!e)
@@ -84,11 +84,7 @@ AssertionConsumerService::AssertionConsumerService(
     setAddress(address.c_str());
 #ifndef SHIBSP_LITE
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-        m_decoder.reset(
-            SAMLConfig::getConfig().MessageDecoderManager.newPlugin(
-                getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
-                )
-            );
+        m_decoder.reset(SAMLConfig::getConfig().MessageDecoderManager.newPlugin(getString("Binding").second, e));
         m_decoder->setArtifactResolver(SPConfig::getConfig().getArtifactResolver());
     }
 #endif
@@ -162,7 +158,7 @@ pair<bool,long> AssertionConsumerService::processMessage(
 {
 #ifndef SHIBSP_LITE
     // Locate policy key.
-    pair<bool,const char*> prop = getString("policyId", m_configNS.get());  // may be namespace-qualified if inside handler element
+    pair<bool,const char*> prop = getString("policyId", shibspconstants::ASCII_SHIBSPCONFIG_NS);  // may be namespace-qualified if inside handler element
     if (!prop.first)
         prop = getString("policyId");   // try unqualified
     if (!prop.first)
@@ -244,7 +240,7 @@ pair<bool,long> AssertionConsumerService::processMessage(
         // Check for isPassive error condition.
         const char* sc2 = ex.getProperty("statusCode2");
         if (sc2 && !strcmp(sc2, "urn:oasis:names:tc:SAML:2.0:status:NoPassive")) {
-            pair<bool,bool> ignore = getBool("ignoreNoPassive", m_configNS.get());  // may be namespace-qualified inside handler element
+            pair<bool,bool> ignore = getBool("ignoreNoPassive", shibspconstants::ASCII_SHIBSPCONFIG_NS);  // may be namespace-qualified inside handler element
             if (!ignore.first)
                 ignore = getBool("ignoreNoPassive");    // try unqualified
             if (ignore.first && ignore.second && !relayState.empty()) {
@@ -361,7 +357,7 @@ void AssertionConsumerService::generateMetadata(SPSSODescriptor& role, const cha
     // Initial guess at index to use.
     pair<bool,unsigned int> ix = pair<bool,unsigned int>(false,0);
     if (!strncmp(handlerURL, "https", 5))
-        ix = getUnsignedInt("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS);
+        ix = getUnsignedInt("sslIndex", shibspconstants::ASCII_SHIBSPCONFIG_NS);
     if (!ix.first)
         ix = getUnsignedInt("index");
     if (!ix.first)
diff --git a/shibsp/handler/impl/ChainingLogoutInitiator.cpp b/shibsp/handler/impl/ChainingLogoutInitiator.cpp
index a5031fb..63e9580 100644
--- a/shibsp/handler/impl/ChainingLogoutInitiator.cpp
+++ b/shibsp/handler/impl/ChainingLogoutInitiator.cpp
@@ -76,7 +76,7 @@ namespace shibsp {
     {
     public:
         FilterAction acceptNode(const DOMNode* node) const {
-            if (XMLHelper::isNodeNamed(node,shibspconstants::SHIB2SPCONFIG_NS,_LogoutInitiator))
+            if (XMLString::equals(node->getLocalName(), _LogoutInitiator))
                 return FILTER_REJECT;
             return FILTER_ACCEPT;
         }
diff --git a/shibsp/handler/impl/ChainingSessionInitiator.cpp b/shibsp/handler/impl/ChainingSessionInitiator.cpp
index 4a1984a..eaca81b 100644
--- a/shibsp/handler/impl/ChainingSessionInitiator.cpp
+++ b/shibsp/handler/impl/ChainingSessionInitiator.cpp
@@ -77,7 +77,7 @@ namespace shibsp {
     {
     public:
         FilterAction acceptNode(const DOMNode* node) const {
-            if (XMLHelper::isNodeNamed(node,shibspconstants::SHIB2SPCONFIG_NS,_SessionInitiator))
+            if (XMLString::equals(node->getLocalName(), _SessionInitiator))
                 return FILTER_REJECT;
             return FILTER_ACCEPT;
         }
diff --git a/shibsp/handler/impl/SAML2ArtifactResolution.cpp b/shibsp/handler/impl/SAML2ArtifactResolution.cpp
index 8001949..0d3576d 100644
--- a/shibsp/handler/impl/SAML2ArtifactResolution.cpp
+++ b/shibsp/handler/impl/SAML2ArtifactResolution.cpp
@@ -88,7 +88,7 @@ namespace shibsp {
             // Initial guess at index to use.
             pair<bool,unsigned int> ix = pair<bool,unsigned int>(false,0);
             if (!strncmp(handlerURL, "https", 5))
-                ix = getUnsignedInt("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS);
+                ix = getUnsignedInt("sslIndex", shibspconstants::ASCII_SHIBSPCONFIG_NS);
             if (!ix.first)
                 ix = getUnsignedInt("index");
             if (!ix.first)
@@ -146,16 +146,8 @@ SAML2ArtifactResolution::SAML2ArtifactResolution(const DOMElement* e, const char
 {
 #ifndef SHIBSP_LITE
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-        m_encoder.reset(
-            SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
-                getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
-                )
-            );
-        m_decoder.reset(
-            SAMLConfig::getConfig().MessageDecoderManager.newPlugin(
-                getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
-                )
-            );
+        m_encoder.reset(SAMLConfig::getConfig().MessageEncoderManager.newPlugin(getString("Binding").second, e));
+        m_decoder.reset(SAMLConfig::getConfig().MessageDecoderManager.newPlugin(getString("Binding").second, e));
     }
 #endif
     string address(appId);
@@ -193,7 +185,7 @@ pair<bool,long> SAML2ArtifactResolution::run(SPRequest& request, bool isHandler)
         code->setCode(&Faultcode::SERVER);
         Faultstring* fs = FaultstringBuilder::buildFaultstring();
         fault->setFaultstring(fs);
-        pair<bool,bool> flag = getBool("detailedErrors", m_configNS.get());
+        pair<bool,bool> flag = getBool("detailedErrors", shibspconstants::ASCII_SHIBSPCONFIG_NS);
         auto_ptr_XMLCh msg((flag.first && flag.second) ? ex.what() : "Error processing request.");
         fs->setString(msg.get());
 #ifndef SHIBSP_LITE
@@ -255,7 +247,7 @@ void SAML2ArtifactResolution::receive(DDF& in, ostream& out)
         code->setCode(&Faultcode::SERVER);
         Faultstring* fs = FaultstringBuilder::buildFaultstring();
         fault->setFaultstring(fs);
-        pair<bool,bool> flag = getBool("detailedErrors", m_configNS.get());
+        pair<bool,bool> flag = getBool("detailedErrors", shibspconstants::ASCII_SHIBSPCONFIG_NS);
         auto_ptr_XMLCh msg((flag.first && flag.second) ? ex.what() : "Error processing request.");
         fs->setString(msg.get());
         m_encoder->encode(*resp, fault.get(), nullptr);
@@ -277,7 +269,7 @@ pair<bool,long> SAML2ArtifactResolution::processMessage(const Application& appli
         throw ConfigurationException("No ArtifactMap instance installed.");
 
     // Locate policy key.
-    pair<bool,const char*> policyId = getString("policyId", m_configNS.get());  // namespace-qualified if inside handler element
+    pair<bool,const char*> policyId = getString("policyId", shibspconstants::ASCII_SHIBSPCONFIG_NS);  // namespace-qualified if inside handler element
     if (!policyId.first)
         policyId = application.getString("policyId");   // unqualified in Application(s) element
         
diff --git a/shibsp/handler/impl/SAML2Logout.cpp b/shibsp/handler/impl/SAML2Logout.cpp
index 389e18a..8e09301 100644
--- a/shibsp/handler/impl/SAML2Logout.cpp
+++ b/shibsp/handler/impl/SAML2Logout.cpp
@@ -161,17 +161,13 @@ SAML2Logout::SAML2Logout(const DOMElement* e, const char* appId)
         SAMLConfig& conf = SAMLConfig::getConfig();
 
         // Handle incoming binding.
-        m_decoder.reset(
-            conf.MessageDecoderManager.newPlugin(
-                getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
-                )
-            );
+        m_decoder.reset(conf.MessageDecoderManager.newPlugin(getString("Binding").second, e));
         m_decoder->setArtifactResolver(SPConfig::getConfig().getArtifactResolver());
 
         if (m_decoder->isUserAgentPresent()) {
             // Handle front-channel binding setup.
             string dupBindings;
-            pair<bool,const char*> outgoing = getString("outgoingBindings", m_configNS.get());
+            pair<bool,const char*> outgoing = getString("outgoingBindings", shibspconstants::ASCII_SHIBSPCONFIG_NS);
             if (outgoing.first) {
                 dupBindings = outgoing.second;
                 trim(dupBindings);
@@ -185,9 +181,7 @@ SAML2Logout::SAML2Logout(const DOMElement* e, const char* appId)
             split(m_bindings, dupBindings, is_space(), algorithm::token_compress_on);
             for (vector<string>::const_iterator b = m_bindings.begin(); b != m_bindings.end(); ++b) {
                 try {
-                    boost::shared_ptr<MessageEncoder> encoder(
-                        conf.MessageEncoderManager.newPlugin(*b, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS))
-                        );
+                    boost::shared_ptr<MessageEncoder> encoder(conf.MessageEncoderManager.newPlugin(*b, e));
                     if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
                         m_encoders[*b] = encoder;
                         m_log.debug("supporting outgoing binding (%s)", b->c_str());
@@ -203,9 +197,7 @@ SAML2Logout::SAML2Logout(const DOMElement* e, const char* appId)
         }
         else {
             pair<bool,const char*> b = getString("Binding");
-            boost::shared_ptr<MessageEncoder> encoder(
-                conf.MessageEncoderManager.newPlugin(b.second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS))
-                );
+            boost::shared_ptr<MessageEncoder> encoder(conf.MessageEncoderManager.newPlugin(b.second, e));
             m_encoders[b.second] = encoder;
         }
     }
@@ -354,7 +346,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
     // If we get here, it's an external protocol message to decode.
 
     // Locate policy key.
-    pair<bool,const char*> policyId = getString("policyId", m_configNS.get());  // may be namespace-qualified inside handler element
+    pair<bool,const char*> policyId = getString("policyId", shibspconstants::ASCII_SHIBSPCONFIG_NS);  // may be namespace-qualified inside handler element
     if (!policyId.first)
         policyId = getString("policyId");   // try unqualified
     if (!policyId.first)
diff --git a/shibsp/handler/impl/SAML2LogoutInitiator.cpp b/shibsp/handler/impl/SAML2LogoutInitiator.cpp
index d70a991..2af104c 100644
--- a/shibsp/handler/impl/SAML2LogoutInitiator.cpp
+++ b/shibsp/handler/impl/SAML2LogoutInitiator.cpp
@@ -171,9 +171,7 @@ void SAML2LogoutInitiator::init(const char* location)
         split(m_bindings, dupBindings, is_space(), algorithm::token_compress_on);
         for (vector<string>::const_iterator b = m_bindings.begin(); b != m_bindings.end(); ++b) {
             try {
-                boost::shared_ptr<MessageEncoder> encoder(
-                    SAMLConfig::getConfig().MessageEncoderManager.newPlugin(*b, pair<const DOMElement*,const XMLCh*>(getElement(),nullptr))
-                    );
+                boost::shared_ptr<MessageEncoder> encoder(SAMLConfig::getConfig().MessageEncoderManager.newPlugin(*b, getElement()));
                 if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
                     m_encoders[*b] = encoder;
                     m_log.debug("supporting outgoing binding (%s)", b->c_str());
diff --git a/shibsp/handler/impl/SAML2NameIDMgmt.cpp b/shibsp/handler/impl/SAML2NameIDMgmt.cpp
index 273c2cd..4a7fe7d 100644
--- a/shibsp/handler/impl/SAML2NameIDMgmt.cpp
+++ b/shibsp/handler/impl/SAML2NameIDMgmt.cpp
@@ -148,17 +148,13 @@ SAML2NameIDMgmt::SAML2NameIDMgmt(const DOMElement* e, const char* appId)
         SAMLConfig& conf = SAMLConfig::getConfig();
 
         // Handle incoming binding.
-        m_decoder.reset(
-            conf.MessageDecoderManager.newPlugin(
-                getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
-                )
-            );
+        m_decoder.reset(conf.MessageDecoderManager.newPlugin(getString("Binding").second, e));
         m_decoder->setArtifactResolver(SPConfig::getConfig().getArtifactResolver());
 
         if (m_decoder->isUserAgentPresent()) {
             // Handle front-channel binding setup.
             string dupBindings;
-            pair<bool,const char*> outgoing = getString("outgoingBindings", m_configNS.get());
+            pair<bool,const char*> outgoing = getString("outgoingBindings", shibspconstants::ASCII_SHIBSPCONFIG_NS);
             if (outgoing.first) {
                 dupBindings = outgoing.second;
                 trim(dupBindings);
@@ -172,9 +168,7 @@ SAML2NameIDMgmt::SAML2NameIDMgmt(const DOMElement* e, const char* appId)
             split(m_bindings, dupBindings, is_space(), algorithm::token_compress_on);
             for (vector<string>::const_iterator b = m_bindings.begin(); b != m_bindings.end(); ++b) {
                 try {
-                    boost::shared_ptr<MessageEncoder> encoder(
-                        conf.MessageEncoderManager.newPlugin(*b, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS))
-                        );
+                    boost::shared_ptr<MessageEncoder> encoder(conf.MessageEncoderManager.newPlugin(*b, e));
                     if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
                         m_encoders[*b] = encoder;
                         m_log.debug("supporting outgoing binding (%s)", b->c_str());
@@ -190,9 +184,7 @@ SAML2NameIDMgmt::SAML2NameIDMgmt(const DOMElement* e, const char* appId)
         }
         else {
             pair<bool,const char*> b = getString("Binding");
-            boost::shared_ptr<MessageEncoder> encoder(
-                conf.MessageEncoderManager.newPlugin(b.second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS))
-                );
+            boost::shared_ptr<MessageEncoder> encoder(conf.MessageEncoderManager.newPlugin(b.second, e));
             m_encoders[b.second] = encoder;
         }
     }
@@ -253,7 +245,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(const Application& application, const
     SessionCache* cache = application.getServiceProvider().getSessionCache();
 
     // Locate policy key.
-    pair<bool,const char*> policyId = getString("policyId", m_configNS.get());  // may be namespace-qualified inside handler element
+    pair<bool,const char*> policyId = getString("policyId", shibspconstants::ASCII_SHIBSPCONFIG_NS);  // may be namespace-qualified inside handler element
     if (!policyId.first)
         policyId = getString("policyId");   // try unqualified
     if (!policyId.first)
diff --git a/shibsp/handler/impl/SAML2SessionInitiator.cpp b/shibsp/handler/impl/SAML2SessionInitiator.cpp
index b89d588..e526867 100644
--- a/shibsp/handler/impl/SAML2SessionInitiator.cpp
+++ b/shibsp/handler/impl/SAML2SessionInitiator.cpp
@@ -149,7 +149,7 @@ namespace shibsp {
 };
 
 SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* appId)
-    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.SAML2"), &g_SINFilter, &m_remapper), m_appId(appId),
+    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.SAML2"), &g_SINFilter, this), m_appId(appId),
         m_paosNS(samlconstants::PAOS_NS), m_ecpNS(samlconstants::SAML20ECP_NS), m_paosBinding(samlconstants::SAML20_BINDING_PAOS)
 #ifdef SHIBSP_LITE
         ,m_ecp(false)
@@ -199,11 +199,7 @@ void SAML2SessionInitiator::init(const char* location)
         // If directed, build an ECP encoder.
         if (flag.first && flag.second) {
             try {
-                m_ecp.reset(
-                    SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
-                        samlconstants::SAML20_BINDING_PAOS, pair<const DOMElement*,const XMLCh*>(getElement(), nullptr)
-                        )
-                    );
+                m_ecp.reset(SAMLConfig::getConfig().MessageEncoderManager.newPlugin(samlconstants::SAML20_BINDING_PAOS, getElement()));
             }
             catch (std::exception& ex) {
                 m_log.error("error building PAOS/ECP MessageEncoder: %s", ex.what());
@@ -224,9 +220,7 @@ void SAML2SessionInitiator::init(const char* location)
         split(m_bindings, dupBindings, is_space(), algorithm::token_compress_on);
         for (vector<string>::const_iterator b = m_bindings.begin(); b != m_bindings.end(); ++b) {
             try {
-                boost::shared_ptr<MessageEncoder> encoder(
-                    SAMLConfig::getConfig().MessageEncoderManager.newPlugin(*b, pair<const DOMElement*,const XMLCh*>(getElement(),nullptr))
-                    );
+                boost::shared_ptr<MessageEncoder> encoder(SAMLConfig::getConfig().MessageEncoderManager.newPlugin(*b, getElement()));
                 if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
                     m_encoders[*b] = encoder;
                     m_log.debug("supporting outgoing binding (%s)", b->c_str());
@@ -383,7 +377,7 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
             // Determine index to use.
             pair<bool,const XMLCh*> ix = pair<bool,const XMLCh*>(false,nullptr);
             if (!strncmp(ACSloc.c_str(), "https://", 8)) {
-            	ix = ACS->getXMLString("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS);
+            	ix = ACS->getXMLString("sslIndex", shibspconstants::ASCII_SHIBSPCONFIG_NS);
             	if (!ix.first)
             		ix = ACS->getXMLString("index");
             }
@@ -460,7 +454,7 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         // Determine index to use.
         pair<bool,const char*> ix = pair<bool,const char*>(false,nullptr);
         if (!strncmp(ACSloc.c_str(), "https://", 8)) {
-        	ix = ACS->getString("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS);
+        	ix = ACS->getString("sslIndex", shibspconstants::ASCII_SHIBSPCONFIG_NS);
         	if (!ix.first)
         		ix = ACS->getString("index");
         }
diff --git a/shibsp/handler/impl/SecuredHandler.cpp b/shibsp/handler/impl/SecuredHandler.cpp
index 194917f..79d4c42 100644
--- a/shibsp/handler/impl/SecuredHandler.cpp
+++ b/shibsp/handler/impl/SecuredHandler.cpp
@@ -54,7 +54,7 @@ SecuredHandler::SecuredHandler(
     const char* aclProperty,
     const char* defaultACL,
     DOMNodeFilter* filter,
-    const map<string,string>* remapper
+    const Remapper* remapper
     ) : AbstractHandler(e, log, filter ? filter : &g_Blocker, remapper)
 {
     if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
diff --git a/shibsp/handler/impl/SessionInitiator.cpp b/shibsp/handler/impl/SessionInitiator.cpp
index f5280c8..ca682db 100644
--- a/shibsp/handler/impl/SessionInitiator.cpp
+++ b/shibsp/handler/impl/SessionInitiator.cpp
@@ -50,8 +50,6 @@ namespace shibsp {
     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory CookieSessionInitiatorFactory;
 };
 
-map<string,string> SessionInitiator::m_remapper;
-
 void SHIBSP_API shibsp::registerSessionInitiators()
 {
     SPConfig& conf=SPConfig::getConfig();
@@ -63,8 +61,6 @@ void SHIBSP_API shibsp::registerSessionInitiators()
     conf.SessionInitiatorManager.registerFactory(TRANSFORM_SESSION_INITIATOR, TransformSessionInitiatorFactory);
     conf.SessionInitiatorManager.registerFactory(FORM_SESSION_INITIATOR, FormSessionInitiatorFactory);
     conf.SessionInitiatorManager.registerFactory(COOKIE_SESSION_INITIATOR, CookieSessionInitiatorFactory);
-
-    SessionInitiator::m_remapper["defaultACSIndex"] = "acsIndex";
 }
 
 SessionInitiator::SessionInitiator()
@@ -75,6 +71,17 @@ SessionInitiator::~SessionInitiator()
 {
 }
 
+const char* SessionInitiator::remap(const char* src, Category& log) const
+{
+    if (XMLString::equals(src, "defaultACSIndex")) {
+        log.warn("DEPRECATED configuration - remapping property/set (%s) to (%s)", src, "acsIndex");
+        return "acsIndex";
+    }
+    else {
+        return src;
+    }
+}
+
 const char* SessionInitiator::getEventType() const {
     return LOGIN_EVENT;
 }
diff --git a/shibsp/handler/impl/Shib1SessionInitiator.cpp b/shibsp/handler/impl/Shib1SessionInitiator.cpp
index cd35d07..83acb1d 100644
--- a/shibsp/handler/impl/Shib1SessionInitiator.cpp
+++ b/shibsp/handler/impl/Shib1SessionInitiator.cpp
@@ -64,7 +64,7 @@ namespace shibsp {
     {
     public:
         Shib1SessionInitiator(const DOMElement* e, const char* appId)
-                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.Shib1"), nullptr, &m_remapper), m_appId(appId) {
+                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.Shib1"), nullptr, this), m_appId(appId) {
             // If Location isn't set, defer address registration until the setParent call.
             pair<bool,const char*> loc = getString("Location");
             if (loc.first) {
diff --git a/shibsp/handler/impl/WAYFSessionInitiator.cpp b/shibsp/handler/impl/WAYFSessionInitiator.cpp
index b04f018..e26f18d 100644
--- a/shibsp/handler/impl/WAYFSessionInitiator.cpp
+++ b/shibsp/handler/impl/WAYFSessionInitiator.cpp
@@ -59,7 +59,7 @@ namespace shibsp {
     {
     public:
         WAYFSessionInitiator(const DOMElement* e, const char* appId)
-                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.WAYF"), nullptr, &m_remapper), m_url(nullptr) {
+                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.WAYF"), nullptr, this), m_url(nullptr) {
             pair<bool,const char*> url = getString("URL");
             if (!url.first)
                 throw ConfigurationException("WAYF SessionInitiator requires a URL property.");
diff --git a/shibsp/impl/XMLRequestMapper.cpp b/shibsp/impl/XMLRequestMapper.cpp
index 4069f31..ae3dae0 100644
--- a/shibsp/impl/XMLRequestMapper.cpp
+++ b/shibsp/impl/XMLRequestMapper.cpp
@@ -45,7 +45,6 @@
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xercesc/util/regx/RegularExpression.hpp>
 
-using shibspconstants::SHIB2SPCONFIG_NS;
 using namespace shibsp;
 using namespace xmltooling;
 using namespace boost;
@@ -256,7 +255,7 @@ Override::Override(bool unicodeAware, const DOMElement* e, Category& log, const
 
             if (*n) {
                 // Create a placeholder Path element for the first path segment and replant under it.
-                DOMElement* newpath = path->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, Path);
+                DOMElement* newpath = path->getOwnerDocument()->createElementNS(path->getNamespaceURI(), Path);
                 newpath->setAttributeNS(nullptr, name, namebuf.c_str());
                 path->setAttributeNS(nullptr, name, n);
                 path->getParentNode()->replaceChild(newpath, path);
@@ -466,8 +465,14 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
 #endif
     static const XMLCh _RequestMap[] =  UNICODE_LITERAL_10(R,e,q,u,e,s,t,M,a,p);
 
-    if (e && !XMLHelper::isNodeNamed(e, SHIB2SPCONFIG_NS, _RequestMap))
+    if (e && !XMLHelper::isNodeNamed(e, shibspconstants::SHIB2SPCONFIG_NS, _RequestMap)
+          && !XMLHelper::isNodeNamed(e, shibspconstants::SHIB3SPCONFIG_NS, _RequestMap)) {
         throw ConfigurationException("XML RequestMapper requires conf:RequestMap at root of configuration.");
+    }
+
+    if (XMLString::equals(e->getNamespaceURI(), shibspconstants::SHIB2SPCONFIG_NS)) {
+        log.warn("detected legacy 2.0 configuration, support will be removed from a future version of the software");
+    }
 
     // Load the property set.
     load(e, nullptr, this);
diff --git a/shibsp/impl/XMLSecurityPolicyProvider.cpp b/shibsp/impl/XMLSecurityPolicyProvider.cpp
index 8efc65b..6c58de6 100644
--- a/shibsp/impl/XMLSecurityPolicyProvider.cpp
+++ b/shibsp/impl/XMLSecurityPolicyProvider.cpp
@@ -45,7 +45,6 @@
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xsec/dsig/DSIGConstants.hpp>
 
-using shibspconstants::SHIB2SPCONFIG_NS;
 using opensaml::SAMLConfig;
 using opensaml::SecurityPolicyRule;
 using namespace shibsp;
@@ -197,8 +196,14 @@ XMLSecurityPolicyProviderImpl::XMLSecurityPolicyProviderImpl(const DOMElement* e
     xmltooling::NDC ndc("XMLSecurityPolicyProviderImpl");
 #endif
 
-    if (!XMLHelper::isNodeNamed(e, SHIB2SPCONFIG_NS, SecurityPolicies))
+    if (!XMLHelper::isNodeNamed(e, shibspconstants::SHIB2SPCONFIG_NS, SecurityPolicies) &&
+        !XMLHelper::isNodeNamed(e, shibspconstants::SHIB3SPCONFIG_NS, SecurityPolicies)) {
         throw ConfigurationException("XML SecurityPolicyProvider requires conf:SecurityPolicies at root of configuration.");
+    }
+
+    if (XMLString::equals(e->getNamespaceURI(), shibspconstants::SHIB2SPCONFIG_NS)) {
+        log.warn("detected legacy 2.0 configuration, support will be removed from a future version of the software");
+    }
 
     const XMLCh* algs = nullptr;
     const DOMElement* alglist = XMLHelper::getLastChildElement(e, AlgorithmBlacklist);
diff --git a/shibsp/impl/XMLServiceProvider.cpp b/shibsp/impl/XMLServiceProvider.cpp
index 5a78b60..2426478 100644
--- a/shibsp/impl/XMLServiceProvider.cpp
+++ b/shibsp/impl/XMLServiceProvider.cpp
@@ -115,7 +115,8 @@ namespace {
     static vector<const Handler*> g_noHandlers;
 
     // Application configuration wrapper
-    class SHIBSP_DLLLOCAL XMLApplication : public Application, public Remoted, public DOMPropertySet, public DOMNodeFilter
+    class SHIBSP_DLLLOCAL XMLApplication
+        : public Application, public Remoted, public DOMPropertySet, public DOMNodeFilter
     {
     public:
         XMLApplication(const ServiceProvider*, const ProtocolProvider*, DOMElement*, const XMLApplication* base=nullptr);
@@ -331,6 +332,10 @@ namespace {
             background_load();
         }
 
+        const XMLCh* getConfigurationNamespace() const {
+            return m_impl ? m_impl->getElement()->getNamespaceURI() : nullptr;
+        }
+
         ~XMLConfig() {
             shutdown();
 #ifndef SHIBSP_LITE
@@ -363,7 +368,7 @@ namespace {
         pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const {return m_impl->getUnsignedInt(name,ns);}
         pair<bool,int> getInt(const char* name, const char* ns=nullptr) const {return m_impl->getInt(name,ns);}
         void getAll(map<string,const char*>& properties) const {return m_impl->getAll(properties);}
-        const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:2.0:native:sp:config") const {return m_impl->getPropertySet(name,ns);}
+        const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const {return m_impl->getPropertySet(name,ns);}
         const DOMElement* getElement() const {return m_impl->getElement();}
 
         // ServiceProvider
@@ -529,9 +534,11 @@ XMLApplication::XMLApplication(
     Category& log = Category::getInstance(SHIBSP_LOGCAT ".Application");
 
     // First load any property sets.
-    map<string,string> remapper;
-    remapper["relayStateLimit"] = "redirectLimit";
-    remapper["relayStateWhitelist"] = "redirectWhitelist";
+    map<string,string> remapperMap;
+    remapperMap[shibspconstants::ASCII_SHIB2SPCONFIG_NS] = shibspconstants::ASCII_SHIB3SPCONFIG_NS;
+    remapperMap["relayStateLimit"] = "redirectLimit";
+    remapperMap["relayStateWhitelist"] = "redirectWhitelist";
+    DOMPropertySet::STLRemapper remapper(remapperMap);
     load(e, nullptr, this, &remapper);
 
     // Process redirect limit policy. Do this before assigning the parent pointer
@@ -619,7 +626,7 @@ XMLApplication::XMLApplication(
         doHandlers(pp, e, log);
 
     // Notification.
-    DOMNodeList* nlist = e->getElementsByTagNameNS(shibspconstants::SHIB2SPCONFIG_NS, Notify);
+    DOMNodeList* nlist = e->getElementsByTagNameNS(e->getNamespaceURI(), Notify);
     for (XMLSize_t i = 0; nlist && i < nlist->getLength(); ++i) {
         if (nlist->item(i)->getParentNode()->isSameNode(e)) {
             const XMLCh* channel = static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(nullptr, Channel);
@@ -869,7 +876,7 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
     pair<bool,const char*> location = sessions ? sessions->getString("exportLocation") : pair<bool,const char*>(false,nullptr);
     if (location.first) {
         try {
-            DOMElement* exportElement = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, _Handler);
+            DOMElement* exportElement = e->getOwnerDocument()->createElementNS(e->getNamespaceURI(), _Handler);
             exportElement->setAttributeNS(nullptr,Location,sessions->getXMLString("exportLocation").second);
             pair<bool,const XMLCh*> exportACL = sessions->getXMLString("exportACL");
             if (exportACL.first) {
@@ -902,19 +909,19 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
     set<string> protocols;
     DOMElement* child = sessions ? XMLHelper::getFirstChildElement(sessions->getElement()) : nullptr;
     while (child) {
-        if (XMLHelper::isNodeNamed(child, shibspconstants::SHIB2SPCONFIG_NS, SSO)) {
+        if (XMLHelper::isNodeNamed(child, sessions->getElement()->getNamespaceURI(), SSO)) {
             if (pp)
                 doSSO(*pp, protocols, child, log);
             else
                 log.error("no ProtocolProvider, SSO auto-configure unsupported");
         }
-        else if (XMLHelper::isNodeNamed(child, shibspconstants::SHIB2SPCONFIG_NS, Logout)) {
+        else if (XMLHelper::isNodeNamed(child, sessions->getElement()->getNamespaceURI(), Logout)) {
             if (pp)
                 doLogout(*pp, protocols, child, log);
             else
                 log.error("no ProtocolProvider, Logout auto-configure unsupported");
         }
-        else if (XMLHelper::isNodeNamed(child, shibspconstants::SHIB2SPCONFIG_NS, NameIDMgmt)) {
+        else if (XMLHelper::isNodeNamed(child, sessions->getElement()->getNamespaceURI(), NameIDMgmt)) {
             if (pp)
                 doNameIDMgmt(*pp, protocols, child, log);
             else
@@ -1089,7 +1096,7 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set<string>& protocols, D
             pair<bool,const XMLCh*> inittype = initiator->getXMLString("id");
             if (inittype.first) {
                 // Append a session initiator element of the designated type to the root element.
-                DOMElement* sidom = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, _SessionInitiator);
+                DOMElement* sidom = e->getOwnerDocument()->createElementNS(e->getNamespaceURI(), _SessionInitiator);
                 sidom->setAttributeNS(nullptr, _type, inittype.second);
                 e->appendChild(sidom);
                 log.info("adding SessionInitiator of type (%s) to chain (/Login)", initiator->getString("id").second);
@@ -1177,7 +1184,7 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set<string>& protocols, D
         const XMLCh* discou = e->getAttributeNS(nullptr, discoveryURL);
         if (discou && *discou) {
             // Append a session initiator element of the designated type to the root element.
-            DOMElement* sidom = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, _SessionInitiator);
+            DOMElement* sidom = e->getOwnerDocument()->createElementNS(e->getNamespaceURI(), _SessionInitiator);
             sidom->setAttributeNS(nullptr, _type, discop);
             sidom->setAttributeNS(nullptr, _URL, discou);
             e->appendChild(sidom);
@@ -1225,7 +1232,7 @@ void XMLApplication::doLogout(const ProtocolProvider& pp, set<string>& protocols
             pair<bool,const XMLCh*> inittype = initiator->getXMLString("id");
             if (inittype.first) {
                 // Append a logout initiator element of the designated type to the root element.
-                DOMElement* lidom = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, _LogoutInitiator);
+                DOMElement* lidom = e->getOwnerDocument()->createElementNS(e->getNamespaceURI(), _LogoutInitiator);
                 lidom->setAttributeNS(nullptr, _type, inittype.second);
                 e->appendChild(lidom);
                 log.info("adding LogoutInitiator of type (%s) to chain (/Logout)", initiator->getString("id").second);
@@ -1267,7 +1274,7 @@ void XMLApplication::doLogout(const ProtocolProvider& pp, set<string>& protocols
                     slodom->setAttributeNS(nullptr, Binding, idprop.second);
                     slodom->setAttributeNS(nullptr, Location, pathprop.second);
                     if (e->hasAttributeNS(nullptr, _policyId))
-                        slodom->setAttributeNS(shibspconstants::SHIB2SPCONFIG_NS, _policyId, e->getAttributeNS(nullptr, _policyId));
+                        slodom->setAttributeNS(e->getNamespaceURI(), _policyId, e->getAttributeNS(nullptr, _policyId));
 
                     log.info("adding SingleLogoutService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
                     boost::shared_ptr<Handler> handler(
@@ -1351,7 +1358,7 @@ void XMLApplication::doNameIDMgmt(const ProtocolProvider& pp, set<string>& proto
                     nimdom->setAttributeNS(nullptr, Binding, idprop.second);
                     nimdom->setAttributeNS(nullptr, Location, pathprop.second);
                     if (e->hasAttributeNS(nullptr, _policyId))
-                        nimdom->setAttributeNS(shibspconstants::SHIB2SPCONFIG_NS, _policyId, e->getAttributeNS(nullptr, _policyId));
+                        nimdom->setAttributeNS(e->getNamespaceURI(), _policyId, e->getAttributeNS(nullptr, _policyId));
 
                     log.info("adding ManageNameIDService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
                     boost::shared_ptr<Handler> handler(
@@ -1814,7 +1821,8 @@ void XMLApplication::limitRedirect(const GenericRequest& request, const char* ur
 
 DOMNodeFilter::FilterAction XMLConfigImpl::acceptNode(const DOMNode* node) const
 {
-    if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB2SPCONFIG_NS))
+    if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB2SPCONFIG_NS)
+            && !XMLString::equals(node->getNamespaceURI(), shibspconstants::SHIB3SPCONFIG_NS))
         return FILTER_ACCEPT;
     const XMLCh* name=node->getLocalName();
     if (XMLString::equals(name,ApplicationDefaults) ||
@@ -2057,6 +2065,10 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer,
         );
 #endif
 
+    if (XMLString::equals(e->getNamespaceURI(), shibspconstants::SHIB2SPCONFIG_NS)) {
+        log.warn("detected legacy 2.0 configuration, support will be removed from a future version of the software");
+    }
+
     // First load any property sets.
     load(e, nullptr, this);
 
@@ -2128,7 +2140,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer,
         if (!m_requestMapper) {
             log.info("no RequestMapper specified, using 'Native' plugin with empty/default map");
             child = e->getOwnerDocument()->createElementNS(nullptr, _RequestMapper);
-            DOMElement* mapperDummy = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, RequestMap);
+            DOMElement* mapperDummy = e->getOwnerDocument()->createElementNS(e->getNamespaceURI(), RequestMap);
             mapperDummy->setAttributeNS(nullptr, applicationId, _default);
             child->appendChild(mapperDummy);
             m_requestMapper.reset(conf.RequestMapperManager.newPlugin(NATIVE_REQUEST_MAPPER, child));
diff --git a/shibsp/util/DOMPropertySet.cpp b/shibsp/util/DOMPropertySet.cpp
index 54a5c39..58d9f4e 100644
--- a/shibsp/util/DOMPropertySet.cpp
+++ b/shibsp/util/DOMPropertySet.cpp
@@ -46,6 +46,34 @@ PropertySet::~PropertySet()
 {
 }
 
+DOMPropertySet::Remapper::Remapper()
+{
+}
+
+DOMPropertySet::Remapper::~Remapper()
+{
+}
+
+DOMPropertySet::STLRemapper::STLRemapper(const std::map<std::string, std::string>& rules) : m_rules(rules)
+{
+}
+
+DOMPropertySet::STLRemapper::~STLRemapper()
+{
+}
+
+const char* DOMPropertySet::STLRemapper::remap(const char* src, xmltooling::logging::Category& log) const
+{
+    map<string,string>::const_iterator i = src ? m_rules.find(src) : m_rules.end();
+    if (i != m_rules.end()) {
+        log.warn("DEPRECATED configuration - remapping property/set (%s) to (%s)", src, i->second.c_str());
+        return i->second.c_str();
+    }
+    else {
+        return src;
+    }
+}
+
 DOMPropertySet::DOMPropertySet() : m_parent(nullptr), m_root(nullptr)
 {
 }
@@ -75,7 +103,7 @@ void DOMPropertySet::load(
     const DOMElement* e,
     Category* log,
     DOMNodeFilter* filter,
-    const std::map<std::string,std::string>* remapper
+    const Remapper* remapper
     )
 {
 #ifdef _DEBUG
@@ -98,24 +126,23 @@ void DOMPropertySet::load(
             auto_ptr_char ns(a->getNamespaceURI());
             auto_ptr_char name(a->getLocalName());
             const char* realname=name.get();
-            map<string,string>::const_iterator remap;
             if (remapper) {
-                remap=remapper->find(realname);
-                if (remap!=remapper->end()) {
-                    log->warn("deprecation - remapping property (%s) to (%s)",realname,remap->second.c_str());
-                    realname=remap->second.c_str();
-                }
+                realname = remapper->remap(realname, *log);
             }
             if (ns.get()) {
-                if (remapper && (remap=remapper->find(ns.get()))!=remapper->end())
-                    m_map[string("{") + remap->second.c_str() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
-                else
-                    m_map[string("{") + ns.get() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
-                log->debug("added property {%s}%s (%s)",ns.get(),realname,val);
+                const char* realns = ns.get();
+                if (remapper) {
+                    realns = remapper->remap(realns, *log);
+                }
+                else if (XMLString::equals(realns, shibspconstants::ASCII_SHIB2SPCONFIG_NS)) {
+                    realns = shibspconstants::ASCII_SHIB3SPCONFIG_NS;
+                }
+                m_map[string("{") + realns + '}' + realname] = pair<char*, const XMLCh*>(val, a->getNodeValue());
+                log->debug("added property {%s}%s (%s)", realns, realname, val);
             }
             else {
                 m_map[realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
-                log->debug("added property %s (%s)",realname,val);
+                log->debug("added property %s (%s)", realname, val);
             }
         }
     }
@@ -130,23 +157,23 @@ void DOMPropertySet::load(
         auto_ptr_char ns(e->getNamespaceURI());
         auto_ptr_char name(e->getLocalName());
         const char* realname=name.get();
-        map<string,string>::const_iterator remap;
         if (remapper) {
-            remap = remapper->find(realname);
-            if (remap != remapper->end()) {
-                log->warn("deprecation - remapping nested property set (%s) to (%s)", realname, remap->second.c_str());
-                realname = remap->second.c_str();
-            }
+            realname = remapper->remap(realname, *log);
         }
         string key;
         if (ns.get()) {
-            if (remapper && (remap = remapper->find(ns.get())) != remapper->end())
-                key = string("{") + remap->second.c_str() + '}' + realname;
-            else
-                key = string("{") + ns.get() + '}' + realname;
+            const char* realns = ns.get();
+            if (remapper) {
+                realns = remapper->remap(realns, *log);
+            }
+            else if (XMLString::equals(realns, shibspconstants::ASCII_SHIB2SPCONFIG_NS)) {
+                realns = shibspconstants::ASCII_SHIB3SPCONFIG_NS;
+            }
+            key = string("{") + realns + '}' + realname;
         }
-        else
+        else {
             key = realname;
+        }
         if (m_nested.find(key) != m_nested.end())
             log->warn("load() skipping duplicate property set: %s", key.c_str());
         else {
diff --git a/shibsp/util/DOMPropertySet.h b/shibsp/util/DOMPropertySet.h
index 91b8498..016e65c 100644
--- a/shibsp/util/DOMPropertySet.h
+++ b/shibsp/util/DOMPropertySet.h
@@ -52,22 +52,65 @@ namespace shibsp {
         std::pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const;
         std::pair<bool,int> getInt(const char* name, const char* ns=nullptr) const;
         void getAll(std::map<std::string,const char*>& properties) const;
-        const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIB2SPCONFIG_NS) const;
+        const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const;
         const xercesc::DOMElement* getElement() const;
 
         /**
+         * Interface that remaps property names for legacy support.
+         */
+        class SHIBSP_API Remapper {
+            MAKE_NONCOPYABLE(Remapper);
+        protected:
+            /** Constructor. */
+            Remapper();
+
+        public:
+            /** Destructor. */
+            virtual ~Remapper();
+
+            /**
+             * Remap a name (or return it unchanged).
+             *
+             * @param src original name
+             * @param log logger to use
+             *
+             * @return the name to use
+             */
+            virtual const char* remap(const char* src, xmltooling::logging::Category& log) const=0;
+        };
+
+        /**
+         * Concrete remapper that relies on an STL map.
+         */
+        class SHIBSP_API STLRemapper : public Remapper {
+        public:
+            /**
+             * Constructor.
+             *
+             * @param rules remapping rules
+             */
+            STLRemapper(const std::map<std::string,std::string>& rules);
+            virtual ~STLRemapper();
+
+            const char* remap(const char* src, xmltooling::logging::Category& log) const;
+
+        private:
+            const std::map<std::string, std::string>& m_rules;
+        };
+
+        /**
          * Loads the property set from a DOM element.
          * 
          * @param e         root element of property set
          * @param log       optional log object for tracing
          * @param filter    optional filter controls what child elements to include as nested PropertySets
-         * @param remapper  optional map of property rename rules for legacy property support
+         * @param remapper  optional mapper of property rename rules for legacy property support
          */
         void load(
             const xercesc::DOMElement* e,
             xmltooling::logging::Category* log=nullptr,
             xercesc::DOMNodeFilter* filter=nullptr,
-            const std::map<std::string,std::string>* remapper=nullptr
+            const Remapper* remapper=nullptr
             );
 
     protected:
diff --git a/shibsp/util/PropertySet.h b/shibsp/util/PropertySet.h
index 773ebd9..68cee60 100644
--- a/shibsp/util/PropertySet.h
+++ b/shibsp/util/PropertySet.h
@@ -119,7 +119,7 @@ namespace shibsp {
          * @param ns    nested property set namespace, or nullptr
          * @return the nested property set, or nullptr
          */        
-        virtual const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIB2SPCONFIG_NS) const=0;
+        virtual const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const=0;
         
         /**
          * Returns a DOM element representing the property container, if any.
diff --git a/shibsp/util/SPConstants.cpp b/shibsp/util/SPConstants.cpp
index bc6c8a5..e7a935b 100644
--- a/shibsp/util/SPConstants.cpp
+++ b/shibsp/util/SPConstants.cpp
@@ -45,6 +45,13 @@ const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0
 
 const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d);
 
+const XMLCh shibspconstants::SHIB3SPCONFIG_NS[] = // urn:mace:shibboleth:3.0:native:sp:config
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+chDigit_3, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon,
+chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull
+};
+
 const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config
 { chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
   chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
@@ -52,6 +59,8 @@ const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:nat
   chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull
 };
 
+const XMLCh* shibspconstants::SHIBSPCONFIG_NS = shibspconstants::SHIB3SPCONFIG_NS;
+
 const XMLCh shibspconstants::SHIB2SPPROTOCOLS_NS[] = // urn:mace:shibboleth:2.0:native:sp:protocols
 { chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
   chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
@@ -132,4 +141,8 @@ const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibbole
 
 const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout";
 
+const char shibspconstants::ASCII_SHIB3SPCONFIG_NS[] = "urn:mace:shibboleth:3.0:native:sp:config";
+
 const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config";
+
+const char* shibspconstants::ASCII_SHIBSPCONFIG_NS = shibspconstants::ASCII_SHIB3SPCONFIG_NS;
diff --git a/shibsp/util/SPConstants.h b/shibsp/util/SPConstants.h
index dac5693..676f9e4 100644
--- a/shibsp/util/SPConstants.h
+++ b/shibsp/util/SPConstants.h
@@ -41,6 +41,12 @@ namespace shibspconstants {
     /** Shibboleth Metadata QName prefix ("shibmd") */
     extern SHIBSP_API const XMLCh SHIBMD_PREFIX[];
 
+    /** "Current" Shibboleth SP configuration namespace */
+    extern SHIBSP_API const XMLCh* SHIBSPCONFIG_NS;
+
+    /** Shibboleth 3.0 SP configuration namespace ("urn:mace:shibboleth:3.0:native:sp:config") */
+    extern SHIBSP_API const XMLCh SHIB3SPCONFIG_NS[];
+
     /** Shibboleth 2.0 SP configuration namespace ("urn:mace:shibboleth:2.0:native:sp:config") */
     extern SHIBSP_API const XMLCh SHIB2SPCONFIG_NS[];
 
@@ -83,6 +89,12 @@ namespace shibspconstants {
     /** Shibboleth 1.3 Local Logout binding/profile ("urn:mace:shibboleth:sp:1.3:Logout") */
     extern SHIBSP_API const char SHIB1_LOGOUT_PROFILE_URI[];
     
+    /** "Current" Shibboleth SP configuration namespace */
+    extern SHIBSP_API const char* ASCII_SHIBSPCONFIG_NS;
+
+    /** Shibboleth 3.0 SP configuration namespace ("urn:mace:shibboleth:3.0:native:sp:config") */
+    extern SHIBSP_API const char ASCII_SHIB3SPCONFIG_NS[];
+
     /** Shibboleth 2.0 SP configuration namespace ("urn:mace:shibboleth:2.0:native:sp:config") */
     extern SHIBSP_API const char ASCII_SHIB2SPCONFIG_NS[];
 };
diff --git a/unittests/TestApplication.h b/unittests/TestApplication.h
index 8735e0c..0e497fc 100644
--- a/unittests/TestApplication.h
+++ b/unittests/TestApplication.h
@@ -53,7 +53,7 @@ namespace ta {
         virtual pair<bool, unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const;
         virtual pair<bool, int> getInt(const char* name, const char* ns=nullptr) const;
         virtual void getAll(std::map<std::string, const char*>& properties) const;
-        virtual const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIB2SPCONFIG_NS) const;
+        virtual const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const;
         virtual const xercesc::DOMElement* getElement() const;
 
     private:

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list