Boost changes
authorScott Cantor <cantor.2@osu.edu>
Tue, 10 Jan 2012 20:55:02 +0000 (20:55 +0000)
committerScott Cantor <cantor.2@osu.edu>
Tue, 10 Jan 2012 20:55:02 +0000 (20:55 +0000)
51 files changed:
shibsp/attribute/filtering/impl/AndMatchFunctor.cpp
shibsp/attribute/filtering/impl/AttributeIssuerRegexFunctor.cpp
shibsp/attribute/filtering/impl/AttributeIssuerStringFunctor.cpp
shibsp/attribute/filtering/impl/AttributeRequesterRegexFunctor.cpp
shibsp/attribute/filtering/impl/AttributeRequesterStringFunctor.cpp
shibsp/attribute/filtering/impl/AttributeScopeMatchesShibMDScopeFunctor.cpp
shibsp/attribute/filtering/impl/AttributeScopeRegexFunctor.cpp
shibsp/attribute/filtering/impl/AttributeScopeStringFunctor.cpp
shibsp/attribute/filtering/impl/AttributeValueRegexFunctor.cpp
shibsp/attribute/filtering/impl/AttributeValueStringFunctor.cpp
shibsp/attribute/filtering/impl/AuthenticationMethodRegexFunctor.cpp
shibsp/attribute/filtering/impl/ChainingAttributeFilter.cpp
shibsp/attribute/filtering/impl/NotMatchFunctor.cpp
shibsp/attribute/filtering/impl/OrMatchFunctor.cpp
shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp
shibsp/attribute/resolver/impl/AssertionAttributeExtractor.cpp
shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp
shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp
shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp
shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp
shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp
shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
shibsp/handler/AssertionConsumerService.h
shibsp/handler/impl/AbstractHandler.cpp
shibsp/handler/impl/AssertionConsumerService.cpp
shibsp/handler/impl/AssertionLookup.cpp
shibsp/handler/impl/ChainingLogoutInitiator.cpp
shibsp/handler/impl/ChainingSessionInitiator.cpp
shibsp/handler/impl/DiscoveryFeed.cpp
shibsp/handler/impl/LocalLogoutInitiator.cpp
shibsp/handler/impl/LogoutHandler.cpp
shibsp/handler/impl/MetadataGenerator.cpp
shibsp/handler/impl/RemotedHandler.cpp
shibsp/handler/impl/SAML1Consumer.cpp
shibsp/handler/impl/SAML2ArtifactResolution.cpp
shibsp/handler/impl/SAML2Consumer.cpp
shibsp/handler/impl/SAML2Logout.cpp
shibsp/handler/impl/SAML2LogoutInitiator.cpp
shibsp/handler/impl/SAML2NameIDMgmt.cpp
shibsp/handler/impl/SAML2SessionInitiator.cpp
shibsp/handler/impl/SAMLDSSessionInitiator.cpp
shibsp/handler/impl/SessionHandler.cpp
shibsp/handler/impl/Shib1SessionInitiator.cpp
shibsp/handler/impl/StatusHandler.cpp
shibsp/handler/impl/TransformSessionInitiator.cpp
shibsp/handler/impl/WAYFSessionInitiator.cpp
shibsp/impl/StorageServiceSessionCache.cpp
shibsp/util/CGIParser.cpp
shibsp/util/DOMPropertySet.cpp
shibsp/util/DOMPropertySet.h

index e2c31a3..3930a6e 100644 (file)
 #include "attribute/filtering/MatchFunctor.h"
 #include "util/SPConstants.h"
 
+#include <boost/scoped_ptr.hpp>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/lambda.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost::lambda;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -50,19 +55,21 @@ namespace shibsp {
         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
             if (m_functors.empty())
                 return false;
-            for (vector<const MatchFunctor*>::const_iterator mf = m_functors.begin(); mf!=m_functors.end(); ++mf)
-                if (!(*mf)->evaluatePolicyRequirement(filterContext))
-                    return false;
-            return true;
+            vector<const MatchFunctor*>::const_iterator i = find_if(
+                m_functors.begin(), m_functors.end(),
+                lambda::bind(&MatchFunctor::evaluatePolicyRequirement, _1, boost::ref(filterContext)) == false
+                );
+            return (i == m_functors.end());
         }
 
         bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const {
             if (m_functors.empty())
                 return false;
-            for (vector<const MatchFunctor*>::const_iterator mf = m_functors.begin(); mf!=m_functors.end(); ++mf)
-                if (!(*mf)->evaluatePermitValue(filterContext, attribute, index))
-                    return false;
-            return true;
+            vector<const MatchFunctor*>::const_iterator i = find_if(
+                m_functors.begin(), m_functors.end(),
+                lambda::bind(&MatchFunctor::evaluatePermitValue, _1, boost::ref(filterContext), boost::ref(attribute), index) == false
+                );
+            return (i == m_functors.end());
         }
 
     private:
@@ -113,11 +120,11 @@ MatchFunctor* AndMatchFunctor::buildFunctor(const DOMElement* e, const FilterPol
     if (!id.empty() && functorMap->getMatchFunctors().count(id))
         id.clear();
 
-    auto_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
-    if (!type.get())
+    scoped_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
+    if (!type)
         throw ConfigurationException("Child Rule found with no xsi:type.");
 
-    MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(functorMap,e));
-    functorMap->getMatchFunctors().insert(multimap<string,MatchFunctor*>::value_type(id, func));
-    return func;
+    auto_ptr<MatchFunctor> func(SPConfig::getConfig().MatchFunctorManager.newPlugin(*type, make_pair(functorMap,e)));
+    functorMap->getMatchFunctors().insert(multimap<string,MatchFunctor*>::value_type(id, func.get()));
+    return func.release();
 }
index 729ba30..c680e8a 100644 (file)
@@ -31,6 +31,7 @@
 #include "attribute/filtering/FilterPolicyContext.h"
 #include "attribute/filtering/MatchFunctor.h"
 
+#include <boost/scoped_ptr.hpp>
 #include <xercesc/util/regx/RegularExpression.hpp>
 
 namespace shibsp {
@@ -44,14 +45,14 @@ namespace shibsp {
      */
     class SHIBSP_DLLLOCAL AttributeIssuerRegexFunctor : public MatchFunctor
     {
-        RegularExpression* m_regex;
+        boost::scoped_ptr<RegularExpression> m_regex;
     public:
-        AttributeIssuerRegexFunctor(const DOMElement* e) : m_regex(nullptr) {
-            const XMLCh* r = e ? e->getAttributeNS(nullptr,regex) : nullptr;
+        AttributeIssuerRegexFunctor(const DOMElement* e) {
+            const XMLCh* r = e ? e->getAttributeNS(nullptr, regex) : nullptr;
             if (!r || !*r)
                 throw ConfigurationException("AttributeIssuerRegex MatchFunctor requires non-empty regex attribute.");
             try {
-                m_regex = new RegularExpression(r, e->getAttributeNS(nullptr,options));
+                m_regex.reset(new RegularExpression(r, e->getAttributeNS(nullptr,options)));
             }
             catch (XMLException& ex) {
                 xmltooling::auto_ptr_char temp(ex.getMessage());
@@ -59,9 +60,7 @@ namespace shibsp {
             }
         }
 
-        virtual ~AttributeIssuerRegexFunctor() {
-            delete m_regex;
-        }
+        virtual ~AttributeIssuerRegexFunctor() {}
 
         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
             return m_regex->matches(filterContext.getAttributeIssuer());
index 39b3648..28a9796 100644 (file)
@@ -46,8 +46,9 @@ namespace shibsp {
         const XMLCh* m_value;
         bool m_ignoreCase;
     public:
-        AttributeIssuerStringFunctor(const DOMElement* e) : m_value(nullptr), m_ignoreCase(XMLHelper::getAttrBool(e, false, ignoreCase)) {
-            m_value = e ? e->getAttributeNS(nullptr,value) : nullptr;
+        AttributeIssuerStringFunctor(const DOMElement* e)
+            : m_value(e ? e->getAttributeNS(nullptr,value) : nullptr),
+                m_ignoreCase(XMLHelper::getAttrBool(e, false, ignoreCase)) {
             if (!m_value || !*m_value)
                 throw ConfigurationException("AttributeIssuerString MatchFunctor requires non-empty value attribute.");
         }
index 0272489..8a18269 100644 (file)
@@ -31,6 +31,7 @@
 #include "attribute/filtering/FilterPolicyContext.h"
 #include "attribute/filtering/MatchFunctor.h"
 
+#include <boost/scoped_ptr.hpp>
 #include <xercesc/util/regx/RegularExpression.hpp>
 
 namespace shibsp {
@@ -44,14 +45,14 @@ namespace shibsp {
      */
     class SHIBSP_DLLLOCAL AttributeRequesterRegexFunctor : public MatchFunctor
     {
-        RegularExpression* m_regex;
+        boost::scoped_ptr<RegularExpression> m_regex;
     public:
-        AttributeRequesterRegexFunctor(const DOMElement* e) : m_regex(nullptr) {
-            const XMLCh* r = e ? e->getAttributeNS(nullptr,regex) : nullptr;
+        AttributeRequesterRegexFunctor(const DOMElement* e) {
+            const XMLCh* r = e ? e->getAttributeNS(nullptr, regex) : nullptr;
             if (!r || !*r)
                 throw ConfigurationException("AttributeRequesterRegex MatchFunctor requires non-empty regex attribute.");
             try {
-                m_regex = new RegularExpression(r, e->getAttributeNS(nullptr,options));
+                m_regex.reset(new RegularExpression(r, e->getAttributeNS(nullptr, options)));
             }
             catch (XMLException& ex) {
                 xmltooling::auto_ptr_char temp(ex.getMessage());
@@ -59,9 +60,7 @@ namespace shibsp {
             }
         }
 
-        virtual ~AttributeRequesterRegexFunctor() {
-            delete m_regex;
-        }
+        virtual ~AttributeRequesterRegexFunctor() {}
 
         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
             return m_regex->matches(filterContext.getAttributeRequester());
index 51a1e6b..db56eea 100644 (file)
@@ -46,8 +46,9 @@ namespace shibsp {
         const XMLCh* m_value;
         bool m_ignoreCase;
     public:
-        AttributeRequesterStringFunctor(const DOMElement* e) : m_value(nullptr), m_ignoreCase(XMLHelper::getAttrBool(e, false, ignoreCase)) {
-            m_value = e ? e->getAttributeNS(nullptr,value) : nullptr;
+        AttributeRequesterStringFunctor(const DOMElement* e)
+                : m_value(e ? e->getAttributeNS(nullptr,value) : nullptr),
+                    m_ignoreCase(XMLHelper::getAttrBool(e, false, ignoreCase)) {
             if (!m_value || !*m_value)
                 throw ConfigurationException("AttributeRequesterString MatchFunctor requires non-empty value attribute.");
         }
index 3556832..c78f0b6 100644 (file)
@@ -62,21 +62,16 @@ namespace shibsp {
             const char* scope = attribute.getScope(index);
             if (!scope || !*scope)
                 return false;
+            auto_arrayptr<XMLCh> widescope(fromUTF8(scope));
 
             const Scope* rule;
-            const XMLCh* widescope=nullptr;
             const Extensions* ext = issuer->getExtensions();
             if (ext) {
                 const vector<XMLObject*>& exts = ext->getUnknownXMLObjects();
-                for (vector<XMLObject*>::const_iterator e = exts.begin(); e!=exts.end(); ++e) {
+                for (vector<XMLObject*>::const_iterator e = exts.begin(); e != exts.end(); ++e) {
                     rule = dynamic_cast<const Scope*>(*e);
-                    if (rule) {
-                        if (!widescope)
-                            widescope = fromUTF8(scope);
-                        if (matches(*rule, widescope)) {
-                            delete[] widescope;
-                            return true;
-                        }
+                    if (rule && matches(*rule, widescope)) {
+                        return true;
                     }
                 }
             }
@@ -84,40 +79,34 @@ namespace shibsp {
             ext = dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getExtensions();
             if (ext) {
                 const vector<XMLObject*>& exts = ext->getUnknownXMLObjects();
-                for (vector<XMLObject*>::const_iterator e = exts.begin(); e!=exts.end(); ++e) {
+                for (vector<XMLObject*>::const_iterator e = exts.begin(); e != exts.end(); ++e) {
                     rule = dynamic_cast<const Scope*>(*e);
-                    if (rule) {
-                        if (!widescope)
-                            widescope = fromUTF8(scope);
-                        if (matches(*rule, widescope)) {
-                            delete[] widescope;
-                            return true;
-                        }
+                    if (rule && matches(*rule, widescope)) {
+                        return true;
                     }
                 }
             }
 
-            delete[] widescope;
             return false;
         }
 
     private:
-        bool matches(const Scope& rule, const XMLCh* scope) const {
+        bool matches(const Scope& rule, auto_arrayptr<XMLCh>& scope) const {
             const XMLCh* val = rule.getValue();
             if (val && *val) {
                 if (rule.Regexp()) {
                     RegularExpression re(val);
-                    return re.matches(scope);
+                    return re.matches(scope.get());
                 }
                 else {
-                    return XMLString::equals(val, scope);
+                    return XMLString::equals(val, scope.get());
                 }
             }
             return false;
         }
     };
 
-    MatchFunctor* SHIBSP_DLLLOCAL AttributeScopeMatchesShibMDScopeFactory(const std::pair<const FilterPolicyContext*,const DOMElement*>& p)
+    MatchFunctor* SHIBSP_DLLLOCAL AttributeScopeMatchesShibMDScopeFactory(const pair<const FilterPolicyContext*,const DOMElement*>& p)
     {
         return new AttributeScopeMatchesShibMDScopeFunctor();
     }
index 10787f2..6cf9047 100644 (file)
 #include "attribute/filtering/FilterPolicyContext.h"
 #include "attribute/filtering/MatchFunctor.h"
 
+#include <boost/scoped_ptr.hpp>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/regx/RegularExpression.hpp>
 
 using namespace shibsp;
+using namespace xmltooling;
+using namespace boost;
 using namespace std;
-using xmltooling::XMLHelper;
 
 namespace shibsp {
 
@@ -51,18 +53,18 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL AttributeScopeRegexFunctor : public MatchFunctor
     {
         string m_attributeID;
-        RegularExpression* m_regex;
+        scoped_ptr<RegularExpression> m_regex;
 
         bool hasScope(const FilteringContext& filterContext) const;
         bool matches(const Attribute& attribute, size_t index) const;
 
     public:
-        AttributeScopeRegexFunctor(const DOMElement* e) : m_attributeID(XMLHelper::getAttrString(e, nullptr, attributeID)), m_regex(nullptr) {
-            const XMLCh* r = e ? e->getAttributeNS(nullptr,regex) : nullptr;
+        AttributeScopeRegexFunctor(const DOMElement* e) : m_attributeID(XMLHelper::getAttrString(e, nullptr, attributeID)) {
+            const XMLCh* r = e ? e->getAttributeNS(nullptr, regex) : nullptr;
             if (!r || !*r)
                 throw ConfigurationException("AttributeScopeRegex MatchFunctor requires non-empty regex attribute.");
             try {
-                m_regex = new RegularExpression(r, e->getAttributeNS(nullptr,options));
+                m_regex.reset(new RegularExpression(r, e->getAttributeNS(nullptr, options)));
             }
             catch (XMLException& ex) {
                 xmltooling::auto_ptr_char temp(ex.getMessage());
@@ -70,9 +72,7 @@ namespace shibsp {
             }
         }
 
-        virtual ~AttributeScopeRegexFunctor() {
-            delete m_regex;
-        }
+        virtual ~AttributeScopeRegexFunctor() {}
 
         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
             if (m_attributeID.empty())
@@ -87,7 +87,7 @@ namespace shibsp {
         }
     };
 
-    MatchFunctor* SHIBSP_DLLLOCAL AttributeScopeRegexFactory(const std::pair<const FilterPolicyContext*,const DOMElement*>& p)
+    MatchFunctor* SHIBSP_DLLLOCAL AttributeScopeRegexFactory(const pair<const FilterPolicyContext*,const DOMElement*>& p)
     {
         return new AttributeScopeRegexFunctor(p.second);
     }
@@ -114,8 +114,6 @@ bool AttributeScopeRegexFunctor::matches(const Attribute& attribute, size_t inde
     const char* val = attribute.getScope(index);
     if (!val)
         return false;
-    XMLCh* temp = xmltooling::fromUTF8(val);
-    bool ret = m_regex->matches(temp);
-    delete[] temp;
-    return ret;
+    auto_arrayptr<XMLCh> temp(fromUTF8(val));
+    return m_regex->matches(temp.get());
 }
index 132fd83..640c72f 100644 (file)
@@ -35,8 +35,8 @@
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
+using namespace xmltooling;
 using namespace std;
-using xmltooling::XMLHelper;
 
 namespace shibsp {
 
@@ -50,7 +50,7 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL AttributeScopeStringFunctor : public MatchFunctor
     {
         string m_attributeID;
-        char* m_value;
+        auto_arrayptr<char> m_value;
         bool m_ignoreCase;
 
         bool hasScope(const FilteringContext& filterContext) const;
@@ -58,17 +58,14 @@ namespace shibsp {
     public:
         AttributeScopeStringFunctor(const DOMElement* e)
             : m_attributeID(XMLHelper::getAttrString(e, nullptr, attributeID)),
-                m_value(e ? xmltooling::toUTF8(e->getAttributeNS(nullptr,value)) : nullptr),
+                m_value(e ? toUTF8(e->getAttributeNS(nullptr, value)) : nullptr),
                 m_ignoreCase(XMLHelper::getAttrBool(e, false, ignoreCase)) {
-            if (!m_value || !*m_value) {
-                delete[] m_value;
+            if (!m_value.get() || !*m_value.get()) {
                 throw ConfigurationException("AttributeScopeString MatchFunctor requires non-empty value attribute.");
             }
         }
 
-        virtual ~AttributeScopeStringFunctor() {
-            delete[] m_value;
-        }
+        virtual ~AttributeScopeStringFunctor() {}
 
         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
             if (m_attributeID.empty())
@@ -78,21 +75,26 @@ namespace shibsp {
 
         bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const {
             if (m_attributeID.empty() || m_attributeID == attribute.getId()) {
-                if (m_ignoreCase) {
+                const char* scope = attribute.getScope(index);
+                if (!scope) {
+                    return false;
+                }
+                else if (m_ignoreCase) {
 #ifdef HAVE_STRCASECMP
-                    return !strcasecmp(attribute.getScope(index), m_value);
+                    return !strcasecmp(scope, m_value.get());
 #else
-                    return !stricmp(attribute.getScope(index), m_value);
+                    return !stricmp(scope, m_value.get());
 #endif
                 }
-                else
-                    return !strcmp(attribute.getScope(index), m_value);
+                else {
+                    return !strcmp(scope, m_value.get());
+                }
             }
             return hasScope(filterContext);
         }
     };
 
-    MatchFunctor* SHIBSP_DLLLOCAL AttributeScopeStringFactory(const std::pair<const FilterPolicyContext*,const DOMElement*>& p)
+    MatchFunctor* SHIBSP_DLLLOCAL AttributeScopeStringFactory(const pair<const FilterPolicyContext*,const DOMElement*>& p)
     {
         return new AttributeScopeStringFunctor(p.second);
     }
@@ -102,22 +104,27 @@ namespace shibsp {
 bool AttributeScopeStringFunctor::hasScope(const FilteringContext& filterContext) const
 {
     size_t count;
+    const char* scope;
     pair<multimap<string,Attribute*>::const_iterator,multimap<string,Attribute*>::const_iterator> attrs =
         filterContext.getAttributes().equal_range(m_attributeID);
     for (; attrs.first != attrs.second; ++attrs.first) {
         count = attrs.first->second->valueCount();
         for (size_t index = 0; index < count; ++index) {
-            if (m_ignoreCase) {
+            scope = attrs.first->second->getScope(index);
+            if (!scope) {
+                return false;
+            }
+            else if (m_ignoreCase) {
 #ifdef HAVE_STRCASECMP
-                if (!strcasecmp(attrs.first->second->getScope(index), m_value))
+                if (!strcasecmp(scope, m_value.get()))
                     return true;
 #else
-                if (!stricmp(attrs.first->second->getScope(index), m_value))
+                if (!stricmp(scope, m_value.get()))
                     return true;
 #endif
             }
             else {
-                if (!strcmp(attrs.first->second->getScope(index), m_value))
+                if (!strcmp(scope, m_value.get()))
                     return true;
             }
         }
index 39e77c6..5200efe 100644 (file)
 #include "attribute/filtering/FilterPolicyContext.h"
 #include "attribute/filtering/MatchFunctor.h"
 
+#include <boost/scoped_ptr.hpp>
 #include <xmltooling/util/XMLHelper.h>
-
 #include <xercesc/util/regx/RegularExpression.hpp>
 
 using namespace shibsp;
+using namespace xmltooling;
+using namespace boost;
 using namespace std;
-using xmltooling::XMLHelper;
 
 namespace shibsp {
 
@@ -52,19 +53,19 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL AttributeValueRegexFunctor : public MatchFunctor
     {
         string m_attributeID;
-        RegularExpression* m_regex;
+        scoped_ptr<RegularExpression> m_regex;
 
         bool hasValue(const FilteringContext& filterContext) const;
         bool matches(const Attribute& attribute, size_t index) const;
 
     public:
         AttributeValueRegexFunctor(const DOMElement* e)
-                : m_attributeID(XMLHelper::getAttrString(e, nullptr, attributeID)), m_regex(nullptr) {
-            const XMLCh* r = e ? e->getAttributeNS(nullptr,regex) : nullptr;
+                : m_attributeID(XMLHelper::getAttrString(e, nullptr, attributeID)) {
+            const XMLCh* r = e ? e->getAttributeNS(nullptr, regex) : nullptr;
             if (!r || !*r)
                 throw ConfigurationException("AttributeValueRegex MatchFunctor requires non-empty regex attribute.");
             try {
-                m_regex = new RegularExpression(r, e->getAttributeNS(nullptr,options));
+                m_regex.reset(new RegularExpression(r, e->getAttributeNS(nullptr, options)));
             }
             catch (XMLException& ex) {
                 xmltooling::auto_ptr_char temp(ex.getMessage());
@@ -72,9 +73,7 @@ namespace shibsp {
             }
         }
 
-        virtual ~AttributeValueRegexFunctor() {
-            delete m_regex;
-        }
+        virtual ~AttributeValueRegexFunctor() {}
 
         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
             if (m_attributeID.empty())
@@ -89,7 +88,7 @@ namespace shibsp {
         }
     };
 
-    MatchFunctor* SHIBSP_DLLLOCAL AttributeValueRegexFactory(const std::pair<const FilterPolicyContext*,const DOMElement*>& p)
+    MatchFunctor* SHIBSP_DLLLOCAL AttributeValueRegexFactory(const pair<const FilterPolicyContext*,const DOMElement*>& p)
     {
         return new AttributeValueRegexFunctor(p.second);
     }
@@ -116,8 +115,6 @@ bool AttributeValueRegexFunctor::matches(const Attribute& attribute, size_t inde
     const char* val = attribute.getString(index);
     if (!val)
         return false;
-    XMLCh* temp = xmltooling::fromUTF8(val);
-    bool ret = m_regex->matches(temp);
-    delete[] temp;
-    return ret;
+    auto_arrayptr<XMLCh> temp(fromUTF8(val));
+    return m_regex->matches(temp.get());
 }
index 8052440..4a481d7 100644 (file)
@@ -35,8 +35,8 @@
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
+using namespace xmltooling;
 using namespace std;
-using xmltooling::XMLHelper;
 
 namespace shibsp {
 
@@ -50,7 +50,7 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL AttributeValueStringFunctor : public MatchFunctor
     {
         string m_attributeID;
-        char* m_value;
+        auto_arrayptr<char> m_value;
 
         bool hasValue(const FilteringContext& filterContext) const;
         bool matches(const Attribute& attribute, size_t index) const;
@@ -58,21 +58,18 @@ namespace shibsp {
     public:
         AttributeValueStringFunctor(const DOMElement* e)
                : m_attributeID(XMLHelper::getAttrString(e, nullptr, attributeID)),
-                 m_value(e ? xmltooling::toUTF8(e->getAttributeNS(nullptr,value)) : nullptr) {
-            if (!m_value || !*m_value) {
-                delete[] m_value;
+                 m_value(e ? toUTF8(e->getAttributeNS(nullptr, value)) : nullptr) {
+            if (!m_value.get() || !*m_value.get()) {
                 throw ConfigurationException("AttributeValueString MatchFunctor requires non-empty value attribute.");
             }
-            if (e && e->hasAttributeNS(nullptr,ignoreCase)) {
-                xmltooling::logging::Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(
+            if (e && e->hasAttributeNS(nullptr, ignoreCase)) {
+                Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(
                     "ignoreCase property ignored by AttributeValueString MatchFunctor in favor of attribute's caseSensitive property"
                     );
             }
         }
 
-        virtual ~AttributeValueStringFunctor() {
-            delete[] m_value;
-        }
+        virtual ~AttributeValueStringFunctor() {}
 
         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
             if (m_attributeID.empty())
@@ -87,7 +84,7 @@ namespace shibsp {
         }
     };
 
-    MatchFunctor* SHIBSP_DLLLOCAL AttributeValueStringFactory(const std::pair<const FilterPolicyContext*,const DOMElement*>& p)
+    MatchFunctor* SHIBSP_DLLLOCAL AttributeValueStringFactory(const pair<const FilterPolicyContext*,const DOMElement*>& p)
     {
         return new AttributeValueStringFunctor(p.second);
     }
@@ -115,11 +112,11 @@ bool AttributeValueStringFunctor::matches(const Attribute& attribute, size_t ind
     if (!val)
         return false;
     if (attribute.isCaseSensitive())
-        return !strcmp(m_value, val);
+        return !strcmp(m_value.get(), val);
 
 #ifdef HAVE_STRCASECMP
-    return !strcasecmp(m_value, val);
+    return !strcasecmp(m_value.get(), val);
 #else
-    return !stricmp(m_value, val);
+    return !stricmp(m_value.get(), val);
 #endif
 }
index 7ecad04..8d18bae 100644 (file)
@@ -31,6 +31,7 @@
 #include "attribute/filtering/FilterPolicyContext.h"
 #include "attribute/filtering/MatchFunctor.h"
 
+#include <boost/scoped_ptr.hpp>
 #include <xercesc/util/regx/RegularExpression.hpp>
 
 namespace shibsp {
@@ -44,14 +45,14 @@ namespace shibsp {
      */
     class SHIBSP_DLLLOCAL AuthenticationMethodRegexFunctor : public MatchFunctor
     {
-        RegularExpression* m_regex;
+        boost::scoped_ptr<RegularExpression> m_regex;
     public:
-        AuthenticationMethodRegexFunctor(const DOMElement* e) : m_regex(nullptr) {
-            const XMLCh* r = e ? e->getAttributeNS(nullptr,regex) : nullptr;
+        AuthenticationMethodRegexFunctor(const DOMElement* e) {
+            const XMLCh* r = e ? e->getAttributeNS(nullptr, regex) : nullptr;
             if (!r || !*r)
                 throw ConfigurationException("AuthenticationMethodRegex MatchFunctor requires non-empty regex attribute.");
             try {
-                m_regex = new RegularExpression(r, e->getAttributeNS(nullptr,options));
+                m_regex.reset(new RegularExpression(r, e->getAttributeNS(nullptr, options)));
             }
             catch (XMLException& ex) {
                 xmltooling::auto_ptr_char temp(ex.getMessage());
@@ -59,9 +60,7 @@ namespace shibsp {
             }
         }
 
-        virtual ~AuthenticationMethodRegexFunctor() {
-            delete m_regex;
-        }
+        virtual ~AuthenticationMethodRegexFunctor() {}
 
         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
             return (m_regex->matches(filterContext.getAuthnContextClassRef()) || m_regex->matches(filterContext.getAuthnContextDeclRef()));
index f397dff..5f4649b 100644 (file)
 #include "attribute/filtering/AttributeFilter.h"
 #include "attribute/filtering/FilteringContext.h"
 
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -42,9 +44,7 @@ namespace shibsp {
     {
     public:
         ChainingAttributeFilter(const DOMElement* e);
-        virtual ~ChainingAttributeFilter() {
-            for_each(m_filters.begin(), m_filters.end(), xmltooling::cleanup<AttributeFilter>());
-        }
+        virtual ~ChainingAttributeFilter() {}
         
         Lockable* lock() {
             return this;
@@ -53,14 +53,14 @@ namespace shibsp {
         }
         
         void filterAttributes(const FilteringContext& context, vector<Attribute*>& attributes) const {
-            for (vector<AttributeFilter*>::const_iterator i=m_filters.begin(); i!=m_filters.end(); ++i) {
-                Locker locker(*i);
-                (*i)->filterAttributes(context, attributes);
+            for (ptr_vector<AttributeFilter>::iterator i = m_filters.begin(); i != m_filters.end(); ++i) {
+                Locker locker(&(*i));
+                i->filterAttributes(context, attributes);
             }
         }
 
     private:
-        vector<AttributeFilter*> m_filters;
+        mutable ptr_vector<AttributeFilter> m_filters;
     };
 
     static const XMLCh _AttributeFilter[] = UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);
@@ -75,20 +75,15 @@ namespace shibsp {
 ChainingAttributeFilter::ChainingAttributeFilter(const DOMElement* e)
 {
     // Load up the chain of handlers.
-    try {
-        e = XMLHelper::getFirstChildElement(e, _AttributeFilter);
-        while (e) {
-            string t(XMLHelper::getAttrString(e, nullptr, _type));
-            if (!t.empty()) {
-                Category::getInstance(SHIBSP_LOGCAT".AttributeFilter.Chaining").info("building AttributeFilter of type (%s)...", t.c_str());
-                m_filters.push_back(SPConfig::getConfig().AttributeFilterManager.newPlugin(t.c_str(), e));
-            }
-            e = XMLHelper::getNextSiblingElement(e, _AttributeFilter);
+    e = XMLHelper::getFirstChildElement(e, _AttributeFilter);
+    while (e) {
+        string t(XMLHelper::getAttrString(e, nullptr, _type));
+        if (!t.empty()) {
+            Category::getInstance(SHIBSP_LOGCAT".AttributeFilter.Chaining").info("building AttributeFilter of type (%s)...", t.c_str());
+            auto_ptr<AttributeFilter> np(SPConfig::getConfig().AttributeFilterManager.newPlugin(t.c_str(), e));
+            m_filters.push_back(np);
         }
-    }
-    catch (exception&) {
-        for_each(m_filters.begin(), m_filters.end(), xmltooling::cleanup<AttributeFilter>());
-        throw;
+        e = XMLHelper::getNextSiblingElement(e, _AttributeFilter);
     }
     if (m_filters.empty())
         throw ConfigurationException("Chaining AttributeFilter plugin requires at least one child plugin.");
index c279d52..4998747 100644 (file)
 #include "attribute/filtering/MatchFunctor.h"
 #include "util/SPConstants.h"
 
+#include <boost/scoped_ptr.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -103,11 +105,11 @@ MatchFunctor* NotMatchFunctor::buildFunctor(const DOMElement* e, const FilterPol
     if (!id.empty() && functorMap->getMatchFunctors().count(id))
         id.clear();
 
-    auto_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
-    if (!type.get())
+    scoped_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
+    if (!type)
         throw ConfigurationException("Child Rule found with no xsi:type.");
 
-    MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(functorMap,e));
-    functorMap->getMatchFunctors().insert(multimap<string,MatchFunctor*>::value_type(id, func));
-    return func;
+    auto_ptr<MatchFunctor> func(SPConfig::getConfig().MatchFunctorManager.newPlugin(*type, make_pair(functorMap,e)));
+    functorMap->getMatchFunctors().insert(multimap<string,MatchFunctor*>::value_type(id, func.get()));
+    return func.release();
 }
index bbf9431..6018d13 100644 (file)
 #include "attribute/filtering/MatchFunctor.h"
 #include "util/SPConstants.h"
 
+#include <boost/scoped_ptr.hpp>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/lambda.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost::lambda;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -48,17 +53,19 @@ namespace shibsp {
         OrMatchFunctor(const pair<const FilterPolicyContext*,const DOMElement*>& p);
 
         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
-            for (vector<const MatchFunctor*>::const_iterator mf = m_functors.begin(); mf!=m_functors.end(); ++mf)
-                if ((*mf)->evaluatePolicyRequirement(filterContext))
-                    return true;
-            return false;
+            vector<const MatchFunctor*>::const_iterator i = find_if(
+                m_functors.begin(), m_functors.end(),
+                lambda::bind(&MatchFunctor::evaluatePolicyRequirement, _1, boost::ref(filterContext)) == true
+                );
+            return (i != m_functors.end());
         }
 
         bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const {
-            for (vector<const MatchFunctor*>::const_iterator mf = m_functors.begin(); mf!=m_functors.end(); ++mf)
-                if ((*mf)->evaluatePermitValue(filterContext, attribute, index))
-                    return true;
-            return false;
+            vector<const MatchFunctor*>::const_iterator i = find_if(
+                m_functors.begin(), m_functors.end(),
+                lambda::bind(&MatchFunctor::evaluatePermitValue, _1, boost::ref(filterContext), boost::ref(attribute), index) == true
+                );
+            return (i != m_functors.end());
         }
 
     private:
@@ -109,11 +116,11 @@ MatchFunctor* OrMatchFunctor::buildFunctor(const DOMElement* e, const FilterPoli
     if (!id.empty() && functorMap->getMatchFunctors().count(id))
         id.clear();
 
-    auto_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
-    if (!type.get())
+    scoped_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
+    if (!type)
         throw ConfigurationException("Child Rule found with no xsi:type.");
 
-    MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(functorMap,e));
-    functorMap->getMatchFunctors().insert(multimap<string,MatchFunctor*>::value_type(id, func));
-    return func;
+    auto_ptr<MatchFunctor> func(SPConfig::getConfig().MatchFunctorManager.newPlugin(*type, make_pair(functorMap,e)));
+    functorMap->getMatchFunctors().insert(multimap<string,MatchFunctor*>::value_type(id, func.get()));
+    return func.release();
 }
index 3880638..f317b42 100644 (file)
@@ -35,6 +35,9 @@
 #include "attribute/filtering/MatchFunctor.h"
 #include "util/SPConstants.h"
 
+#include <boost/scoped_ptr.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/tuple/tuple.hpp>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
 #include <xmltooling/util/Threads.h>
@@ -46,6 +49,7 @@ using namespace shibsp;
 using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -87,14 +91,14 @@ namespace shibsp {
         MatchFunctor* buildFunctor(
             const DOMElement* e, const FilterPolicyContext& functorMap, const char* logname, bool standalone
             );
-        pair< string,pair<const MatchFunctor*,const MatchFunctor*> > buildAttributeRule(
+        tuple<string,const MatchFunctor*,const MatchFunctor*> buildAttributeRule(
             const DOMElement* e, const FilterPolicyContext& permMap, const FilterPolicyContext& denyMap, bool standalone
             );
 
         Category& m_log;
         DOMDocument* m_document;
         vector<Policy> m_policies;
-        map< string,pair<string,pair<const MatchFunctor*,const MatchFunctor*> > > m_attrRules;
+        map< string,tuple<string,const MatchFunctor*,const MatchFunctor*> > m_attrRules;
         multimap<string,MatchFunctor*> m_policyReqRules;
         multimap<string,MatchFunctor*> m_permitValRules;
         multimap<string,MatchFunctor*> m_denyValRules;
@@ -103,12 +107,11 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL XMLFilter : public AttributeFilter, public ReloadableXMLFile
     {
     public:
-        XMLFilter(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeFilter")), m_impl(nullptr) {
+        XMLFilter(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeFilter")) {
             background_load();
         }
         ~XMLFilter() {
             shutdown();
-            delete m_impl;
         }
 
         void filterAttributes(const FilteringContext& context, vector<Attribute*>& attributes) const {
@@ -119,7 +122,7 @@ namespace shibsp {
         pair<bool,DOMElement*> background_load();
 
     private:
-        XMLFilterImpl* m_impl;
+        scoped_ptr<XMLFilterImpl> m_impl;
     };
 
 #if defined (_MSC_VER)
@@ -192,18 +195,22 @@ XMLFilterImpl::XMLFilterImpl(const DOMElement* e, Category& log) : m_log(log), m
                 e = XMLHelper::getNextSiblingElement(e);
                 while (e) {
                     if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, AttributeRule)) {
-                        pair< string,pair<const MatchFunctor*,const MatchFunctor*> > rule = buildAttributeRule(e, permFunctors, denyFunctors, false);
-                        if (rule.second.first || rule.second.second)
-                            m_policies.back().m_rules.insert(Policy::rules_t::value_type(rule.first, rule.second));
+                        tuple<string,const MatchFunctor*,const MatchFunctor*> rule = buildAttributeRule(e, permFunctors, denyFunctors, false);
+                        if (rule.get<1>() || rule.get<2>())
+                            m_policies.back().m_rules.insert(Policy::rules_t::value_type(rule.get<0>(), make_pair(rule.get<1>(), rule.get<2>())));
                     }
                     else if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, AttributeRuleReference)) {
                         string ref(XMLHelper::getAttrString(e, nullptr, _ref));
                         if (!ref.empty()) {
-                            map< string,pair< string,pair< const MatchFunctor*,const MatchFunctor*> > >::const_iterator ar = m_attrRules.find(ref);
-                            if (ar != m_attrRules.end())
-                                m_policies.back().m_rules.insert(Policy::rules_t::value_type(ar->second.first, ar->second.second));
-                            else
+                            map< string,tuple<string,const MatchFunctor*,const MatchFunctor*> >::const_iterator ar = m_attrRules.find(ref);
+                            if (ar != m_attrRules.end()) {
+                                m_policies.back().m_rules.insert(
+                                    Policy::rules_t::value_type(ar->second.get<0>(), make_pair(ar->second.get<1>(), ar->second.get<2>()))
+                                    );
+                            }
+                            else {
                                 m_log.warn("skipping invalid AttributeRuleReference (%s)", ref.c_str());
+                            }
                         }
                     }
                     e = XMLHelper::getNextSiblingElement(e);
@@ -236,12 +243,12 @@ MatchFunctor* XMLFilterImpl::buildFunctor(
             id.clear();
     }
 
-    auto_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
-    if (type.get()) {
+    scoped_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
+    if (type) {
         try {
-            MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(&functorMap,e));
-            functorMap.getMatchFunctors().insert(multimap<string,MatchFunctor*>::value_type(id, func));
-            return func;
+            auto_ptr<MatchFunctor> func(SPConfig::getConfig().MatchFunctorManager.newPlugin(*type, make_pair(&functorMap,e)));
+            functorMap.getMatchFunctors().insert(multimap<string,MatchFunctor*>::value_type(id, func.get()));
+            return func.release();
         }
         catch (exception& ex) {
             m_log.error("error building %s with type (%s): %s", logname, type->toString().c_str(), ex.what());
@@ -255,7 +262,7 @@ MatchFunctor* XMLFilterImpl::buildFunctor(
     return nullptr;
 }
 
-pair< string,pair<const MatchFunctor*,const MatchFunctor*> > XMLFilterImpl::buildAttributeRule(
+tuple<string,const MatchFunctor*,const MatchFunctor*> XMLFilterImpl::buildAttributeRule(
     const DOMElement* e, const FilterPolicyContext& permMap, const FilterPolicyContext& denyMap, bool standalone
     )
 {
@@ -263,12 +270,12 @@ pair< string,pair<const MatchFunctor*,const MatchFunctor*> > XMLFilterImpl::buil
 
     if (standalone && id.empty()) {
         m_log.warn("skipping stand-alone AttributeRule with no id");
-        return make_pair(string(),pair<const MatchFunctor*,const MatchFunctor*>(nullptr,nullptr));
+        return tuple<string,const MatchFunctor*,const MatchFunctor*>(string(),nullptr,nullptr);
     }
     else if (!id.empty() && m_attrRules.count(id)) {
         if (standalone) {
             m_log.warn("skipping duplicate stand-alone AttributeRule with id (%s)", id.c_str());
-            return make_pair(string(),pair<const MatchFunctor*,const MatchFunctor*>(nullptr,nullptr));
+            return tuple<string,const MatchFunctor*,const MatchFunctor*>(string(),nullptr,nullptr);
         }
         else
             id.clear();
@@ -278,8 +285,8 @@ pair< string,pair<const MatchFunctor*,const MatchFunctor*> > XMLFilterImpl::buil
     if (attrID.empty())
         m_log.warn("skipping AttributeRule with no attributeID");
 
-    MatchFunctor* perm=nullptr;
-    MatchFunctor* deny=nullptr;
+    MatchFunctor* perm = nullptr;
+    MatchFunctor* deny = nullptr;
 
     e = XMLHelper::getFirstChildElement(e);
     if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, PermitValueRule)) {
@@ -308,12 +315,11 @@ pair< string,pair<const MatchFunctor*,const MatchFunctor*> > XMLFilterImpl::buil
 
     if (perm || deny) {
         if (!id.empty()) {
-            m_attrRules[id] =
-                pair< string,pair<const MatchFunctor*,const MatchFunctor*> >(attrID, pair<const MatchFunctor*,const MatchFunctor*>(perm,deny));
+            m_attrRules[id] = make_tuple(attrID, perm, deny);
             return m_attrRules[id];
         }
         else {
-            return pair< string,pair<const MatchFunctor*,const MatchFunctor*> >(attrID, pair<const MatchFunctor*,const MatchFunctor*>(perm,deny));
+            return make_tuple(attrID, perm, deny);
         }
     }
 
@@ -321,7 +327,7 @@ pair< string,pair<const MatchFunctor*,const MatchFunctor*> > XMLFilterImpl::buil
         m_log.warn("skipping AttributeRule (%s), permit and denial rule(s) invalid or missing", id.c_str());
     else
         m_log.warn("skipping AttributeRule, permit and denial rule(s) invalid or missing");
-    return pair< string,pair<const MatchFunctor*,const MatchFunctor*> >(string(),pair<const MatchFunctor*,const MatchFunctor*>(nullptr,nullptr));
+    return tuple<string,const MatchFunctor*,const MatchFunctor*>(string(),nullptr,nullptr);
 }
 
 void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector<Attribute*>& attributes) const
@@ -341,7 +347,7 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector<Att
 
     // For efficiency, we build an array of the policies that apply in advance.
     vector<const Policy*> applicablePolicies;
-    for (vector<Policy>::const_iterator p=m_policies.begin(); p!=m_policies.end(); ++p) {
+    for (vector<Policy>::const_iterator p = m_policies.begin(); p != m_policies.end(); ++p) {
         if (p->m_applies->evaluatePolicyRequirement(context))
             applicablePolicies.push_back(&(*p));
     }
@@ -351,8 +357,9 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector<Att
     vector< pair<const MatchFunctor*,const MatchFunctor*> > wildcardRules;
 
     // Store off the wildcards ahead of time.
-    for (vector<const Policy*>::const_iterator pol=applicablePolicies.begin(); pol!=applicablePolicies.end(); ++pol) {
-        pair<Policy::rules_t::const_iterator,Policy::rules_t::const_iterator> rules = (*pol)->m_rules.equal_range("*");
+    for (indirect_iterator<vector<const Policy*>::const_iterator> pol = make_indirect_iterator(applicablePolicies.begin());
+            pol != make_indirect_iterator(applicablePolicies.end()); ++pol) {
+        pair<Policy::rules_t::const_iterator,Policy::rules_t::const_iterator> rules = pol->m_rules.equal_range("*");
         for (; rules.first!=rules.second; ++rules.first)
             wildcardRules.push_back(rules.first->second);
     }
@@ -364,21 +371,23 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector<Att
     map< Attribute*, vector<bool> > deletedPositions;
 
     // Loop over each attribute to filter them.
-    for (vector<Attribute*>::size_type a=0; a<attributes.size(); ++a) {
+    for (vector<Attribute*>::size_type a = 0; a < attributes.size(); ++a) {
         Attribute* attr = attributes[a];
 
         // Clear the rule store.
         applicableRules.clear();
 
         // Look for rules to run in each policy.
-        for (vector<const Policy*>::const_iterator pol=applicablePolicies.begin(); pol!=applicablePolicies.end(); ++pol) {
-            pair<Policy::rules_t::const_iterator,Policy::rules_t::const_iterator> rules = (*pol)->m_rules.equal_range(attr->getId());
+        for (indirect_iterator<vector<const Policy*>::const_iterator> pol = make_indirect_iterator(applicablePolicies.begin());
+                pol != make_indirect_iterator(applicablePolicies.end()); ++pol) {
+            pair<Policy::rules_t::const_iterator,Policy::rules_t::const_iterator> rules = pol->m_rules.equal_range(attr->getId());
             for (; rules.first!=rules.second; ++rules.first)
                 applicableRules.push_back(rules.first->second);
         }
 
         // If no rules found, apply wildcards.
-        const vector< pair<const MatchFunctor*,const MatchFunctor*> >& rulesToRun = applicableRules.empty() ? wildcardRules : applicableRules;
+        const vector< pair<const MatchFunctor*,const MatchFunctor*> >& rulesToRun =
+            applicableRules.empty() ? wildcardRules : applicableRules;
 
         // If no rules apply, remove the attribute entirely.
         if (rulesToRun.empty()) {
@@ -404,7 +413,7 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector<Att
             // Assume we're kicking it out.
             kickit=true;
 
-            for (vector< pair<const MatchFunctor*,const MatchFunctor*> >::const_iterator r=rulesToRun.begin(); r!=rulesToRun.end(); ++r) {
+            for (vector< pair<const MatchFunctor*,const MatchFunctor*> >::const_iterator r = rulesToRun.begin(); r != rulesToRun.end(); ++r) {
                 // If there's a permit rule that passes, don't kick it.
                 if (r->first && r->first->evaluatePermitValue(context, *attr, index))
                     kickit = false;
@@ -426,7 +435,7 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector<Att
 
     // Final step: go over the deletedPositions matrix and apply the actual changes. In order to delete
     // any attributes that end up with no values, we have to do it by looping over the originals.
-    for (vector<Attribute*>::size_type a=0; a<attributes.size();) {
+    for (vector<Attribute*>::size_type a = 0; a < attributes.size();) {
         Attribute* attr = attributes[a];
 
         if (deletedAttributes[a]) {
@@ -474,7 +483,7 @@ pair<bool,DOMElement*> XMLFilter::background_load()
     // If we own it, wrap it.
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
 
-    XMLFilterImpl* impl = new XMLFilterImpl(raw.second, m_log);
+    scoped_ptr<XMLFilterImpl> impl(new XMLFilterImpl(raw.second, m_log));
 
     // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
     impl->setDocument(docjanitor.release());
@@ -483,8 +492,7 @@ pair<bool,DOMElement*> XMLFilter::background_load()
     if (m_lock)
         m_lock->wrlock();
     SharedLock locker(m_lock, false);
-    delete m_impl;
-    m_impl = impl;
+    m_impl.swap(impl);
 
     return make_pair(false,(DOMElement*)nullptr);
 }
index 7bc413b..83e8f38 100644 (file)
@@ -121,22 +121,24 @@ void AssertionExtractor::extractAttributes(
         if (!m_issuer.empty()) {
             const Issuer* i = saml2assertion->getIssuer();
             if (i && (!i->getFormat() || !*(i->getFormat()) || XMLString::equals(i->getFormat(), NameIDType::ENTITY))) {
-                auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
                 auto_ptr_char temp(i->getName());
                 if (temp.get()) {
+                    auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
                     issuer->getValues().push_back(temp.get());
-                    attributes.push_back(issuer.release());
+                    attributes.push_back(issuer.get());
+                    issuer.release();
                 }
             }
         }
 
         // NotOnOrAfter
         if (!m_notOnOrAfter.empty() && saml2assertion->getConditions() && saml2assertion->getConditions()->getNotOnOrAfter()) {
-            auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
             auto_ptr_char temp(saml2assertion->getConditions()->getNotOnOrAfter()->getRawData());
             if (temp.get()) {
+                auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
                 notonorafter->getValues().push_back(temp.get());
-                attributes.push_back(notonorafter.release());
+                attributes.push_back(notonorafter.get());
+                notonorafter.release();
             }
         }
     }
@@ -145,31 +147,34 @@ void AssertionExtractor::extractAttributes(
         if (saml2statement) {
             // AuthnInstant
             if (!m_authnInstant.empty() && saml2statement->getAuthnInstant()) {
-                auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
                 auto_ptr_char temp(saml2statement->getAuthnInstant()->getRawData());
                 if (temp.get()) {
+                    auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
                     authninstant->getValues().push_back(temp.get());
-                    attributes.push_back(authninstant.release());
+                    attributes.push_back(authninstant.get());
+                    authninstant.release();
                 }
             }
 
             // SessionIndex
             if (!m_sessionIndex.empty() && saml2statement->getSessionIndex() && *(saml2statement->getSessionIndex())) {
-                auto_ptr<SimpleAttribute> sessionindex(new SimpleAttribute(vector<string>(1, m_sessionIndex)));
                 auto_ptr_char temp(saml2statement->getSessionIndex());
                 if (temp.get()) {
+                    auto_ptr<SimpleAttribute> sessionindex(new SimpleAttribute(vector<string>(1, m_sessionIndex)));
                     sessionindex->getValues().push_back(temp.get());
-                    attributes.push_back(sessionindex.release());
+                    attributes.push_back(sessionindex.get());
+                    sessionindex.release();
                 }
             }
 
             // SessionNotOnOrAfter
             if (!m_sessionNotOnOrAfter.empty() && saml2statement->getSessionNotOnOrAfter()) {
-                auto_ptr<SimpleAttribute> sessionnotonorafter(new SimpleAttribute(vector<string>(1, m_sessionNotOnOrAfter)));
                 auto_ptr_char temp(saml2statement->getSessionNotOnOrAfter()->getRawData());
                 if (temp.get()) {
+                    auto_ptr<SimpleAttribute> sessionnotonorafter(new SimpleAttribute(vector<string>(1, m_sessionNotOnOrAfter)));
                     sessionnotonorafter->getValues().push_back(temp.get());
-                    attributes.push_back(sessionnotonorafter.release());
+                    attributes.push_back(sessionnotonorafter.get());
+                    sessionnotonorafter.release();
                 }
             }
 
@@ -177,21 +182,23 @@ void AssertionExtractor::extractAttributes(
                 const saml2::SubjectLocality* locality = saml2statement->getSubjectLocality();
                 // Address
                 if (!m_subjectAddress.empty() && locality->getAddress() && *(locality->getAddress())) {
-                    auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
                     auto_ptr_char temp(locality->getAddress());
                     if (temp.get()) {
+                        auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
                         address->getValues().push_back(temp.get());
-                        attributes.push_back(address.release());
+                        attributes.push_back(address.get());
+                        address.release();
                     }
                 }
 
                 // DNSName
                 if (!m_subjectDNS.empty() && locality->getDNSName() && *(locality->getDNSName())) {
-                    auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
                     auto_ptr_char temp(locality->getDNSName());
                     if (temp.get()) {
+                        auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
                         dns->getValues().push_back(temp.get());
-                        attributes.push_back(dns.release());
+                        attributes.push_back(dns.get());
+                        dns.release();
                     }
                 }
             }
@@ -200,21 +207,23 @@ void AssertionExtractor::extractAttributes(
                 const AuthnContext* ac = saml2statement->getAuthnContext();
                 // AuthnContextClassRef
                 if (!m_authnClass.empty() && ac->getAuthnContextClassRef() && ac->getAuthnContextClassRef()->getReference()) {
-                    auto_ptr<SimpleAttribute> classref(new SimpleAttribute(vector<string>(1, m_authnClass)));
                     auto_ptr_char temp(ac->getAuthnContextClassRef()->getReference());
                     if (temp.get()) {
+                        auto_ptr<SimpleAttribute> classref(new SimpleAttribute(vector<string>(1, m_authnClass)));
                         classref->getValues().push_back(temp.get());
-                        attributes.push_back(classref.release());
+                        attributes.push_back(classref.get());
+                        classref.release();
                     }
                 }
 
                 // AuthnContextDeclRef
                 if (!m_authnDecl.empty() && ac->getAuthnContextDeclRef() && ac->getAuthnContextDeclRef()->getReference()) {
-                    auto_ptr<SimpleAttribute> declref(new SimpleAttribute(vector<string>(1, m_authnDecl)));
                     auto_ptr_char temp(ac->getAuthnContextDeclRef()->getReference());
                     if (temp.get()) {
+                        auto_ptr<SimpleAttribute> declref(new SimpleAttribute(vector<string>(1, m_authnDecl)));
                         declref->getValues().push_back(temp.get());
-                        attributes.push_back(declref.release());
+                        attributes.push_back(declref.get());
+                        declref.release();
                     }
                 }
 
@@ -228,7 +237,8 @@ void AssertionExtractor::extractAttributes(
                             attr->getValues().push_back(temp.get());
                     }
                     if (attr->valueCount() > 0) {
-                        attributes.push_back(attr.release());
+                        attributes.push_back(attr.get());
+                        attr.release();
                     }
                 }
             }
@@ -239,22 +249,24 @@ void AssertionExtractor::extractAttributes(
                 // Issuer
                 if (!m_issuer.empty()) {
                     if (saml1assertion->getIssuer() && *(saml1assertion->getIssuer())) {
-                        auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
                         auto_ptr_char temp(saml1assertion->getIssuer());
                         if (temp.get()) {
+                            auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
                             issuer->getValues().push_back(temp.get());
-                            attributes.push_back(issuer.release());
+                            attributes.push_back(issuer.get());
+                            issuer.release();
                         }
                     }
                 }
 
                 // NotOnOrAfter
                 if (!m_notOnOrAfter.empty() && saml1assertion->getConditions() && saml1assertion->getConditions()->getNotOnOrAfter()) {
-                    auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
                     auto_ptr_char temp(saml1assertion->getConditions()->getNotOnOrAfter()->getRawData());
                     if (temp.get()) {
+                        auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
                         notonorafter->getValues().push_back(temp.get());
-                        attributes.push_back(notonorafter.release());
+                        attributes.push_back(notonorafter.get());
+                        notonorafter.release();
                     }
                 }
             }
@@ -263,21 +275,23 @@ void AssertionExtractor::extractAttributes(
                 if (saml1statement) {
                     // AuthnInstant
                     if (!m_authnInstant.empty() && saml1statement->getAuthenticationInstant()) {
-                        auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
                         auto_ptr_char temp(saml1statement->getAuthenticationInstant()->getRawData());
                         if (temp.get()) {
+                            auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
                             authninstant->getValues().push_back(temp.get());
-                            attributes.push_back(authninstant.release());
+                            attributes.push_back(authninstant.get());
+                            authninstant.release();
                         }
                     }
 
                     // AuthenticationMethod
                     if (!m_authnClass.empty() && saml1statement->getAuthenticationMethod() && *(saml1statement->getAuthenticationMethod())) {
-                        auto_ptr<SimpleAttribute> authnmethod(new SimpleAttribute(vector<string>(1, m_authnClass)));
                         auto_ptr_char temp(saml1statement->getAuthenticationMethod());
                         if (temp.get()) {
+                            auto_ptr<SimpleAttribute> authnmethod(new SimpleAttribute(vector<string>(1, m_authnClass)));
                             authnmethod->getValues().push_back(temp.get());
-                            attributes.push_back(authnmethod.release());
+                            attributes.push_back(authnmethod.get());
+                            authnmethod.release();
                         }
                     }
 
@@ -285,21 +299,23 @@ void AssertionExtractor::extractAttributes(
                         const saml1::SubjectLocality* locality = saml1statement->getSubjectLocality();
                         // IPAddress
                         if (!m_subjectAddress.empty() && locality->getIPAddress() && *(locality->getIPAddress())) {
-                            auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
                             auto_ptr_char temp(locality->getIPAddress());
                             if (temp.get()) {
+                                auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
                                 address->getValues().push_back(temp.get());
-                                attributes.push_back(address.release());
+                                attributes.push_back(address.get());
+                                address.release();
                             }
                         }
 
                         // DNSAddress
                         if (!m_subjectDNS.empty() && locality->getDNSAddress() && *(locality->getDNSAddress())) {
-                            auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
                             auto_ptr_char temp(locality->getDNSAddress());
                             if (temp.get()) {
+                                auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
                                 dns->getValues().push_back(temp.get());
-                                attributes.push_back(dns.release());
+                                attributes.push_back(dns.get());
+                                dns.release();
                             }
                         }
                     }
index b46ce9c..76fc3ce 100644 (file)
 #include "attribute/Attribute.h"
 #include "attribute/resolver/AttributeExtractor.h"
 
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
 using namespace opensaml::saml2md;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -44,9 +46,7 @@ namespace shibsp {
     {
     public:
         ChainingAttributeExtractor(const DOMElement* e);
-        virtual ~ChainingAttributeExtractor() {
-            for_each(m_extractors.begin(), m_extractors.end(), xmltooling::cleanup<AttributeExtractor>());
-        }
+        virtual ~ChainingAttributeExtractor() {}
 
         Lockable* lock() {
             return this;
@@ -59,24 +59,29 @@ namespace shibsp {
             const RoleDescriptor* issuer,
             const XMLObject& xmlObject,
             vector<Attribute*>& attributes
-            ) const;
+            ) const {
+            for (ptr_vector<AttributeExtractor>::iterator i = m_extractors.begin(); i != m_extractors.end(); ++i) {
+                Locker locker(&(*i));
+                i->extractAttributes(application, issuer, xmlObject, attributes);
+            }
+        }
 
         void getAttributeIds(vector<string>& attributes) const {
-            for (vector<AttributeExtractor*>::const_iterator i=m_extractors.begin(); i!=m_extractors.end(); ++i) {
-                Locker locker(*i);
-                (*i)->getAttributeIds(attributes);
+            for (ptr_vector<AttributeExtractor>::iterator i = m_extractors.begin(); i != m_extractors.end(); ++i) {
+                Locker locker(&(*i));
+                i->getAttributeIds(attributes);
             }
         }
 
         void generateMetadata(SPSSODescriptor& role) const {
-            for (vector<AttributeExtractor*>::const_iterator i=m_extractors.begin(); i!=m_extractors.end(); ++i) {
-                Locker locker(*i);
-                (*i)->generateMetadata(role);
+            for (ptr_vector<AttributeExtractor>::iterator i = m_extractors.begin(); i != m_extractors.end(); ++i) {
+                Locker locker(&(*i));
+                i->generateMetadata(role);
             }
         }
 
     private:
-        vector<AttributeExtractor*> m_extractors;
+        mutable ptr_vector<AttributeExtractor> m_extractors;
     };
 
     static const XMLCh _AttributeExtractor[] =  UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);
@@ -126,7 +131,8 @@ ChainingAttributeExtractor::ChainingAttributeExtractor(const DOMElement* e)
                 Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.Chaining").info(
                     "building AttributeExtractor of type (%s)...", t.c_str()
                     );
-                m_extractors.push_back(conf.AttributeExtractorManager.newPlugin(t.c_str(), e));
+                auto_ptr<AttributeExtractor> np(conf.AttributeExtractorManager.newPlugin(t.c_str(), e));
+                m_extractors.push_back(np);
             }
             catch (exception& ex) {
                 Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.Chaining").error(
@@ -137,13 +143,3 @@ ChainingAttributeExtractor::ChainingAttributeExtractor(const DOMElement* e)
         e = XMLHelper::getNextSiblingElement(e, _AttributeExtractor);
     }
 }
-
-void ChainingAttributeExtractor::extractAttributes(
-    const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
-    ) const
-{
-    for (vector<AttributeExtractor*>::const_iterator i=m_extractors.begin(); i!=m_extractors.end(); ++i) {
-        Locker locker(*i);
-        (*i)->extractAttributes(application, issuer, xmlObject, attributes);
-    }
-}
index 2635489..bb3e748 100644 (file)
 #include "attribute/resolver/AttributeResolver.h"
 #include "attribute/resolver/ResolutionContext.h"
 
-#include <saml/Assertion.h>
+#include <boost/scoped_ptr.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
+#include <saml/Assertion.h>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
 using namespace opensaml::saml2;
 using namespace opensaml::saml2md;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -95,9 +98,7 @@ namespace shibsp {
     {
     public:
         ChainingAttributeResolver(const DOMElement* e);
-        virtual ~ChainingAttributeResolver() {
-            for_each(m_resolvers.begin(), m_resolvers.end(), xmltooling::cleanup<AttributeResolver>());
-        }
+        virtual ~ChainingAttributeResolver() {}
 
         Lockable* lock() {
             return this;
@@ -125,14 +126,14 @@ namespace shibsp {
         void resolveAttributes(ResolutionContext& ctx) const;
 
         void getAttributeIds(vector<string>& attributes) const {
-            for (vector<AttributeResolver*>::const_iterator i=m_resolvers.begin(); i!=m_resolvers.end(); ++i) {
-                Locker locker(*i);
-                (*i)->getAttributeIds(attributes);
+            for (ptr_vector<AttributeResolver>::iterator i = m_resolvers.begin(); i != m_resolvers.end(); ++i) {
+                Locker locker(&(*i));
+                i->getAttributeIds(attributes);
             }
         }
 
     private:
-        vector<AttributeResolver*> m_resolvers;
+        mutable ptr_vector<AttributeResolver> m_resolvers;
     };
 
     static const XMLCh _AttributeResolver[] =   UNICODE_LITERAL_17(A,t,t,r,i,b,u,t,e,R,e,s,o,l,v,e,r);
@@ -183,7 +184,8 @@ ChainingAttributeResolver::ChainingAttributeResolver(const DOMElement* e)
                 Category::getInstance(SHIBSP_LOGCAT".AttributeResolver.Chaining").info(
                     "building AttributeResolver of type (%s)...", t.c_str()
                     );
-                m_resolvers.push_back(conf.AttributeResolverManager.newPlugin(t.c_str(), e));
+                auto_ptr<AttributeResolver> np(conf.AttributeResolverManager.newPlugin(t.c_str(), e));
+                m_resolvers.push_back(np);
             }
             catch (exception& ex) {
                 Category::getInstance(SHIBSP_LOGCAT".AttributeResolver.Chaining").error(
@@ -198,17 +200,17 @@ ChainingAttributeResolver::ChainingAttributeResolver(const DOMElement* e)
 void ChainingAttributeResolver::resolveAttributes(ResolutionContext& ctx) const
 {
     ChainingContext& chain = dynamic_cast<ChainingContext&>(ctx);
-    for (vector<AttributeResolver*>::const_iterator i=m_resolvers.begin(); i!=m_resolvers.end(); ++i) {
-        Locker locker(*i);
-        auto_ptr<ResolutionContext> context(
+    for (ptr_vector<AttributeResolver>::iterator i = m_resolvers.begin(); i != m_resolvers.end(); ++i) {
+        Locker locker(&(*i));
+        scoped_ptr<ResolutionContext> context(
             chain.m_session ?
-                (*i)->createResolutionContext(chain.m_app, *chain.m_session) :
-                (*i)->createResolutionContext(
+                i->createResolutionContext(chain.m_app, *chain.m_session) :
+                i->createResolutionContext(
                     chain.m_app, chain.m_issuer, chain.m_protocol, chain.m_nameid, chain.m_authclass, chain.m_authdecl, &chain.m_tokens, &chain.m_attributes
                     )
             );
 
-        (*i)->resolveAttributes(*context.get());
+        i->resolveAttributes(*context);
 
         chain.m_attributes.insert(chain.m_attributes.end(), context->getResolvedAttributes().begin(), context->getResolvedAttributes().end());
         chain.m_ownedAttributes.insert(chain.m_ownedAttributes.end(), context->getResolvedAttributes().begin(), context->getResolvedAttributes().end());
index d8754cf..2600a89 100644 (file)
@@ -31,6 +31,8 @@
 #include "attribute/resolver/AttributeExtractor.h"
 #include "util/SPConstants.h"
 
+#include <boost/shared_ptr.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
 #include <saml/saml2/core/Assertions.h>
 #include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
@@ -43,6 +45,7 @@ using namespace shibsp;
 using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -113,14 +116,16 @@ void DelegationExtractor::extractAttributes(
             auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(vector<string>(1,m_attributeId), m_formatter.c_str()));
 
             const vector<saml2::Delegate*>& dels = drt->getDelegates();
-            for (vector<saml2::Delegate*>::const_iterator d = dels.begin(); d != dels.end(); ++d) {
-                if ((*d)->getBaseID()) {
+            for (indirect_iterator<vector<saml2::Delegate*>::const_iterator> d = make_indirect_iterator(dels.begin());
+                    d != make_indirect_iterator(dels.end()); ++d) {
+                if (d->getBaseID()) {
                     log.error("delegate identified by saml:BaseID cannot be processed into an attribute value");
                     continue;
                 }
 
                 saml2::NameID* n = nullptr;
-                if ((*d)->getEncryptedID()) {
+                boost::shared_ptr<saml2::NameID> namewrapper;
+                if (d->getEncryptedID()) {
                     CredentialResolver* cr = application.getCredentialResolver();
                     if (!cr) {
                         log.warn("found encrypted Delegate, but no CredentialResolver was available");
@@ -133,61 +138,56 @@ void DelegationExtractor::extractAttributes(
                         Locker credlocker(cr);
                         if (issuer) {
                             MetadataCredentialCriteria mcc(*issuer);
-                            auto_ptr<XMLObject> decrypted((*d)->getEncryptedID()->decrypt(*cr, recipient, &mcc));
-                            n = dynamic_cast<saml2::NameID*>(decrypted.release());
+                            boost::shared_ptr<XMLObject> decrypted(d->getEncryptedID()->decrypt(*cr, recipient, &mcc));
+                            namewrapper = dynamic_pointer_cast<saml2::NameID>(decrypted);
+                            n = namewrapper.get();
                         }
                         else {
-                            auto_ptr<XMLObject> decrypted((*d)->getEncryptedID()->decrypt(*cr, recipient));
-                            n = dynamic_cast<saml2::NameID*>(decrypted.release());
+                            boost::shared_ptr<XMLObject> decrypted(d->getEncryptedID()->decrypt(*cr, recipient));
+                            namewrapper = dynamic_pointer_cast<saml2::NameID>(decrypted);
+                            n = namewrapper.get();
                         }
                         if (n && log.isDebugEnabled())
                             log.debugStream() << "decrypted Delegate: " << *n << logging::eol;
                     }
-                    catch (exception& ex) {
+                    catch (std::exception& ex) {
                         log.error("caught exception decrypting Delegate: %s", ex.what());
                     }
                 }
                 else {
-                    n = (*d)->getNameID();
+                    n = d->getNameID();
                 }
 
                 if (n) {
                     DDF val = DDF(nullptr).structure();
-                    if ((*d)->getConfirmationMethod()) {
-                        auto_ptr_char temp((*d)->getConfirmationMethod());
+                    if (d->getConfirmationMethod()) {
+                        auto_ptr_char temp(d->getConfirmationMethod());
                         val.addmember("ConfirmationMethod").string(temp.get());
                     }
-                    if ((*d)->getDelegationInstant()) {
-                        auto_ptr_char temp((*d)->getDelegationInstant()->getRawData());
+                    if (d->getDelegationInstant()) {
+                        auto_ptr_char temp(d->getDelegationInstant()->getRawData());
                         val.addmember("DelegationInstant").string(temp.get());
                     }
 
                     auto_arrayptr<char> name(toUTF8(n->getName()));
                     if (name.get() && *name.get()) {
                         val.addmember("Name").string(name.get());
-                        char* str = toUTF8(n->getFormat());
-                        if (str && *str)
-                            val.addmember("Format").string(str);
-                        delete[] str;
-
-                        str = toUTF8(n->getNameQualifier());
-                        if (str && *str)
-                            val.addmember("NameQualifier").string(str);
-                        delete[] str;
-
-                        str = toUTF8(n->getSPNameQualifier());
-                        if (str && *str)
-                            val.addmember("SPNameQualifier").string(str);
-                        delete[] str;
-
-                        str = toUTF8(n->getSPProvidedID());
-                        if (str && *str)
-                            val.addmember("SPProvidedID").string(str);
-                        delete[] str;
-                    }
+                        auto_arrayptr<char> format(toUTF8(n->getFormat()));
+                        if (format.get())
+                            val.addmember("Format").string(format.get());
+
+                        auto_arrayptr<char> nq(toUTF8(n->getNameQualifier()));
+                        if (nq.get())
+                            val.addmember("NameQualifier").string(nq.get());
 
-                    if (n != (*d)->getNameID())
-                        delete n;
+                        auto_arrayptr<char> spnq(toUTF8(n->getSPNameQualifier()));
+                        if (spnq.get())
+                            val.addmember("SPNameQualifier").string(spnq.get());
+
+                        auto_arrayptr<char> sppid(toUTF8(n->getSPProvidedID()));
+                        if (sppid.get())
+                            val.addmember("SPProvidedID").string(sppid.get());
+                    }
 
                     if (val.integer())
                         attr->getValues().add(val);
@@ -196,7 +196,8 @@ void DelegationExtractor::extractAttributes(
                 }
             }
 
-            attributes.push_back(attr.release());
+            attributes.push_back(attr.get());
+            attr.release();
         }
     }
 }
index b6008ab..545f8c7 100644 (file)
@@ -31,6 +31,7 @@
 #include "attribute/SimpleAttribute.h"
 #include "attribute/resolver/AttributeExtractor.h"
 
+#include <boost/iterator/indirect_iterator.hpp>
 #include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 #include <saml/saml2/metadata/MetadataProvider.h>
@@ -43,6 +44,7 @@ using namespace shibsp;
 using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -134,28 +136,34 @@ void KeyDescriptorExtractor::extractAttributes(
             if (!m_hashId.empty()) {
                 auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_hashId));
                 vector<string>& vals = attr->getValues();
-                for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
+                for (indirect_iterator<vector<const Credential*>::const_iterator> c = make_indirect_iterator(creds.begin());
+                        c != make_indirect_iterator(creds.end()); ++c) {
                     if (vals.empty() || !vals.back().empty())
                         vals.push_back(string());
-                    vals.back() = SecurityHelper::getDEREncoding(*(*c), m_hashAlg.c_str());
+                    vals.back() = SecurityHelper::getDEREncoding(*c, m_hashAlg.c_str());
                 }
                 if (vals.back().empty())
                     vals.pop_back();
-                if (!vals.empty())
-                    attributes.push_back(attr.release());
+                if (!vals.empty()) {
+                    attributes.push_back(attr.get());
+                    attr.release();
+                }
             }
             if (!m_signingId.empty()) {
                 auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_signingId));
                 vector<string>& vals = attr->getValues();
-                for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
+                for (indirect_iterator<vector<const Credential*>::const_iterator> c = make_indirect_iterator(creds.begin());
+                        c != make_indirect_iterator(creds.end()); ++c) {
                     if (vals.empty() || !vals.back().empty())
                         vals.push_back(string());
-                    vals.back() = SecurityHelper::getDEREncoding(*(*c));
+                    vals.back() = SecurityHelper::getDEREncoding(*c);
                 }
                 if (vals.back().empty())
                     vals.pop_back();
-                if (!vals.empty())
-                    attributes.push_back(attr.release());
+                if (!vals.empty()) {
+                    attributes.push_back(attr.get());
+                    attr.release();
+                }
             }
             creds.clear();
         }
@@ -166,15 +174,18 @@ void KeyDescriptorExtractor::extractAttributes(
         if (application.getMetadataProvider()->resolve(creds, &mcc)) {
             auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_encryptionId));
             vector<string>& vals = attr->getValues();
-            for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
+            for (indirect_iterator<vector<const Credential*>::const_iterator> c = make_indirect_iterator(creds.begin());
+                    c != make_indirect_iterator(creds.end()); ++c) {
                 if (vals.empty() || !vals.back().empty())
                     vals.push_back(string());
-                vals.back() = SecurityHelper::getDEREncoding(*(*c));
+                vals.back() = SecurityHelper::getDEREncoding(*c);
             }
             if (vals.back().empty())
                 vals.pop_back();
-            if (!vals.empty())
-                attributes.push_back(attr.release());
+            if (!vals.empty()) {
+                attributes.push_back(attr.get());
+                attr.release();
+            }
         }
     }
 }
index 2206b0a..6891fe0 100644 (file)
@@ -40,6 +40,9 @@
 #include "security/SecurityPolicyProvider.h"
 #include "util/SPConstants.h"
 
+#include <boost/scoped_ptr.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <saml/exceptions.h>
 #include <saml/saml1/binding/SAML1SOAPClient.h>
 #include <saml/saml1/core/Assertions.h>
@@ -63,6 +66,7 @@ using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -175,10 +179,7 @@ namespace shibsp {
     {
     public:
         QueryResolver(const DOMElement* e);
-        ~QueryResolver() {
-            for_each(m_SAML1Designators.begin(), m_SAML1Designators.end(), xmltooling::cleanup<AttributeDesignator>());
-            for_each(m_SAML2Designators.begin(), m_SAML2Designators.end(), xmltooling::cleanup<saml2::Attribute>());
-        }
+        ~QueryResolver() {}
 
         Lockable* lock() {return this;}
         void unlock() {}
@@ -213,8 +214,8 @@ namespace shibsp {
         Category& m_log;
         string m_policyId;
         bool m_subjectMatch;
-        vector<AttributeDesignator*> m_SAML1Designators;
-        vector<saml2::Attribute*> m_SAML2Designators;
+        ptr_vector<AttributeDesignator> m_SAML1Designators;
+        ptr_vector<saml2::Attribute> m_SAML2Designators;
         vector<string> m_exceptionId;
     };
 
@@ -289,20 +290,21 @@ void QueryResolver::SAML1Query(QueryContext& ctx) const
     const char* policyId = m_policyId.empty() ? application.getString("policyId").second : m_policyId.c_str();
 
     // Set up policy and SOAP client.
-    auto_ptr<SecurityPolicy> policy(
+    scoped_ptr<SecurityPolicy> policy(
         application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, nullptr, policyId)
         );
     policy->getAudiences().push_back(relyingParty->getXMLString("entityID").second);
     MetadataCredentialCriteria mcc(*AA);
-    shibsp::SOAPClient soaper(*policy.get());
+    shibsp::SOAPClient soaper(*policy);
 
     auto_ptr_XMLCh binding(samlconstants::SAML1_BINDING_SOAP);
-    saml1p::Response* response=nullptr;
+    auto_ptr<saml1p::Response> response;
     const vector<AttributeService*>& endpoints=AA->getAttributeServices();
-    for (vector<AttributeService*>::const_iterator ep=endpoints.begin(); !response && ep!=endpoints.end(); ++ep) {
-        if (!XMLString::equals((*ep)->getBinding(),binding.get()) || !(*ep)->getLocation())
+    for (indirect_iterator<vector<AttributeService*>::const_iterator> ep = make_indirect_iterator(endpoints.begin());
+            !response.get() && ep != make_indirect_iterator(endpoints.end()); ++ep) {
+        if (!XMLString::equals(ep->getBinding(), binding.get()) || !ep->getLocation())
             continue;
-        auto_ptr_char loc((*ep)->getLocation());
+        auto_ptr_char loc(ep->getLocation());
         try {
             NameIdentifier* nameid = NameIdentifierBuilder::buildNameIdentifier();
             nameid->setName(ctx.getNameID()->getName());
@@ -313,15 +315,18 @@ void QueryResolver::SAML1Query(QueryContext& ctx) const
             saml1p::AttributeQuery* query = saml1p::AttributeQueryBuilder::buildAttributeQuery();
             query->setSubject(subject);
             query->setResource(relyingParty->getXMLString("entityID").second);
-            for (vector<AttributeDesignator*>::const_iterator ad = m_SAML1Designators.begin(); ad!=m_SAML1Designators.end(); ++ad)
-                query->getAttributeDesignators().push_back((*ad)->cloneAttributeDesignator());
+            for (ptr_vector<AttributeDesignator>::const_iterator ad = m_SAML1Designators.begin(); ad != m_SAML1Designators.end(); ++ad) {
+                auto_ptr<AttributeDesignator> adwrapper(ad->cloneAttributeDesignator());
+                query->getAttributeDesignators().push_back(adwrapper.get());
+                adwrapper.release();
+            }
             Request* request = RequestBuilder::buildRequest();
             request->setAttributeQuery(query);
             request->setMinorVersion(version);
 
             SAML1SOAPClient client(soaper, false);
             client.sendSAML(request, application.getId(), mcc, loc.get());
-            response = client.receiveSAML();
+            response.reset(client.receiveSAML());
         }
         catch (exception& ex) {
             m_log.error("exception during SAML query to %s: %s", loc.get(), ex.what());
@@ -329,28 +334,25 @@ void QueryResolver::SAML1Query(QueryContext& ctx) const
         }
     }
 
-    if (!response) {
+    if (!response.get()) {
         m_log.error("unable to obtain a SAML response from attribute authority");
         throw BindingException("Unable to obtain a SAML response from attribute authority.");
     }
     else if (!response->getStatus() || !response->getStatus()->getStatusCode() || response->getStatus()->getStatusCode()->getValue()==nullptr ||
             *(response->getStatus()->getStatusCode()->getValue()) != saml1p::StatusCode::SUCCESS) {
-        delete response;
         m_log.error("attribute authority returned a SAML error");
         throw FatalProfileException("Attribute authority returned a SAML error.");
     }
 
-    const vector<saml1::Assertion*>& assertions = const_cast<const saml1p::Response*>(response)->getAssertions();
+    const vector<saml1::Assertion*>& assertions = const_cast<const saml1p::Response*>(response.get())->getAssertions();
     if (assertions.empty()) {
-        delete response;
         m_log.warn("response from attribute authority was empty");
         return;
     }
-    else if (assertions.size()>1) {
+    else if (assertions.size() > 1) {
         m_log.warn("simple resolver only supports one assertion in the query response");
     }
 
-    auto_ptr<saml1p::Response> wrapper(response);
     saml1::Assertion* newtoken = assertions.front();
 
     pair<bool,bool> signedAssertions = relyingParty->getBool("requireSignedAssertions");
@@ -378,7 +380,7 @@ void QueryResolver::SAML1Query(QueryContext& ctx) const
     }
 
     newtoken->detach();
-    wrapper.release();  // detach blows away the Response
+    response.release();  // detach blows away the Response
     ctx.getResolvedAssertions().push_back(newtoken);
 
     // Finally, extract and filter the result.
@@ -387,10 +389,11 @@ void QueryResolver::SAML1Query(QueryContext& ctx) const
         if (extractor) {
             Locker extlocker(extractor);
             const vector<saml1::AttributeStatement*>& statements = const_cast<const saml1::Assertion*>(newtoken)->getAttributeStatements();
-            for (vector<saml1::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
+            for (indirect_iterator<vector<saml1::AttributeStatement*>::const_iterator> s = make_indirect_iterator(statements.begin());
+                    s != make_indirect_iterator(statements.end()); ++s) {
                 if (m_subjectMatch) {
                     // Check for subject match.
-                    const NameIdentifier* respName = (*s)->getSubject() ? (*s)->getSubject()->getNameIdentifier() : nullptr;
+                    const NameIdentifier* respName = s->getSubject() ? s->getSubject()->getNameIdentifier() : nullptr;
                     if (!respName || !XMLString::equals(respName->getName(), ctx.getNameID()->getName()) ||
                         !XMLString::equals(respName->getFormat(), ctx.getNameID()->getFormat()) ||
                         !XMLString::equals(respName->getNameQualifier(), ctx.getNameID()->getNameQualifier())) {
@@ -402,7 +405,7 @@ void QueryResolver::SAML1Query(QueryContext& ctx) const
                         continue;
                     }
                 }
-                extractor->extractAttributes(application, AA, *(*s), ctx.getResolvedAttributes());
+                extractor->extractAttributes(application, AA, *s, ctx.getResolvedAttributes());
             }
         }
 
@@ -443,20 +446,21 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
     const char* policyId = m_policyId.empty() ? application.getString("policyId").second : m_policyId.c_str();
 
     // Set up policy and SOAP client.
-    auto_ptr<SecurityPolicy> policy(
+    scoped_ptr<SecurityPolicy> policy(
         application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, nullptr, policyId)
         );
     policy->getAudiences().push_back(relyingParty->getXMLString("entityID").second);
     MetadataCredentialCriteria mcc(*AA);
-    shibsp::SOAPClient soaper(*policy.get());
+    shibsp::SOAPClient soaper(*policy);
 
     auto_ptr_XMLCh binding(samlconstants::SAML20_BINDING_SOAP);
-    saml2p::StatusResponseType* srt=nullptr;
+    auto_ptr<saml2p::StatusResponseType> srt;
     const vector<AttributeService*>& endpoints=AA->getAttributeServices();
-    for (vector<AttributeService*>::const_iterator ep=endpoints.begin(); !srt && ep!=endpoints.end(); ++ep) {
-        if (!XMLString::equals((*ep)->getBinding(),binding.get())  || !(*ep)->getLocation())
+    for (indirect_iterator<vector<AttributeService*>::const_iterator> ep = make_indirect_iterator(endpoints.begin());
+            !srt.get() && ep != make_indirect_iterator(endpoints.end()); ++ep) {
+        if (!XMLString::equals(ep->getBinding(), binding.get())  || !ep->getLocation())
             continue;
-        auto_ptr_char loc((*ep)->getLocation());
+        auto_ptr_char loc(ep->getLocation());
         try {
             auto_ptr<saml2::Subject> subject(saml2::SubjectBuilder::buildSubject());
 
@@ -470,10 +474,13 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
                     false,
                     relyingParty->getXMLString("encryptionAlg").second
                     );
-                subject->setEncryptedID(encrypted.release());
+                subject->setEncryptedID(encrypted.get());
+                encrypted.release();
             }
             else {
-                subject->setNameID(ctx.getNameID()->cloneNameID());
+                auto_ptr<NameID> namewrapper(ctx.getNameID()->cloneNameID());
+                subject->setNameID(namewrapper.get());
+                namewrapper.release();
             }
 
             saml2p::AttributeQuery* query = saml2p::AttributeQueryBuilder::buildAttributeQuery();
@@ -481,12 +488,15 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
             Issuer* iss = IssuerBuilder::buildIssuer();
             iss->setName(relyingParty->getXMLString("entityID").second);
             query->setIssuer(iss);
-            for (vector<saml2::Attribute*>::const_iterator ad = m_SAML2Designators.begin(); ad!=m_SAML2Designators.end(); ++ad)
-                query->getAttributes().push_back((*ad)->cloneAttribute());
+            for (ptr_vector<saml2::Attribute>::const_iterator ad = m_SAML2Designators.begin(); ad != m_SAML2Designators.end(); ++ad) {
+                auto_ptr<saml2::Attribute> adwrapper(ad->cloneAttribute());
+                query->getAttributes().push_back(adwrapper.get());
+                adwrapper.release();
+            }
 
             SAML2SOAPClient client(soaper, false);
             client.sendSAML(query, application.getId(), mcc, loc.get());
-            srt = client.receiveSAML();
+            srt.reset(client.receiveSAML());
         }
         catch (exception& ex) {
             m_log.error("exception during SAML query to %s: %s", loc.get(), ex.what());
@@ -494,14 +504,12 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
         }
     }
 
-    if (!srt) {
+    if (!srt.get()) {
         m_log.error("unable to obtain a SAML response from attribute authority");
         throw BindingException("Unable to obtain a SAML response from attribute authority.");
     }
 
-    auto_ptr<saml2p::StatusResponseType> wrapper(srt);
-
-    saml2p::Response* response = dynamic_cast<saml2p::Response*>(srt);
+    saml2p::Response* response = dynamic_cast<saml2p::Response*>(srt.get());
     if (!response) {
         m_log.error("message was not a samlp:Response");
         throw FatalProfileException("Attribute authority returned an unrecognized message.");
@@ -513,6 +521,7 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
     }
 
     saml2::Assertion* newtoken = nullptr;
+    auto_ptr<saml2::Assertion> newtokenwrapper;
     const vector<saml2::Assertion*>& assertions = const_cast<const saml2p::Response*>(response)->getAssertions();
     if (assertions.empty()) {
         // Check for encryption.
@@ -538,10 +547,9 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
             newtoken = dynamic_cast<saml2::Assertion*>(tokenwrapper.get());
             if (newtoken) {
                 tokenwrapper.release();
+                newtokenwrapper.reset(newtoken);
                 if (m_log.isDebugEnabled())
                     m_log.debugStream() << "decrypted Assertion: " << *newtoken << logging::eol;
-                // Free the Response now, so we know this is a stand-alone token later.
-                delete wrapper.release();
             }
         }
         catch (exception& ex) {
@@ -557,8 +565,6 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
 
     if (!newtoken->getSignature() && signedAssertions.first && signedAssertions.second) {
         m_log.error("assertion unsigned, rejecting it based on signedAssertions policy");
-        if (!wrapper.get())
-            delete newtoken;
         throw SecurityPolicyException("Rejected unsigned assertion based on local policy.");
     }
 
@@ -577,7 +583,7 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
 
         if (m_subjectMatch) {
             // Check for subject match.
-            bool ownedName = false;
+            auto_ptr<NameID> nameIDwrapper;
             NameID* respName = newtoken->getSubject() ? newtoken->getSubject()->getNameID() : nullptr;
             if (!respName) {
                 // Check for encryption.
@@ -591,8 +597,8 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
                         auto_ptr<XMLObject> decryptedID(encname->decrypt(*cr, relyingParty->getXMLString("entityID").second, &mcc));
                         respName = dynamic_cast<NameID*>(decryptedID.get());
                         if (respName) {
-                            ownedName = true;
                             decryptedID.release();
+                            nameIDwrapper.reset(respName);
                             if (m_log.isDebugEnabled())
                                 m_log.debugStream() << "decrypted NameID: " << *respName << logging::eol;
                         }
@@ -600,8 +606,6 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
                 }
             }
 
-            auto_ptr<NameID> nameIDwrapper(ownedName ? respName : nullptr);
-
             if (!respName || !XMLString::equals(respName->getName(), ctx.getNameID()->getName()) ||
                 !XMLString::equals(respName->getFormat(), ctx.getNameID()->getFormat()) ||
                 !XMLString::equals(respName->getNameQualifier(), ctx.getNameID()->getNameQualifier()) ||
@@ -611,24 +615,23 @@ void QueryResolver::SAML2Query(QueryContext& ctx) const
                         *respName << logging::eol;
                 else
                     m_log.warn("ignoring Assertion without NameID in Subject");
-                if (!wrapper.get())
-                    delete newtoken;
                 return;
             }
         }
     }
     catch (exception& ex) {
         m_log.error("assertion failed policy validation: %s", ex.what());
-        if (!wrapper.get())
-            delete newtoken;
         throw;
     }
 
-    if (wrapper.get()) {
+    // If the token's embedded, detach it.
+    if (!newtokenwrapper.get()) {
         newtoken->detach();
-        wrapper.release();  // detach blows away the Response
+        srt.release();  // detach blows away the Response, so avoid a double free
+        newtokenwrapper.reset(newtoken);
     }
     ctx.getResolvedAssertions().push_back(newtoken);
+    newtokenwrapper.release();
 
     // Finally, extract and filter the result.
     try {
@@ -687,9 +690,10 @@ void QueryResolver::resolveAttributes(ResolutionContext& ctx) const
     catch (exception& ex) {
         // Already logged.
         if (!m_exceptionId.empty()) {
-            SimpleAttribute* attr = new SimpleAttribute(m_exceptionId);
+            auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_exceptionId));
             attr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
-            qctx.getResolvedAttributes().push_back(attr);
+            qctx.getResolvedAttributes().push_back(attr.get());
+            attr.release();
         }
     }
 }
index 8d6b5bf..253b187 100644 (file)
 #include "security/SecurityPolicyProvider.h"
 #include "util/SPConstants.h"
 
+#include <boost/scoped_ptr.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <saml/exceptions.h>
 #include <saml/SAMLConfig.h>
 #include <saml/saml2/binding/SAML2SOAPClient.h>
@@ -62,6 +66,7 @@ using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -73,9 +78,8 @@ namespace shibsp {
             : m_app(application),
               m_session(&session),
               m_nameid(nullptr),
-              m_entityid(nullptr),
-              m_class(XMLString::transcode(session.getAuthnContextClassRef())),
-              m_decl(XMLString::transcode(session.getAuthnContextDeclRef())),
+              m_class(session.getAuthnContextClassRef()),
+              m_decl(session.getAuthnContextDeclRef()),
               m_inputTokens(nullptr),
               m_inputAttributes(nullptr) {
         }
@@ -91,9 +95,9 @@ namespace shibsp {
             ) : m_app(application),
                 m_session(nullptr),
                 m_nameid(nameid),
-                m_entityid(entityID ? XMLString::transcode(entityID) : nullptr),
-                m_class(const_cast<XMLCh*>(authncontext_class)),
-                m_decl(const_cast<XMLCh*>(authncontext_decl)),
+                m_entityid(entityID),
+                m_class(authncontext_class),
+                m_decl(authncontext_decl),
                 m_inputTokens(tokens),
                 m_inputAttributes(attributes) {
         }
@@ -101,27 +105,22 @@ namespace shibsp {
         ~SimpleAggregationContext() {
             for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<shibsp::Attribute>());
             for_each(m_assertions.begin(), m_assertions.end(), xmltooling::cleanup<opensaml::Assertion>());
-            if (m_session) {
-                XMLString::release(&m_class);
-                XMLString::release(&m_decl);
-            }
-            XMLString::release(&m_entityid);
         }
 
         const Application& getApplication() const {
             return m_app;
         }
         const char* getEntityID() const {
-            return m_session ? m_session->getEntityID() : m_entityid;
+            return m_session ? m_session->getEntityID() : m_entityid.get();
         }
         const NameID* getNameID() const {
             return m_session ? m_session->getNameID() : m_nameid;
         }
         const XMLCh* getClassRef() const {
-            return m_class;
+            return m_class.get();
         }
         const XMLCh* getDeclRef() const {
-            return m_decl;
+            return m_decl.get();
         }
         const Session* getSession() const {
             return m_session;
@@ -143,9 +142,9 @@ namespace shibsp {
         const Application& m_app;
         const Session* m_session;
         const NameID* m_nameid;
-        char* m_entityid;
-        XMLCh* m_class;
-        XMLCh* m_decl;
+        auto_ptr_char m_entityid;
+        auto_ptr_XMLCh m_class;
+        auto_ptr_XMLCh m_decl;
         const vector<const opensaml::Assertion*>* m_inputTokens;
         const vector<shibsp::Attribute*>* m_inputAttributes;
         vector<shibsp::Attribute*> m_attributes;
@@ -156,11 +155,7 @@ namespace shibsp {
     {
     public:
         SimpleAggregationResolver(const DOMElement* e);
-        ~SimpleAggregationResolver() {
-            delete m_trust;
-            delete m_metadata;
-            for_each(m_designators.begin(), m_designators.end(), xmltooling::cleanup<saml2::Attribute>());
-        }
+        ~SimpleAggregationResolver() {}
 
         Lockable* lock() {return this;}
         void unlock() {}
@@ -198,9 +193,9 @@ namespace shibsp {
         bool m_subjectMatch;
         vector<string> m_attributeIds;
         xstring m_format;
-        MetadataProvider* m_metadata;
-        TrustEngine* m_trust;
-        vector<saml2::Attribute*> m_designators;
+        scoped_ptr<MetadataProvider> m_metadata;
+        scoped_ptr<TrustEngine> m_trust;
+        ptr_vector<saml2::Attribute> m_designators;
         vector< pair<string,bool> > m_sources;
         vector<string> m_exceptionId;
     };
@@ -225,8 +220,7 @@ namespace shibsp {
 SimpleAggregationResolver::SimpleAggregationResolver(const DOMElement* e)
     : m_log(Category::getInstance(SHIBSP_LOGCAT".AttributeResolver.SimpleAggregation")),
         m_policyId(XMLHelper::getAttrString(e, nullptr, policyId)),
-        m_subjectMatch(XMLHelper::getAttrBool(e, false, subjectMatch)),
-        m_metadata(nullptr), m_trust(nullptr)
+        m_subjectMatch(XMLHelper::getAttrBool(e, false, subjectMatch))
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("SimpleAggregationResolver");
@@ -234,21 +228,9 @@ SimpleAggregationResolver::SimpleAggregationResolver(const DOMElement* e)
 
     const XMLCh* aid = e ? e->getAttributeNS(nullptr, attributeId) : nullptr;
     if (aid && *aid) {
-        char* dup = XMLString::transcode(aid);
-        char* pos;
-        char* start = dup;
-        while (start && *start) {
-            while (*start && isspace(*start))
-                start++;
-            if (!*start)
-                break;
-            pos = strchr(start,' ');
-            if (pos)
-                *pos=0;
-            m_attributeIds.push_back(start);
-            start = pos ? pos+1 : nullptr;
-        }
-        XMLString::release(&dup);
+        auto_ptr_char dup(aid);
+        string sdup(dup.get());
+        split(m_attributeIds, sdup, is_space(), algorithm::token_compress_on);
 
         aid = e->getAttributeNS(nullptr, format);
         if (aid && *aid)
@@ -265,24 +247,17 @@ SimpleAggregationResolver::SimpleAggregationResolver(const DOMElement* e)
         if (t.empty())
             throw ConfigurationException("MetadataProvider element missing type attribute.");
         m_log.info("building MetadataProvider of type %s...", t.c_str());
-        auto_ptr<MetadataProvider> mp(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(t.c_str(), child));
-        mp->init();
-        m_metadata = mp.release();
+        m_metadata.reset(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(t.c_str(), child));
+        m_metadata->init();
     }
 
     child = XMLHelper::getFirstChildElement(e,  _TrustEngine);
     if (child) {
-        try {
-            string t(XMLHelper::getAttrString(child, nullptr, _type));
-            if (t.empty())
-                throw ConfigurationException("TrustEngine element missing type attribute.");
-            m_log.info("building TrustEngine of type %s...", t.c_str());
-            m_trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child);
-        }
-        catch (exception&) {
-            delete m_metadata;
-            throw;
-        }
+        string t(XMLHelper::getAttrString(child, nullptr, _type));
+        if (t.empty())
+            throw ConfigurationException("TrustEngine element missing type attribute.");
+        m_log.info("building TrustEngine of type %s...", t.c_str());
+        m_trust.reset(XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child));
     }
 
     child = XMLHelper::getFirstChildElement(e);
@@ -310,7 +285,7 @@ SimpleAggregationResolver::SimpleAggregationResolver(const DOMElement* e)
                     obj.release();
                 }
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("exception loading attribute designator: %s", ex.what());
             }
         }
@@ -325,10 +300,10 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
 #endif
     const Application& application = ctx.getApplication();
     MetadataProviderCriteria mc(application, entityID, &AttributeAuthorityDescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS);
-    Locker mlocker(m_metadata);
+    Locker mlocker(m_metadata.get());
     const AttributeAuthorityDescriptor* AA=nullptr;
     pair<const EntityDescriptor*,const RoleDescriptor*> mdresult =
-        (m_metadata ? m_metadata : application.getMetadataProvider())->getEntityDescriptor(mc);
+        (m_metadata ? m_metadata.get() : application.getMetadataProvider())->getEntityDescriptor(mc);
     if (!mdresult.first) {
         m_log.warn("unable to locate metadata for provider (%s)", entityID);
         return;
@@ -346,25 +321,26 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
     const char* policyId = m_policyId.empty() ? application.getString("policyId").second : m_policyId.c_str();
 
     // Set up policy and SOAP client.
-    auto_ptr<SecurityPolicy> policy(
+    scoped_ptr<SecurityPolicy> policy(
         application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, nullptr, policyId)
         );
     if (m_metadata)
-        policy->setMetadataProvider(m_metadata);
+        policy->setMetadataProvider(m_metadata.get());
     if (m_trust)
-        policy->setTrustEngine(m_trust);
+        policy->setTrustEngine(m_trust.get());
     policy->getAudiences().push_back(relyingParty->getXMLString("entityID").second);
 
     MetadataCredentialCriteria mcc(*AA);
     shibsp::SOAPClient soaper(*policy.get());
 
     auto_ptr_XMLCh binding(samlconstants::SAML20_BINDING_SOAP);
-    saml2p::StatusResponseType* srt=nullptr;
+    auto_ptr<saml2p::StatusResponseType> srt;
     const vector<AttributeService*>& endpoints=AA->getAttributeServices();
-    for (vector<AttributeService*>::const_iterator ep=endpoints.begin(); !srt && ep!=endpoints.end(); ++ep) {
-        if (!XMLString::equals((*ep)->getBinding(),binding.get())  || !(*ep)->getLocation())
+    for (indirect_iterator<vector<AttributeService*>::const_iterator> ep = make_indirect_iterator(endpoints.begin());
+            !srt.get() && ep != make_indirect_iterator(endpoints.end()); ++ep) {
+        if (!XMLString::equals(ep->getBinding(), binding.get())  || !ep->getLocation())
             continue;
-        auto_ptr_char loc((*ep)->getLocation());
+        auto_ptr_char loc(ep->getLocation());
         try {
             auto_ptr<saml2::Subject> subject(saml2::SubjectBuilder::buildSubject());
 
@@ -378,7 +354,8 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
                     false,
                     relyingParty->getXMLString("encryptionAlg").second
                     );
-                subject->setEncryptedID(encrypted.release());
+                subject->setEncryptedID(encrypted.get());
+                encrypted.release();
             }
             else {
                 subject->setNameID(name->cloneNameID());
@@ -389,27 +366,28 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
             Issuer* iss = IssuerBuilder::buildIssuer();
             iss->setName(relyingParty->getXMLString("entityID").second);
             query->setIssuer(iss);
-            for (vector<saml2::Attribute*>::const_iterator ad = m_designators.begin(); ad!=m_designators.end(); ++ad)
-                query->getAttributes().push_back((*ad)->cloneAttribute());
+            for (ptr_vector<saml2::Attribute>::const_iterator ad = m_designators.begin(); ad != m_designators.end(); ++ad) {
+                auto_ptr<saml2::Attribute> adwrapper(ad->cloneAttribute());
+                query->getAttributes().push_back(adwrapper.get());
+                adwrapper.release();
+            }
 
             SAML2SOAPClient client(soaper, false);
             client.sendSAML(query, application.getId(), mcc, loc.get());
-            srt = client.receiveSAML();
+            srt.reset(client.receiveSAML());
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error("exception during SAML query to %s: %s", loc.get(), ex.what());
             soaper.reset();
         }
     }
 
-    if (!srt) {
+    if (!srt.get()) {
         m_log.error("unable to obtain a SAML response from attribute authority (%s)", entityID);
         throw BindingException("Unable to obtain a SAML response from attribute authority.");
     }
 
-    auto_ptr<saml2p::StatusResponseType> wrapper(srt);
-
-    saml2p::Response* response = dynamic_cast<saml2p::Response*>(srt);
+    saml2p::Response* response = dynamic_cast<saml2p::Response*>(srt.get());
     if (!response) {
         m_log.error("message was not a samlp:Response");
         throw FatalProfileException("Attribute authority returned an unrecognized message.");
@@ -421,6 +399,7 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
     }
 
     saml2::Assertion* newtoken = nullptr;
+    auto_ptr<saml2::Assertion> newtokenwrapper;
     const vector<saml2::Assertion*>& assertions = const_cast<const saml2p::Response*>(response)->getAssertions();
     if (assertions.empty()) {
         // Check for encryption.
@@ -447,13 +426,12 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
             newtoken = dynamic_cast<saml2::Assertion*>(tokenwrapper.get());
             if (newtoken) {
                 tokenwrapper.release();
+                newtokenwrapper.reset(newtoken);
                 if (m_log.isDebugEnabled())
                     m_log.debugStream() << "decrypted Assertion: " << *newtoken << logging::eol;
-                // Free the Response now, so we know this is a stand-alone token later.
-                delete wrapper.release();
             }
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error(ex.what());
             throw;
         }
@@ -466,8 +444,6 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
 
     if (!newtoken->getSignature() && signedAssertions.first && signedAssertions.second) {
         m_log.error("assertion unsigned, rejecting it based on signedAssertions policy");
-        if (!wrapper.get())
-            delete newtoken;
         throw SecurityPolicyException("Rejected unsigned assertion based on local policy.");
     }
 
@@ -486,7 +462,7 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
 
         if (m_subjectMatch) {
             // Check for subject match.
-            bool ownedName = false;
+            auto_ptr<NameID> nameIDwrapper;
             NameID* respName = newtoken->getSubject() ? newtoken->getSubject()->getNameID() : nullptr;
             if (!respName) {
                 // Check for encryption.
@@ -500,8 +476,8 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
                         auto_ptr<XMLObject> decryptedID(encname->decrypt(*cr, relyingParty->getXMLString("entityID").second, &mcc));
                         respName = dynamic_cast<NameID*>(decryptedID.get());
                         if (respName) {
-                            ownedName = true;
                             decryptedID.release();
+                            nameIDwrapper.reset(respName);
                             if (m_log.isDebugEnabled())
                                 m_log.debugStream() << "decrypted NameID: " << *respName << logging::eol;
                         }
@@ -509,8 +485,6 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
                 }
             }
 
-            auto_ptr<NameID> nameIDwrapper(ownedName ? respName : nullptr);
-
             if (!respName || !XMLString::equals(respName->getName(), name->getName()) ||
                 !XMLString::equals(respName->getFormat(), name->getFormat()) ||
                 !XMLString::equals(respName->getNameQualifier(), name->getNameQualifier()) ||
@@ -520,24 +494,23 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
                         *respName << logging::eol;
                 else
                     m_log.warn("ignoring Assertion without NameID in Subject");
-                if (!wrapper.get())
-                    delete newtoken;
                 return;
             }
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("assertion failed policy validation: %s", ex.what());
-        if (!wrapper.get())
-            delete newtoken;
         throw;
     }
 
-    if (wrapper.get()) {
+    // If the token's embedded, detach it.
+    if (!newtokenwrapper.get()) {
         newtoken->detach();
-        wrapper.release();  // detach blows away the Response
+        srt.release();  // detach blows away the Response, so avoid a double free
+        newtokenwrapper.reset(newtoken);
     }
     ctx.getResolvedAssertions().push_back(newtoken);
+    newtokenwrapper.release();
 
     // Finally, extract and filter the result.
     try {
@@ -554,7 +527,7 @@ void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const cha
             filter->filterAttributes(fc, ctx.getResolvedAttributes());
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what());
         for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup<shibsp::Attribute>());
         ctx.getResolvedAttributes().clear();
@@ -571,8 +544,8 @@ void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
     SimpleAggregationContext& qctx = dynamic_cast<SimpleAggregationContext&>(ctx);
 
     // First we manufacture the appropriate NameID to use.
-    NameID* n=nullptr;
-    for (vector<string>::const_iterator a = m_attributeIds.begin(); !n && a != m_attributeIds.end(); ++a) {
+    scoped_ptr<NameID> n;
+    for (vector<string>::const_iterator a = m_attributeIds.begin(); !n.get() && a != m_attributeIds.end(); ++a) {
         const Attribute* attr=nullptr;
         if (qctx.getSession()) {
             // Input attributes should be available via multimap.
@@ -586,48 +559,44 @@ void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
         else if (qctx.getInputAttributes()) {
             // Have to loop over unindexed set.
             const vector<Attribute*>* matches = qctx.getInputAttributes();
-            for (vector<Attribute*>::const_iterator match = matches->begin(); !attr && match != matches->end(); ++match) {
-                if (*a == (*match)->getId() && (*match)->valueCount() > 0)
-                    attr = *match;
+            for (indirect_iterator<vector<Attribute*>::const_iterator> match = make_indirect_iterator(matches->begin());
+                    !attr && match != make_indirect_iterator(matches->end()); ++match) {
+                if (*a == match->getId() && match->valueCount() > 0)
+                    attr = &(*match);
             }
         }
 
         if (attr) {
             m_log.debug("using input attribute (%s) as identifier for queries", attr->getId());
-            n = NameIDBuilder::buildNameID();
+            n.reset(NameIDBuilder::buildNameID());
             const NameIDAttribute* down = dynamic_cast<const NameIDAttribute*>(attr);
             if (down) {
                 // We can create a NameID directly from the source material.
                 const NameIDAttribute::Value& v = down->getValues().front();
-                XMLCh* val = fromUTF8(v.m_Name.c_str());
-                n->setName(val);
-                delete[] val;
+                auto_arrayptr<XMLCh> val(fromUTF8(v.m_Name.c_str()));
+                n->setName(val.get());
+
                 if (!v.m_Format.empty()) {
-                    val = fromUTF8(v.m_Format.c_str());
-                    n->setFormat(val);
-                    delete[] val;
+                    auto_arrayptr<XMLCh> format(fromUTF8(v.m_Format.c_str()));
+                    n->setFormat(format.get());
                 }
                 if (!v.m_NameQualifier.empty()) {
-                    val = fromUTF8(v.m_NameQualifier.c_str());
-                    n->setNameQualifier(val);
-                    delete[] val;
+                    auto_arrayptr<XMLCh> nq(fromUTF8(v.m_NameQualifier.c_str()));
+                    n->setNameQualifier(nq.get());
                 }
                 if (!v.m_SPNameQualifier.empty()) {
-                    val = fromUTF8(v.m_SPNameQualifier.c_str());
-                    n->setSPNameQualifier(val);
-                    delete[] val;
+                    auto_arrayptr<XMLCh> spnq(fromUTF8(v.m_SPNameQualifier.c_str()));
+                    n->setSPNameQualifier(spnq.get());
                 }
                 if (!v.m_SPProvidedID.empty()) {
-                    val = fromUTF8(v.m_SPProvidedID.c_str());
-                    n->setSPProvidedID(val);
-                    delete[] val;
+                    auto_arrayptr<XMLCh> sppid(fromUTF8(v.m_SPProvidedID.c_str()));
+                    n->setSPProvidedID(sppid.get());
                 }
             }
             else {
                 // We have to mock up the NameID.
-                XMLCh* val = fromUTF8(attr->getSerializedValues().front().c_str());
-                n->setName(val);
-                delete[] val;
+                auto_arrayptr<XMLCh> val(fromUTF8(attr->getSerializedValues().front().c_str()));
+                n->setName(val.get());
                 if (!m_format.empty())
                     n->setFormat(m_format.c_str());
             }
@@ -644,8 +613,6 @@ void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
         }
     }
 
-    auto_ptr<NameID> wrapper(n);
-
     set<string> history;
 
     // Put initial IdP into history to prevent extra query.
@@ -653,11 +620,9 @@ void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
         history.insert(qctx.getEntityID());
 
     // Prepare to track exceptions.
-    SimpleAttribute* exceptAttr = nullptr;
-    if (!m_exceptionId.empty()) {
-        exceptAttr = new SimpleAttribute(m_exceptionId);
-    }
-    auto_ptr<Attribute> exceptWrapper(exceptAttr);
+    auto_ptr<SimpleAttribute> exceptAttr;
+    if (!m_exceptionId.empty())
+        exceptAttr.reset(new SimpleAttribute(m_exceptionId));
 
     // We have a master loop over all the possible sources of material.
     for (vector< pair<string,bool> >::const_iterator source = m_sources.begin(); source != m_sources.end(); ++source) {
@@ -666,10 +631,10 @@ void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
             if (history.count(source->first) == 0) {
                 m_log.debug("issuing SAML query to (%s)", source->first.c_str());
                 try {
-                    doQuery(qctx, source->first.c_str(), n ? n : qctx.getNameID());
+                    doQuery(qctx, source->first.c_str(), n ? n.get() : qctx.getNameID());
                 }
-                catch (exception& ex) {
-                    if (exceptAttr)
+                catch (std::exception& ex) {
+                    if (exceptAttr.get())
                         exceptAttr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
                 }
                 history.insert(source->first);
@@ -690,10 +655,10 @@ void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
                         if (history.count(*link) == 0) {
                             m_log.debug("issuing SAML query to (%s)", link->c_str());
                             try {
-                                doQuery(qctx, link->c_str(), n ? n : qctx.getNameID());
+                                doQuery(qctx, link->c_str(), n ? n.get() : qctx.getNameID());
                             }
-                            catch (exception& ex) {
-                                if (exceptAttr)
+                            catch (std::exception& ex) {
+                                if (exceptAttr.get())
                                     exceptAttr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
                             }
                             history.insert(*link);
@@ -707,17 +672,18 @@ void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
             else if (qctx.getInputAttributes()) {
                 // Have to loop over unindexed set.
                 const vector<Attribute*>* matches = qctx.getInputAttributes();
-                for (vector<Attribute*>::const_iterator match = matches->begin(); match != matches->end(); ++match) {
-                    if (source->first == (*match)->getId()) {
-                        const vector<string>& links = (*match)->getSerializedValues();
+                for (indirect_iterator<vector<Attribute*>::const_iterator> match = make_indirect_iterator(matches->begin());
+                        match != make_indirect_iterator(matches->end()); ++match) {
+                    if (source->first == match->getId()) {
+                        const vector<string>& links = match->getSerializedValues();
                         for (vector<string>::const_iterator link = links.begin(); link != links.end(); ++link) {
                             if (history.count(*link) == 0) {
                                 m_log.debug("issuing SAML query to (%s)", link->c_str());
                                 try {
-                                    doQuery(qctx, link->c_str(), n ? n : qctx.getNameID());
+                                    doQuery(qctx, link->c_str(), n ? n.get() : qctx.getNameID());
                                 }
-                                catch (exception& ex) {
-                                    if (exceptAttr)
+                                catch (std::exception& ex) {
+                                    if (exceptAttr.get())
                                         exceptAttr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
                                 }
                                 history.insert(*link);
@@ -732,7 +698,8 @@ void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
         }
     }
 
-    if (exceptAttr) {
-        qctx.getResolvedAttributes().push_back(exceptWrapper.release());
+    if (exceptAttr.get()) {
+        qctx.getResolvedAttributes().push_back(exceptAttr.get());
+        exceptAttr.release();
     }
 }
index 37906ee..fdb3025 100644 (file)
@@ -656,7 +656,7 @@ void XMLExtractorImpl::extractAttributes(
             ) const = &XMLExtractorImpl::extractAttributes;
         for_each(
             make_indirect_iterator(container->getAttributes().begin()), make_indirect_iterator(container->getAttributes().end()),
-            boost::bind(extractV2Attr, this, boost::ref(application), nullptr, relyingParty, _1, boost::ref(holding))
+            boost::bind(extractV2Attr, this, boost::ref(application), (const char*)nullptr, relyingParty, _1, boost::ref(holding))
             );
 
         if (entityID && m_entityAssertions) {
index 579149f..d00a6f7 100644 (file)
@@ -30,6 +30,8 @@
 #include <shibsp/handler/AbstractHandler.h>
 #include <shibsp/handler/RemotedHandler.h>
 
+#include <boost/scoped_ptr.hpp>
+
 #ifndef SHIBSP_LITE
 namespace opensaml {
     class SAML_API Assertion;
@@ -242,8 +244,7 @@ namespace shibsp {
             ) const;
                 
 #ifndef SHIBSP_LITE
-        opensaml::MessageDecoder* m_decoder;
-        xmltooling::QName m_role;
+        boost::scoped_ptr<opensaml::MessageDecoder> m_decoder;
 #endif
     };
 
index 3a522e7..3abe148 100644 (file)
@@ -38,6 +38,9 @@
 
 #include <vector>
 #include <fstream>
+#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/PathResolver.h>
 #include <xmltooling/util/URLEncoder.h>
@@ -68,6 +71,7 @@ using namespace shibsp;
 using namespace samlconstants;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -91,10 +95,8 @@ namespace shibsp {
             int port = request.getPort();
             const char* scheme = request.getScheme();
             string root = string(scheme) + "://" + request.getHostname();
-            if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
-                ostringstream portstr;
-                portstr << port;
-                root += ":" + portstr.str();
+            if ((!strcmp(scheme, "http") && port != 80) || (!strcmp(scheme, "https") && port != 443)) {
+                root += ":" + lexical_cast<string>(port);
             }
             url = root + url;
         }
@@ -132,9 +134,9 @@ namespace shibsp {
                     else if (!strcmp(httpRequest.getScheme(), "http") && httpRequest.getPort() == 80) {
                         whitelist.push_back(string("http://") + httpRequest.getHostname() + '/');
                     }
-                    ostringstream portstr;
-                    portstr << httpRequest.getPort();
-                    whitelist.push_back(string(httpRequest.getScheme()) + "://" + httpRequest.getHostname() + ':' + portstr.str() + '/');
+                    whitelist.push_back(
+                        string(httpRequest.getScheme()) + "://" + httpRequest.getHostname() + ':' + lexical_cast<string>(httpRequest.getPort()) + '/'
+                        );
                 }
                 else if (!strcmp(relayStateLimit.second, "host")) {
                     // Allow any scheme or port.
@@ -147,20 +149,8 @@ namespace shibsp {
                     // Literal set of comparisons to use.
                     pair<bool,const char*> whitelistval = sessionProps->getString("relayStateWhitelist");
                     if (whitelistval.first) {
-#ifdef HAVE_STRTOK_R
-                        char* pos=nullptr;
-                        const char* token = strtok_r(const_cast<char*>(whitelistval.second), " ", &pos);
-#else
-                        const char* token = strtok(const_cast<char*>(whitelistval.second), " ");
-#endif
-                        while (token) {
-                            whitelist.push_back(token);
-#ifdef HAVE_STRTOK_R
-                            token = strtok_r(nullptr, " ", &pos);
-#else
-                            token = strtok(nullptr, " ");
-#endif
-                        }
+                        string dup(whitelistval.second);
+                        split(whitelist, dup, is_space(), algorithm::token_compress_on);
                     }
                 }
                 else {
@@ -168,14 +158,12 @@ namespace shibsp {
                     throw opensaml::SecurityPolicyException("Unrecognized relayStateLimit setting.");
                 }
 
-                for (vector<string>::const_iterator w = whitelist.begin(); w != whitelist.end(); ++w) {
-                    if (XMLString::startsWithI(relayState, w->c_str())) {
-                        return;
-                    }
+                static bool (*startsWithI)(const char*,const char*) = XMLString::startsWithI;
+                if (find_if(whitelist.begin(), whitelist.end(),
+                        boost::bind(startsWithI, relayState, boost::bind(&string::c_str, _1))) == whitelist.end()) {
+                    log.warn("relayStateLimit policy (%s), blocked redirect to (%s)", relayStateLimit.second, relayState);
+                    throw opensaml::SecurityPolicyException("Blocked unacceptable redirect location.");
                 }
-
-                log.warn("relayStateLimit policy (%s), blocked redirect to (%s)", relayStateLimit.second, relayState);
-                throw opensaml::SecurityPolicyException("Blocked unacceptable redirect location.");
             }
         }
     }
@@ -276,9 +264,9 @@ void Handler::preserveRelayState(const Application& application, HTTPResponse& r
             string stateval = urlenc->encode(relayState.c_str()) + shib_cookie.second;
             // Generate a random key for the cookie name instead of the fixed name.
             string rsKey;
-            generateRandomHex(rsKey,5);
+            generateRandomHex(rsKey, 5);
             shib_cookie.first = "_shibstate_" + rsKey;
-            response.setCookie(shib_cookie.first.c_str(),stateval.c_str());
+            response.setCookie(shib_cookie.first.c_str(), stateval.c_str());
             relayState = "cookie:" + rsKey;
         }
     }
@@ -439,7 +427,7 @@ 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) {
-    load(e,nullptr,filter,remapper);
+    load(e, nullptr, filter, remapper);
 }
 
 AbstractHandler::~AbstractHandler()
@@ -649,7 +637,7 @@ void AbstractHandler::preservePostData(
             if (storage) {
                 // Use a random key
                 string rsKey;
-                SAMLConfig::getConfig().generateRandomBytes(rsKey,32);
+                SAMLConfig::getConfig().generateRandomBytes(rsKey, 32);
                 rsKey = SAMLArtifact::toHex(rsKey);
                 ostringstream out;
                 out << postData;
@@ -809,7 +797,7 @@ DDF AbstractHandler::getPostData(const Application& application, const HTTPReque
 {
     string contentType = request.getContentType();
     if (contentType.find("application/x-www-form-urlencoded") != string::npos) {
-        const PropertySet* props=application.getPropertySet("Sessions");
+        const PropertySet* props = application.getPropertySet("Sessions");
         pair<bool,unsigned int> plimit = props ? props->getUnsignedInt("postLimit") : pair<bool,unsigned int>(false,0);
         if (!plimit.first)
             plimit.second = 1024 * 1024;
@@ -884,8 +872,14 @@ pair<bool,unsigned int> AbstractHandler::getUnsignedInt(const char* name, const
 {
     if (type & HANDLER_PROPERTY_REQUEST) {
         const char* param = request.getParameter(name);
-        if (param && *param)
-            return pair<bool,unsigned int>(true, strtol(param,nullptr,10));
+        if (param && *param) {
+            try {
+                return pair<bool,unsigned int>(true, lexical_cast<unsigned int>(param));
+            }
+            catch (bad_lexical_cast&) {
+                return pair<bool,unsigned int>(false,0);
+            }
+        }
     }
     
     if (type & HANDLER_PROPERTY_MAP) {
index e0e9396..9438b04 100644 (file)
@@ -43,6 +43,7 @@
 # include "metadata/MetadataProviderCriteria.h"
 # include "security/SecurityPolicy.h"
 # include "security/SecurityPolicyProvider.h"
+# include <boost/iterator/indirect_iterator.hpp>
 # include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/saml1/core/Assertions.h>
@@ -64,14 +65,12 @@ using namespace shibspconstants;
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 AssertionConsumerService::AssertionConsumerService(
     const DOMElement* e, const char* appId, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
     ) : AbstractHandler(e, log, filter, remapper)
-#ifndef SHIBSP_LITE
-        ,m_decoder(nullptr), m_role(samlconstants::SAML20MD_NS, opensaml::saml2md::IDPSSODescriptor::LOCAL_NAME)
-#endif
 {
     if (!e)
         return;
@@ -80,8 +79,10 @@ AssertionConsumerService::AssertionConsumerService(
     setAddress(address.c_str());
 #ifndef SHIBSP_LITE
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-        m_decoder = 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, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
+                )
             );
         m_decoder->setArtifactResolver(SPConfig::getConfig().getArtifactResolver());
     }
@@ -90,9 +91,6 @@ AssertionConsumerService::AssertionConsumerService(
 
 AssertionConsumerService::~AssertionConsumerService()
 {
-#ifndef SHIBSP_LITE
-    delete m_decoder;
-#endif
 }
 
 pair<bool,long> AssertionConsumerService::run(SPRequest& request, bool isHandler) const
@@ -127,17 +125,17 @@ void AssertionConsumerService::receive(DDF& in, ostream& out)
     }
 
     // Unpack the request.
-    auto_ptr<HTTPRequest> req(getRequest(in));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
 
     // Wrap a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     // Since we're remoted, the result should either be a throw, a false/0 return,
     // which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    processMessage(*app, *req.get(), *resp.get());
+    processMessage(*app, *req, *resp);
     out << ret;
 }
 
@@ -155,24 +153,23 @@ pair<bool,long> AssertionConsumerService::processMessage(
     Locker metadataLocker(application.getMetadataProvider());
 
     // Create the policy.
-    auto_ptr<opensaml::SecurityPolicy> policy(
-        application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, &m_role, policyId.second)
+    scoped_ptr<opensaml::SecurityPolicy> policy(
+        application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, &IDPSSODescriptor::ELEMENT_QNAME, policyId.second)
         );
 
     string relayState;
     bool relayStateOK = true;
-    auto_ptr<XMLObject> msg(nullptr);
+    scoped_ptr<XMLObject> msg;
     try {
         // Decode the message and process it in a protocol-specific way.
-        auto_ptr<XMLObject> msg2(m_decoder->decode(relayState, httpRequest, *(policy.get())));
-        if (!msg2.get())
+        msg.reset(m_decoder->decode(relayState, httpRequest, *(policy.get())));
+        if (!msg)
             throw BindingException("Failed to decode an SSO protocol response.");
-        msg = msg2; // save off to allow access from within exception handler.
         DDF postData = recoverPostData(application, httpRequest, httpResponse, relayState.c_str());
         DDFJanitor postjan(postData);
         recoverRelayState(application, httpRequest, httpResponse, relayState);
         limitRelayState(m_log, application, httpRequest, relayState.c_str());
-        implementProtocol(application, httpRequest, httpResponse, *(policy.get()), NULL, *msg.get());
+        implementProtocol(application, httpRequest, httpResponse, *policy, nullptr, *msg);
 
         auto_ptr_char issuer(policy->getIssuer() ? policy->getIssuer()->getName() : nullptr);
 
@@ -208,7 +205,7 @@ pair<bool,long> AssertionConsumerService::processMessage(
 
         // Log the error.
         try {
-            auto_ptr<TransactionLog::Event> event(SPConfig::getConfig().EventManager.newPlugin(LOGIN_EVENT, nullptr));
+            scoped_ptr<TransactionLog::Event> event(SPConfig::getConfig().EventManager.newPlugin(LOGIN_EVENT, nullptr));
             LoginEvent* error_event = dynamic_cast<LoginEvent*>(event.get());
             if (error_event) {
                 error_event->m_exception = &ex;
@@ -228,7 +225,7 @@ pair<bool,long> AssertionConsumerService::processMessage(
                 m_log.warn("unable to audit event, log event object was of an incorrect type");
             }
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.warn("exception auditing event: %s", ex.what());
         }
 
@@ -244,10 +241,10 @@ void AssertionConsumerService::checkAddress(const Application& application, cons
     if (!issuedTo || !*issuedTo)
         return;
 
-    const PropertySet* props=application.getPropertySet("Sessions");
+    const PropertySet* props = application.getPropertySet("Sessions");
     pair<bool,bool> checkAddress = props ? props->getBool("checkAddress") : make_pair(false,true);
     if (!checkAddress.first)
-        checkAddress.second=true;
+        checkAddress.second = true;
 
     if (checkAddress.second) {
         m_log.debug("checking client address");
@@ -256,7 +253,7 @@ void AssertionConsumerService::checkAddress(const Application& application, cons
                "Your client's current address ($client_addr) differs from the one used when you authenticated "
                 "to your identity provider. To correct this problem, you may need to bypass a proxy server. "
                 "Please contact your local support staff or help desk for assistance.",
-                namedparams(1,"client_addr",httpRequest.getRemoteAddr().c_str())
+                namedparams(1, "client_addr", httpRequest.getRemoteAddr().c_str())
                 );
         }
     }
@@ -385,13 +382,14 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
                 try {
                     // We pass nullptr for "issuer" because the IdP isn't the one asserting metadata-based attributes.
                     extractor->extractAttributes(application, nullptr, *issuer, resolvedAttributes);
-                    for (vector<Attribute*>::iterator a = resolvedAttributes.begin(); a != resolvedAttributes.end(); ++a) {
-                        vector<string>& ids = (*a)->getAliases();
+                    for (indirect_iterator<vector<Attribute*>::iterator> a = make_indirect_iterator(resolvedAttributes.begin());
+                            a != make_indirect_iterator(resolvedAttributes.end()); ++a) {
+                        vector<string>& ids = a->getAliases();
                         for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
                             *id = mprefix.second + *id;
                     }
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     m_log.error("caught exception extracting attributes: %s", ex.what());
                 }
             }
@@ -406,7 +404,7 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
                 else
                     extractor->extractAttributes(application, issuer, *nameid, resolvedAttributes);
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("caught exception extracting attributes: %s", ex.what());
             }
         }
@@ -418,17 +416,18 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
                 else
                     extractor->extractAttributes(application, issuer, *statement, resolvedAttributes);
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("caught exception extracting attributes: %s", ex.what());
             }
         }
 
         if (tokens) {
-            for (vector<const Assertion*>::const_iterator t = tokens->begin(); t!=tokens->end(); ++t) {
+            for (indirect_iterator<vector<const Assertion*>::const_iterator> t = make_indirect_iterator(tokens->begin());
+                    t != make_indirect_iterator(tokens->end()); ++t) {
                 try {
-                    extractor->extractAttributes(application, issuer, *(*t), resolvedAttributes);
+                    extractor->extractAttributes(application, issuer, *t, resolvedAttributes);
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     m_log.error("caught exception extracting attributes: %s", ex.what());
                 }
             }
@@ -441,7 +440,7 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
             try {
                 filter->filterAttributes(fc, resolvedAttributes);
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("caught exception filtering attributes: %s", ex.what());
                 m_log.error("dumping extracted attributes due to filtering exception");
                 for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup<shibsp::Attribute>());
@@ -471,19 +470,27 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
                     &resolvedAttributes
                     )
                 );
-            resolver->resolveAttributes(*ctx.get());
+            resolver->resolveAttributes(*ctx);
             // Copy over any pushed attributes.
-            if (!resolvedAttributes.empty())
-                ctx->getResolvedAttributes().insert(ctx->getResolvedAttributes().end(), resolvedAttributes.begin(), resolvedAttributes.end());
+            while (!resolvedAttributes.empty()) {
+                ctx->getResolvedAttributes().push_back(resolvedAttributes.back());
+                resolvedAttributes.pop_back();
+            }
             return ctx.release();
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("attribute resolution failed: %s", ex.what());
     }
 
-    if (!resolvedAttributes.empty())
-        return new DummyContext(resolvedAttributes);
+    if (!resolvedAttributes.empty()) {
+        try {
+            return new DummyContext(resolvedAttributes);
+        }
+        catch (bad_alloc&) {
+            for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup<shibsp::Attribute>());
+        }
+    }
     return nullptr;
 }
 
@@ -550,7 +557,7 @@ LoginEvent* AssertionConsumerService::newLoginEvent(const Application& applicati
             m_log.warn("unable to audit event, log event object was of an incorrect type");
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.warn("exception auditing event: %s", ex.what());
     }
     return nullptr;
index 65312e8..490e554 100644 (file)
 #include "util/IPRange.h"
 #include "util/SPConstants.h"
 
+#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/algorithm/string.hpp>
+
 #ifndef SHIBSP_LITE
 # include <saml/exceptions.h>
 # include <saml/Assertion.h>
@@ -45,6 +49,7 @@ using namespace opensaml;
 using namespace shibspconstants;
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -84,6 +89,14 @@ namespace shibsp {
 
     private:
         pair<bool,long> processMessage(const Application& application, HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
+        void parseACL(const string& acl) {
+            try {
+                m_acl.push_back(IPRange::parseCIDRBlock(acl.c_str()));
+            }
+            catch (std::exception& ex) {
+                m_log.error("invalid CIDR block (%s): %s", acl.c_str(), ex.what());
+            }
+        }
 
         vector<IPRange> m_acl;
     };
@@ -106,25 +119,9 @@ AssertionLookup::AssertionLookup(const DOMElement* e, const char* appId)
         pair<bool,const char*> acl = getString("exportACL");
         if (acl.first) {
             string aclbuf=acl.second;
-            int j = 0;
-            for (unsigned int i=0;  i < aclbuf.length();  i++) {
-                if (aclbuf.at(i)==' ') {
-                    try {
-                        m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, i-j).c_str()));
-                    }
-                    catch (exception& ex) {
-                        m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, i-j).c_str(), ex.what());
-                    }
-                    j = i+1;
-                }
-            }
-            try {
-                m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, aclbuf.length()-j).c_str()));
-            }
-            catch (exception& ex) {
-                m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, aclbuf.length()-j).c_str(), ex.what());
-            }
-
+            vector<string> aclarray;
+            split(aclarray, aclbuf, is_space(), algorithm::token_compress_on);
+            for_each(aclarray.begin(), aclarray.end(), boost::bind(&AssertionLookup::parseACL, this, _1));
             if (m_acl.empty()) {
                 m_log.warn("invalid CIDR range(s) in acl property, allowing 127.0.0.1 as a fall back");
                 m_acl.push_back(IPRange::parseCIDRBlock("127.0.0.1"));
@@ -142,11 +139,8 @@ pair<bool,long> AssertionLookup::run(SPRequest& request, bool isHandler) const
 {
     SPConfig& conf = SPConfig::getConfig();
     if (conf.isEnabled(SPConfig::InProcess) && !m_acl.empty()) {
-        bool found = false;
-        for (vector<IPRange>::const_iterator acl = m_acl.begin(); !found && acl != m_acl.end(); ++acl) {
-            found = acl->contains(request.getRemoteAddr().c_str());
-        }
-        if (!found) {
+        static bool (IPRange::* contains)(const char*) const = &IPRange::contains;
+        if (find_if(m_acl.begin(), m_acl.end(), boost::bind(contains, _1, request.getRemoteAddr().c_str())) == m_acl.end()) {
             m_log.error("request for assertion lookup blocked from invalid address (%s)", request.getRemoteAddr().c_str());
             istringstream msg("Assertion Lookup Blocked");
             return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
@@ -167,10 +161,10 @@ pair<bool,long> AssertionLookup::run(SPRequest& request, bool isHandler) const
             return unwrap(request, out);
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error while processing request: %s", ex.what());
         istringstream msg("Assertion Lookup Failed");
-        return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
+        return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
     }
 }
 
@@ -186,18 +180,18 @@ void AssertionLookup::receive(DDF& in, ostream& out)
     }
 
     // Unpack the request.
-    auto_ptr<HTTPRequest> req(getRequest(in));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
     //m_log.debug("found %d client certificates", req->getClientCertificates().size());
 
     // Wrap a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     // Since we're remoted, the result should either be a throw, a false/0 return,
     // which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    processMessage(*app, *req.get(), *resp.get());
+    processMessage(*app, *req, *resp);
     out << ret;
 }
 
index 67512aa..a4cd779 100644 (file)
 #include "handler/LogoutInitiator.h"
 #include "util/SPConstants.h"
 
+#include <boost/bind.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -48,21 +51,18 @@ namespace shibsp {
     {
     public:
         ChainingLogoutInitiator(const DOMElement* e, const char* appId);
-        virtual ~ChainingLogoutInitiator() {
-            for_each(m_handlers.begin(), m_handlers.end(), xmltooling::cleanup<Handler>());
-        }
+        virtual ~ChainingLogoutInitiator() {}
         
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
 #ifndef SHIBSP_LITE
         void generateMetadata(opensaml::saml2md::SPSSODescriptor& role, const char* handlerURL) const {
-            for (vector<Handler*>::const_iterator i = m_handlers.begin(); i!=m_handlers.end(); ++i)
-                (*i)->generateMetadata(role, handlerURL);
+            for_each(m_handlers.begin(), m_handlers.end(), boost::bind(&Handler::generateMetadata, _1, boost::ref(role), handlerURL));
         }
 #endif
 
     private:
-        vector<Handler*> m_handlers;
+        ptr_vector<Handler> m_handlers;
     };
 
 #if defined (_MSC_VER)
@@ -106,10 +106,11 @@ ChainingLogoutInitiator::ChainingLogoutInitiator(const DOMElement* e, const char
         string t(XMLHelper::getAttrString(e, nullptr, _type));
         if (!t.empty()) {
             try {
-                m_handlers.push_back(conf.LogoutInitiatorManager.newPlugin(t.c_str(), make_pair(e, appId)));
-                m_handlers.back()->setParent(this);
+                auto_ptr<Handler> np(conf.LogoutInitiatorManager.newPlugin(t.c_str(), make_pair(e, appId)));
+                m_handlers.push_back(np);
+                m_handlers.back().setParent(this);
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("caught exception processing embedded LogoutInitiator element: %s", ex.what());
             }
         }
@@ -124,8 +125,8 @@ pair<bool,long> ChainingLogoutInitiator::run(SPRequest& request, bool isHandler)
     if (ret.first)
         return ret;
 
-    for (vector<Handler*>::const_iterator i = m_handlers.begin(); i!=m_handlers.end(); ++i) {
-        ret = (*i)->run(request, isHandler);
+    for (ptr_vector<Handler>::const_iterator i = m_handlers.begin(); i != m_handlers.end(); ++i) {
+        ret = i->run(request, isHandler);
         if (ret.first)
             return ret;
     }
index 38671e0..ba02781 100644 (file)
 #include "handler/SessionInitiator.h"
 #include "util/SPConstants.h"
 
+#include <boost/bind.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -48,22 +51,19 @@ namespace shibsp {
     {
     public:
         ChainingSessionInitiator(const DOMElement* e, const char* appId);
-        virtual ~ChainingSessionInitiator() {
-            for_each(m_handlers.begin(), m_handlers.end(), xmltooling::cleanup<SessionInitiator>());
-        }
+        virtual ~ChainingSessionInitiator() {}
         
         pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
 
 #ifndef SHIBSP_LITE
         void generateMetadata(opensaml::saml2md::SPSSODescriptor& role, const char* handlerURL) const {
             SessionInitiator::generateMetadata(role, handlerURL);
-            for (vector<SessionInitiator*>::const_iterator i = m_handlers.begin(); i!=m_handlers.end(); ++i)
-                (*i)->generateMetadata(role, handlerURL);
+            for_each(m_handlers.begin(), m_handlers.end(), boost::bind(&SessionInitiator::generateMetadata, _1, boost::ref(role), handlerURL));
         }
 #endif
 
     private:
-        vector<SessionInitiator*> m_handlers;
+        ptr_vector<SessionInitiator> m_handlers;
     };
 
 #if defined (_MSC_VER)
@@ -104,13 +104,14 @@ ChainingSessionInitiator::ChainingSessionInitiator(const DOMElement* e, const ch
     // Load up the chain of handlers.
     e = e ? XMLHelper::getFirstChildElement(e, _SessionInitiator) : nullptr;
     while (e) {
-        auto_ptr_char type(e->getAttributeNS(nullptr,_type));
-        if (type.get() && *(type.get())) {
+        string t(XMLHelper::getAttrString(e, nullptr, _type));
+        if (!t.empty()) {
             try {
-                m_handlers.push_back(conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(e, appId)));
-                m_handlers.back()->setParent(this);
+                auto_ptr<SessionInitiator> np(conf.SessionInitiatorManager.newPlugin(t.c_str(), make_pair(e, appId)));
+                m_handlers.push_back(np);
+                m_handlers.back().setParent(this);
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("caught exception processing embedded SessionInitiator element: %s", ex.what());
             }
         }
@@ -123,11 +124,11 @@ ChainingSessionInitiator::ChainingSessionInitiator(const DOMElement* e, const ch
 pair<bool,long> ChainingSessionInitiator::run(SPRequest& request, string& entityID, bool isHandler) const
 {
     if (!checkCompatibility(request, isHandler))
-        return make_pair(false,0L);
+        return make_pair(false, 0L);
 
     pair<bool,long> ret;
-    for (vector<SessionInitiator*>::const_iterator i = m_handlers.begin(); i!=m_handlers.end(); ++i) {
-        ret = (*i)->run(request, entityID, isHandler);
+    for (ptr_vector<SessionInitiator>::const_iterator i = m_handlers.begin(); i != m_handlers.end(); ++i) {
+        ret = i->run(request, entityID, isHandler);
         if (ret.first)
             return ret;
     }
index 4fee1ef..3bed7bf 100644 (file)
@@ -40,6 +40,7 @@
 
 #ifndef SHIBSP_LITE
 # include <queue>
+# include <boost/scoped_ptr.hpp>
 # include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/saml2/metadata/DiscoverableMetadataProvider.h>
@@ -49,6 +50,7 @@ using namespace shibsp;
 #ifndef SHIBSP_LITE
 using namespace opensaml::saml2md;
 using namespace opensaml;
+using namespace boost;
 #endif
 using namespace xmltooling;
 using namespace std;
@@ -94,7 +96,7 @@ namespace shibsp {
         // A queue of feed files, linked to the last time of "access".
         // Each filename is also a cache tag.
         mutable queue< pair<string,time_t> > m_feedQueue;
-        Mutex* m_feedLock;
+        scoped_ptr<Mutex> m_feedLock;
 #endif
     };
 
@@ -111,9 +113,6 @@ namespace shibsp {
 
 DiscoveryFeed::DiscoveryFeed(const DOMElement* e, const char* appId)
     : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".DiscoveryFeed"), &g_Blocker), m_cacheToClient(false)
-#ifndef SHIBSP_LITE
-    , m_feedLock(nullptr)
-#endif
 {
     pair<bool,const char*> prop = getString("Location");
     if (!prop.first)
@@ -132,7 +131,7 @@ DiscoveryFeed::DiscoveryFeed(const DOMElement* e, const char* appId)
         XMLToolingConfig::getConfig().getPathResolver()->resolve(m_dir, PathResolver::XMLTOOLING_RUN_FILE);
         m_log.info("feed files will be cached in %s", m_dir.c_str());
 #ifndef SHIBSP_LITE
-        m_feedLock = Mutex::create();
+        m_feedLock.reset(Mutex::create());
 #endif
     }
 }
@@ -149,7 +148,6 @@ DiscoveryFeed::~DiscoveryFeed()
             remove(fname.c_str());
             m_feedQueue.pop();
         }
-        delete m_feedLock;
     }
 #endif
 }
@@ -229,7 +227,7 @@ pair<bool,long> DiscoveryFeed::run(SPRequest& request, bool isHandler) const
         request.setContentType("application/json");
         return make_pair(true, request.sendResponse(feed));
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         request.log(SPRequest::SPError, string("error while processing request:") + ex.what());
         istringstream msg("Discovery Request Failed");
         return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
@@ -278,7 +276,7 @@ void DiscoveryFeed::feedToFile(const Application& application, string& cacheTag)
 #ifndef SHIBSP_LITE
     m_log.debug("processing discovery feed request");
 
-    DiscoverableMetadataProvider* m=dynamic_cast<DiscoverableMetadataProvider*>(application.getMetadataProvider(false));
+    DiscoverableMetadataProvider* m = dynamic_cast<DiscoverableMetadataProvider*>(application.getMetadataProvider(false));
     if (!m)
         m_log.warn("MetadataProvider missing or does not support discovery feed");
     Locker locker(m);
@@ -331,7 +329,7 @@ void DiscoveryFeed::feedToStream(const Application& application, string& cacheTa
 #ifndef SHIBSP_LITE
     m_log.debug("processing discovery feed request");
 
-    DiscoverableMetadataProvider* m=dynamic_cast<DiscoverableMetadataProvider*>(application.getMetadataProvider(false));
+    DiscoverableMetadataProvider* m = dynamic_cast<DiscoverableMetadataProvider*>(application.getMetadataProvider(false));
     if (!m)
         m_log.warn("MetadataProvider missing or does not support discovery feed");
     Locker locker(m);
index 34cd2db..aba50f9 100644 (file)
 #include "handler/AbstractHandler.h"
 #include "handler/LogoutInitiator.h"
 
+#ifndef SHIBSP_LITE
+# include <boost/scoped_ptr.hpp>
+using namespace boost;
+#endif
+
 using namespace shibsp;
 using namespace xmltooling;
 using namespace std;
@@ -108,7 +113,7 @@ pair<bool,long> LocalLogoutInitiator::run(SPRequest& request, bool isHandler) co
         try {
             session = request.getSession(false, true, false);  // don't cache it and ignore all checks
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error("error accessing current session: %s", ex.what());
         }
         return doRequest(request.getApplication(), request, request, session);
@@ -140,23 +145,23 @@ void LocalLogoutInitiator::receive(DDF& in, ostream& out)
     }
 
     // Unpack the request.
-    auto_ptr<HTTPRequest> req(getRequest(in));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
 
     // Set up a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     Session* session = nullptr;
     try {
-         session = app->getServiceProvider().getSessionCache()->find(*app, *req.get(), nullptr, nullptr);
+         session = app->getServiceProvider().getSessionCache()->find(*app, *req, nullptr, nullptr);
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error accessing current session: %s", ex.what());
     }
 
     // This is the "last chance" handler so even without a session, we "complete" the logout.
-    doRequest(*app, *req.get(), *resp.get(), session);
+    doRequest(*app, *req, *resp, session);
 
     out << ret;
 #else
@@ -169,18 +174,21 @@ pair<bool,long> LocalLogoutInitiator::doRequest(
     ) const
 {
     if (session) {
+        // Guard the session in case of exception.
+        Locker locker(session, false);
+
         // Do back channel notification.
         bool result;
         vector<string> sessions(1, session->getID());
         result = notifyBackChannel(application, httpRequest.getRequestURL(), sessions, true);
 #ifndef SHIBSP_LITE
-        auto_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
-        if (logout_event.get()) {
+        scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
+        if (logout_event) {
             logout_event->m_logoutType = result ? LogoutEvent::LOGOUT_EVENT_LOCAL : LogoutEvent::LOGOUT_EVENT_PARTIAL;
             application.getServiceProvider().getTransactionLog()->write(*logout_event);
         }
 #endif
-        session->unlock();
+        locker.assign();    // unlock the session
         application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
         if (!result)
             return sendLogoutPage(application, httpRequest, httpResponse, "partial");
index 2b9d7a3..c15c28b 100644 (file)
 #include "handler/LogoutHandler.h"
 #include "util/TemplateParameters.h"
 
+#ifndef SHIBSP_LITE
+# include <boost/scoped_ptr.hpp>
+#endif
+
 #include <fstream>
+#include <boost/lexical_cast.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/PathResolver.h>
 #include <xmltooling/util/URLEncoder.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 LogoutHandler::LogoutHandler() : m_initiator(true)
@@ -155,35 +161,34 @@ pair<bool,long> LogoutHandler::notifyFrontChannel(
     loc = loc + (strchr(loc.c_str(),'?') ? '&' : '?') + "action=logout";
 
     // Now we create a second URL representing the return location back to us.
-    ostringstream locstr;
     const char* start = request.getRequestURL();
-    const char* end = strchr(start,'?');
-    string tempstr(start, end ? end-start : strlen(start));
+    const char* end = strchr(start, '?');
+    string locstr(start, end ? end - start : strlen(start));
 
     // Add a signal that we're coming back from notification and the next index.
-    locstr << tempstr << "?notifying=1&index=" << index;
+    locstr = locstr + "?notifying=1&index=" + lexical_cast<string>(index);
 
     // Add return if set.
     if (param)
-        locstr << "&return=" << encoder->encode(param);
+        locstr = locstr + "&return=" + encoder->encode(param);
 
     // We preserve anything we're instructed to directly.
     if (params) {
         for (map<string,string>::const_iterator p = params->begin(); p!=params->end(); ++p)
-            locstr << '&' << p->first << '=' << encoder->encode(p->second.c_str());
+            locstr = locstr + '&' + p->first + '=' + encoder->encode(p->second.c_str());
     }
     else {
         for (vector<string>::const_iterator q = m_preserve.begin(); q!=m_preserve.end(); ++q) {
             param = request.getParameter(q->c_str());
             if (param)
-                locstr << '&' << *q << '=' << encoder->encode(param);
+                locstr = locstr + '&' + *q + '=' + encoder->encode(param);
         }
     }
 
     // Add the notifier's return parameter to the destination location and redirect.
     // This is NOT the same as the return parameter that might be embedded inside it ;-)
-    loc = loc + "&return=" + encoder->encode(locstr.str().c_str());
-    return make_pair(true,response.sendRedirect(loc.c_str()));
+    loc = loc + "&return=" + encoder->encode(locstr.c_str());
+    return make_pair(true, response.sendRedirect(loc.c_str()));
 }
 
 #ifndef SHIBSP_LITE
@@ -211,7 +216,6 @@ namespace {
             HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(&transport);
             if (http) {
                 http->useChunkedEncoding(false);
-                http->setRequestHeader("User-Agent", PACKAGE_NAME);
                 http->setRequestHeader(PACKAGE_NAME, PACKAGE_VERSION);
             }
         }
@@ -235,13 +239,13 @@ bool LogoutHandler::notifyBackChannel(
 
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
 #ifndef SHIBSP_LITE
-        auto_ptr<Envelope> env(EnvelopeBuilder::buildEnvelope());
+        scoped_ptr<Envelope> env(EnvelopeBuilder::buildEnvelope());
         Body* body = BodyBuilder::buildBody();
         env->setBody(body);
         ElementProxy* msg = new AnyElementImpl(shibspconstants::SHIB2SPNOTIFY_NS, LogoutNotification);
         body->getUnknownXMLObjects().push_back(msg);
         msg->setAttribute(xmltooling::QName(nullptr, _type), local ? _local : _global);
-        for (vector<string>::const_iterator s = sessions.begin(); s!=sessions.end(); ++s) {
+        for (vector<string>::const_iterator s = sessions.begin(); s != sessions.end(); ++s) {
             auto_ptr_XMLCh temp(s->c_str());
             ElementProxy* child = new AnyElementImpl(shibspconstants::SHIB2SPNOTIFY_NS, SessionID);
             child->setTextContent(temp.get());
@@ -252,10 +256,10 @@ bool LogoutHandler::notifyBackChannel(
         SOAPNotifier soaper;
         while (!endpoint.empty()) {
             try {
-                soaper.send(*env.get(), SOAPTransport::Address(application.getId(), application.getId(), endpoint.c_str()));
+                soaper.send(*env, SOAPTransport::Address(application.getId(), application.getId(), endpoint.c_str()));
                 delete soaper.receive();
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 Category::getInstance(SHIBSP_LOGCAT".Logout").error("error notifying application of logout event: %s", ex.what());
                 result = false;
             }
@@ -281,7 +285,7 @@ bool LogoutHandler::notifyBackChannel(
         DDF temp = DDF(nullptr).string(i->c_str());
         s.add(temp);
     }
-    out=application.getServiceProvider().getListenerService()->send(in);
+    out = application.getServiceProvider().getListenerService()->send(in);
     return (out.integer() == 1);
 }
 
@@ -312,7 +316,7 @@ LogoutEvent* LogoutHandler::newLogoutEvent(
             Category::getInstance(SHIBSP_LOGCAT".Logout").warn("unable to audit event, log event object was of an incorrect type");
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         Category::getInstance(SHIBSP_LOGCAT".Logout").warn("exception auditing event: %s", ex.what());
     }
     return nullptr;
index fe541b2..48663b5 100644 (file)
 #include "handler/RemotedHandler.h"
 #include "util/IPRange.h"
 
+#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/algorithm/string.hpp>
+
 #ifndef SHIBSP_LITE
 # include "attribute/resolver/AttributeExtractor.h"
 # include "metadata/MetadataProviderCriteria.h"
+# include <boost/ptr_container/ptr_vector.hpp>
 # include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/signature/ContentReference.h>
@@ -60,6 +66,7 @@ using namespace opensaml;
 using namespace xmlsignature;
 #endif
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -88,17 +95,7 @@ namespace shibsp {
     {
     public:
         MetadataGenerator(const DOMElement* e, const char* appId);
-        virtual ~MetadataGenerator() {
-#ifndef SHIBSP_LITE
-            delete m_uiinfo;
-            delete m_org;
-            delete m_entityAttrs;
-            for_each(m_contacts.begin(), m_contacts.end(), xmltooling::cleanup<ContactPerson>());
-            for_each(m_formats.begin(), m_formats.end(), xmltooling::cleanup<NameIDFormat>());
-            for_each(m_reqAttrs.begin(), m_reqAttrs.end(), xmltooling::cleanup<RequestedAttribute>());
-            for_each(m_attrConsumers.begin(), m_attrConsumers.end(), xmltooling::cleanup<AttributeConsumingService>());
-#endif
-        }
+        virtual ~MetadataGenerator() {}
 
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
         void receive(DDF& in, ostream& out);
@@ -111,18 +108,27 @@ namespace shibsp {
             HTTPResponse& httpResponse
             ) const;
 
+        void parseACL(const string& acl) {
+            try {
+                m_acl.push_back(IPRange::parseCIDRBlock(acl.c_str()));
+            }
+            catch (std::exception& ex) {
+                m_log.error("invalid CIDR block (%s): %s", acl.c_str(), ex.what());
+            }
+        }
+
         vector<IPRange> m_acl;
 #ifndef SHIBSP_LITE
         string m_salt;
         short m_http,m_https;
         vector<string> m_bases;
-        UIInfo* m_uiinfo;
-        Organization* m_org;
-        EntityAttributes* m_entityAttrs;
-        vector<ContactPerson*> m_contacts;
-        vector<NameIDFormat*> m_formats;
-        vector<RequestedAttribute*> m_reqAttrs;
-        vector<AttributeConsumingService*> m_attrConsumers;
+        scoped_ptr<UIInfo> m_uiinfo;
+        scoped_ptr<Organization> m_org;
+        scoped_ptr<EntityAttributes> m_entityAttrs;
+        ptr_vector<ContactPerson> m_contacts;
+        ptr_vector<NameIDFormat> m_formats;
+        ptr_vector<RequestedAttribute> m_reqAttrs;
+        ptr_vector<AttributeConsumingService> m_attrConsumers;
 #endif
     };
 
@@ -140,7 +146,7 @@ namespace shibsp {
 MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
     : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".MetadataGenerator"), &g_Blocker)
 #ifndef SHIBSP_LITE
-        ,m_http(0), m_https(0), m_uiinfo(nullptr), m_org(nullptr), m_entityAttrs(nullptr)
+        ,m_http(0), m_https(0)
 #endif
 {
     string address(appId);
@@ -151,25 +157,9 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
         pair<bool,const char*> acl = getString("acl");
         if (acl.first) {
             string aclbuf=acl.second;
-            int j = 0;
-            for (unsigned int i=0;  i < aclbuf.length();  ++i) {
-                if (aclbuf.at(i)==' ') {
-                    try {
-                        m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, i-j).c_str()));
-                    }
-                    catch (exception& ex) {
-                        m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, i-j).c_str(), ex.what());
-                    }
-                    j = i + 1;
-                }
-            }
-            try {
-                m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, aclbuf.length()-j).c_str()));
-            }
-            catch (exception& ex) {
-                m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, aclbuf.length()-j).c_str(), ex.what());
-            }
-
+            vector<string> aclarray;
+            split(aclarray, aclbuf, is_space(), algorithm::token_compress_on);
+            for_each(aclarray.begin(), aclarray.end(), boost::bind(&MetadataGenerator::parseACL, this, _1));
             if (m_acl.empty()) {
                 m_log.warn("invalid CIDR range(s) in Metadata Generator acl property, allowing 127.0.0.1 as a fall back");
                 m_acl.push_back(IPRange::parseCIDRBlock("127.0.0.1"));
@@ -203,33 +193,33 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
             auto_ptr<XMLObject> child(XMLObjectBuilder::buildOneFromElement(const_cast<DOMElement*>(e)));
             ContactPerson* cp = dynamic_cast<ContactPerson*>(child.get());
             if (cp) {
-                child.release();
                 m_contacts.push_back(cp);
+                child.release();
             }
             else {
                 NameIDFormat* nif = dynamic_cast<NameIDFormat*>(child.get());
                 if (nif) {
-                    child.release();
                     m_formats.push_back(nif);
+                    child.release();
                 }
                 else {
                     RequestedAttribute* req = dynamic_cast<RequestedAttribute*>(child.get());
                     if (req) {
-                        child.release();
                         m_reqAttrs.push_back(req);
+                        child.release();
                     }
                     else {
                         AttributeConsumingService* acs = dynamic_cast<AttributeConsumingService*>(child.get());
                         if (acs) {
-                            child.release();
                             m_attrConsumers.push_back(acs);
+                            child.release();
                         }
                         else {
                             UIInfo* info = dynamic_cast<UIInfo*>(child.get());
                             if (info) {
                                 if (!m_uiinfo) {
+                                    m_uiinfo.reset(info);
                                     child.release();
-                                    m_uiinfo = info;
                                 }
                                 else {
                                     m_log.warn("skipping duplicate UIInfo element");
@@ -239,8 +229,8 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
                                 Organization* org = dynamic_cast<Organization*>(child.get());
                                 if (org) {
                                     if (!m_org) {
+                                        m_org.reset(org);
                                         child.release();
-                                        m_org = org;
                                     }
                                     else {
                                         m_log.warn("skipping duplicate Organization element");
@@ -250,8 +240,8 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
                                     EntityAttributes* ea = dynamic_cast<EntityAttributes*>(child.get());
                                     if (ea) {
                                         if (!m_entityAttrs) {
+                                            m_entityAttrs.reset(ea);
                                             child.release();
-                                            m_entityAttrs = ea;
                                         }
                                         else {
                                             m_log.warn("skipping duplicate EntityAttributes element");
@@ -273,14 +263,11 @@ pair<bool,long> MetadataGenerator::run(SPRequest& request, bool isHandler) const
 {
     SPConfig& conf = SPConfig::getConfig();
     if (conf.isEnabled(SPConfig::InProcess) && !m_acl.empty()) {
-        bool found = false;
-        for (vector<IPRange>::const_iterator acl = m_acl.begin(); !found && acl != m_acl.end(); ++acl) {
-            found = acl->contains(request.getRemoteAddr().c_str());
-        }
-        if (!found) {
+        static bool (IPRange::* contains)(const char*) const = &IPRange::contains;
+        if (find_if(m_acl.begin(), m_acl.end(), boost::bind(contains, _1, request.getRemoteAddr().c_str())) == m_acl.end()) {
             m_log.error("request for metadata blocked from invalid address (%s)", request.getRemoteAddr().c_str());
             istringstream msg("Metadata Request Blocked");
-            return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
+            return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
         }
     }
 
@@ -302,10 +289,10 @@ pair<bool,long> MetadataGenerator::run(SPRequest& request, bool isHandler) const
             return unwrap(request, out);
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error while processing request: %s", ex.what());
         istringstream msg("Metadata Request Failed");
-        return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
+        return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
     }
 }
 
@@ -327,12 +314,12 @@ void MetadataGenerator::receive(DDF& in, ostream& out)
     // Wrap a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     // Since we're remoted, the result should either be a throw, a false/0 return,
     // which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    processMessage(*app, hurl, in["entity_id"].string(), *resp.get());
+    processMessage(*app, hurl, in["entity_id"].string(), *resp);
     out << ret;
 }
 
@@ -343,9 +330,9 @@ pair<bool,long> MetadataGenerator::processMessage(
 #ifndef SHIBSP_LITE
     m_log.debug("processing metadata request");
 
-    const PropertySet* relyingParty=nullptr;
+    const PropertySet* relyingParty = nullptr;
     if (entityID) {
-        MetadataProvider* m=application.getMetadataProvider();
+        MetadataProvider* m = application.getMetadataProvider();
         Locker locker(m);
         MetadataProviderCriteria mc(application, entityID);
         relyingParty = application.getRelyingParty(m->getEntityDescriptor(mc).first);
@@ -354,7 +341,7 @@ pair<bool,long> MetadataGenerator::processMessage(
         relyingParty = &application;
     }
 
-    EntityDescriptor* entity;
+    scoped_ptr<EntityDescriptor> entity;
     pair<bool,const char*> prop = getString("template");
     if (prop.first) {
         // Load a template to use for our metadata.
@@ -363,17 +350,17 @@ pair<bool,long> MetadataGenerator::processMessage(
         auto_ptr_XMLCh widenit(templ.c_str());
         LocalFileInputSource src(widenit.get());
         Wrapper4InputSource dsrc(&src,false);
-        DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
+        DOMDocument* doc = XMLToolingConfig::getConfig().getParser().parse(dsrc);
         XercesJanitor<DOMDocument> docjan(doc);
         auto_ptr<XMLObject> xmlobj(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
         docjan.release();
-        entity = dynamic_cast<EntityDescriptor*>(xmlobj.get());
+        entity.reset(dynamic_cast<EntityDescriptor*>(xmlobj.get()));
+        xmlobj.release();
         if (!entity)
             throw ConfigurationException("Template file ($1) did not contain an EntityDescriptor", params(1, templ.c_str()));
-        xmlobj.release();
     }
     else {
-        entity = EntityDescriptorBuilder::buildEntityDescriptor();
+        entity.reset(EntityDescriptorBuilder::buildEntityDescriptor());
     }
 
     if (!entity->getID()) {
@@ -383,7 +370,6 @@ pair<bool,long> MetadataGenerator::processMessage(
         entity->setID(widenit.get());
     }
 
-    auto_ptr<EntityDescriptor> wrapper(entity);
     pair<bool,unsigned int> cache = getUnsignedInt("cacheDuration");
     if (cache.first) {
         entity->setCacheDuration(cache.second);
@@ -396,8 +382,8 @@ pair<bool,long> MetadataGenerator::processMessage(
     if (m_org && !entity->getOrganization())
         entity->setOrganization(m_org->cloneOrganization());
 
-    for (vector<ContactPerson*>::const_iterator cp = m_contacts.begin(); cp != m_contacts.end(); ++cp)
-        entity->getContactPersons().push_back((*cp)->cloneContactPerson());
+    for (ptr_vector<ContactPerson>::const_iterator cp = m_contacts.begin(); cp != m_contacts.end(); ++cp)
+        entity->getContactPersons().push_back(cp->cloneContactPerson());
 
     if (m_entityAttrs) {
         if (!entity->getExtensions())
@@ -414,8 +400,8 @@ pair<bool,long> MetadataGenerator::processMessage(
         role = entity->getSPSSODescriptors().front();
     }
 
-    for (vector<NameIDFormat*>::const_iterator nif = m_formats.begin(); nif != m_formats.end(); ++nif)
-        role->getNameIDFormats().push_back((*nif)->cloneNameIDFormat());
+    for (ptr_vector<NameIDFormat>::const_iterator nif = m_formats.begin(); nif != m_formats.end(); ++nif)
+        role->getNameIDFormats().push_back(nif->cloneNameIDFormat());
 
     if (m_uiinfo) {
         if (!role->getExtensions())
@@ -423,14 +409,15 @@ pair<bool,long> MetadataGenerator::processMessage(
         role->getExtensions()->getUnknownXMLObjects().push_back(m_uiinfo->cloneUIInfo());
     }
 
-    for (vector<AttributeConsumingService*>::const_iterator acs = m_attrConsumers.begin(); acs != m_attrConsumers.end(); ++acs)
-        role->getAttributeConsumingServices().push_back((*acs)->cloneAttributeConsumingService());
+    for (ptr_vector<AttributeConsumingService>::const_iterator acs = m_attrConsumers.begin(); acs != m_attrConsumers.end(); ++acs)
+        role->getAttributeConsumingServices().push_back(acs->cloneAttributeConsumingService());
 
     if (!m_reqAttrs.empty()) {
         int index = 1;
         const vector<AttributeConsumingService*>& svcs = const_cast<const SPSSODescriptor*>(role)->getAttributeConsumingServices();
-        for (vector<AttributeConsumingService*>::const_iterator s =svcs.begin(); s != svcs.end(); ++s) {
-            pair<bool,int> i = (*s)->getIndex();
+        for (indirect_iterator<vector<AttributeConsumingService*>::const_iterator> s = make_indirect_iterator(svcs.begin());
+                s != make_indirect_iterator(svcs.end()); ++s) {
+            pair<bool,int> i = s->getIndex();
             if (i.first && index == i.second)
                 index = i.second + 1;
         }
@@ -442,8 +429,8 @@ pair<bool,long> MetadataGenerator::processMessage(
         sn->setName(entity->getEntityID());
         static const XMLCh english[] = UNICODE_LITERAL_2(e,n);
         sn->setLang(english);
-        for (vector<RequestedAttribute*>::const_iterator req = m_reqAttrs.begin(); req != m_reqAttrs.end(); ++req)
-            svc->getRequestedAttributes().push_back((*req)->cloneRequestedAttribute());
+        for (ptr_vector<RequestedAttribute>::const_iterator req = m_reqAttrs.begin(); req != m_reqAttrs.end(); ++req)
+            svc->getRequestedAttributes().push_back(req->cloneRequestedAttribute());
     }
 
     // Policy flags.
@@ -457,30 +444,31 @@ pair<bool,long> MetadataGenerator::processMessage(
     // Ask each handler to generate itself.
     vector<const Handler*> handlers;
     application.getHandlers(handlers);
-    for (vector<const Handler*>::const_iterator h = handlers.begin(); h != handlers.end(); ++h) {
+    for (indirect_iterator<vector<const Handler*>::const_iterator> h = make_indirect_iterator(handlers.begin());
+            h != make_indirect_iterator(handlers.end()); ++h) {
         if (m_bases.empty()) {
             if (strncmp(handlerURL, "https", 5) == 0) {
                 if (m_https >= 0)
-                    (*h)->generateMetadata(*role, handlerURL);
+                    h->generateMetadata(*role, handlerURL);
                 if (m_http == 1) {
                     string temp(handlerURL);
                     temp.erase(4, 1);
-                    (*h)->generateMetadata(*role, temp.c_str());
+                    h->generateMetadata(*role, temp.c_str());
                 }
             }
             else {
                 if (m_http >= 0)
-                    (*h)->generateMetadata(*role, handlerURL);
+                    h->generateMetadata(*role, handlerURL);
                 if (m_https == 1) {
                     string temp(handlerURL);
                     temp.insert(temp.begin() + 4, 's');
-                    (*h)->generateMetadata(*role, temp.c_str());
+                    h->generateMetadata(*role, temp.c_str());
                 }
             }
         }
         else {
             for (vector<string>::const_iterator b = m_bases.begin(); b != m_bases.end(); ++b)
-                (*h)->generateMetadata(*role, b->c_str());
+                h->generateMetadata(*role, b->c_str());
         }
     }
 
@@ -558,7 +546,7 @@ pair<bool,long> MetadataGenerator::processMessage(
             stringstream pretty;
             XMLHelper::serialize(entity->marshall(), pretty, true);
             DOMDocument* prettydoc = XMLToolingConfig::getConfig().getParser().parse(pretty);
-            auto_ptr<XMLObject> prettyentity(XMLObjectBuilder::buildOneFromElement(prettydoc->getDocumentElement(), true));
+            scoped_ptr<XMLObject> prettyentity(XMLObjectBuilder::buildOneFromElement(prettydoc->getDocumentElement(), true));
 
             Signature* sig = SignatureBuilder::buildSignature();
             dynamic_cast<EntityDescriptor*>(prettyentity.get())->setSignature(sig);
index 27b0b23..fe5ce22 100644 (file)
@@ -33,6 +33,7 @@
 #include "handler/RemotedHandler.h"
 
 #include <algorithm>
+#include <boost/scoped_ptr.hpp>
 #include <xmltooling/unicode.h>
 #include <xercesc/util/Base64.hpp>
 
@@ -48,6 +49,7 @@ using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 #ifndef SHIBSP_LITE
@@ -59,7 +61,7 @@ namespace shibsp {
         public HTTPRequest
     {
         DDF& m_input;
-        mutable CGIParser* m_parser;
+        mutable scoped_ptr<CGIParser> m_parser;
         mutable vector<XSECCryptoX509*> m_certs;
 #ifdef SHIBSP_HAVE_GSSAPI
         mutable gss_ctx_id_t m_gss;
@@ -74,7 +76,6 @@ namespace shibsp {
 
         virtual ~RemotedRequest() {
             for_each(m_certs.begin(), m_certs.end(), xmltooling::cleanup<XSECCryptoX509>());
-            delete m_parser;
 #ifdef SHIBSP_HAVE_GSSAPI
             if (m_gss != GSS_C_NO_CONTEXT) {
                 OM_uint32 minor;
@@ -164,19 +165,19 @@ namespace shibsp {
 const char* RemotedRequest::getParameter(const char* name) const
 {
     if (!m_parser)
-        m_parser=new CGIParser(*this);
+        m_parser.reset(new CGIParser(*this));
     
-    pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
+    pair<CGIParser::walker,CGIParser::walker> bounds = m_parser->getParameters(name);
     return (bounds.first==bounds.second) ? nullptr : bounds.first->second;
 }
 
 std::vector<const char*>::size_type RemotedRequest::getParameters(const char* name, std::vector<const char*>& values) const
 {
     if (!m_parser)
-        m_parser=new CGIParser(*this);
+        m_parser.reset(new CGIParser(*this));
 
-    pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
-    while (bounds.first!=bounds.second) {
+    pair<CGIParser::walker,CGIParser::walker> bounds = m_parser->getParameters(name);
+    while (bounds.first != bounds.second) {
         values.push_back(bounds.first->second);
         ++bounds.first;
     }
@@ -195,7 +196,8 @@ const std::vector<XSECCryptoX509*>& RemotedRequest::getClientCertificates() cons
                     x509->loadX509PEM(cert.string(), cert.strlen());
                 else
                     x509->loadX509Base64Bin(cert.string(), cert.strlen());
-                m_certs.push_back(x509.release());
+                m_certs.push_back(x509.get());
+                x509.release();
             }
             catch(XSECException& e) {
                 auto_ptr_char temp(e.getMsg());
@@ -243,8 +245,8 @@ long RemotedResponse::sendResponse(std::istream& in, long status)
     string msg;
     char buf[1024];
     while (in) {
-        in.read(buf,1024);
-        msg.append(buf,in.gcount());
+        in.read(buf, 1024);
+        msg.append(buf, in.gcount());
     }
     if (!m_output.isstruct())
         m_output.structure();
@@ -283,7 +285,7 @@ void RemotedHandler::setAddress(const char* address)
     if (!conf.isEnabled(SPConfig::InProcess)) {
         ListenerService* listener = conf.getServiceProvider()->getListenerService(false);
         if (listener)
-            listener->regListener(m_address.c_str(),this);
+            listener->regListener(m_address.c_str(), this);
         else
             Category::getInstance(SHIBSP_LOGCAT".Handler").info("no ListenerService available, handler remoting disabled");
     }
@@ -329,7 +331,7 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector<string>* headers
         string hdr;
         DDF hin = in.addmember("headers").structure();
         if (headers) {
-            for (vector<string>::const_iterator h = headers->begin(); h!=headers->end(); ++h) {
+            for (vector<string>::const_iterator h = headers->begin(); h != headers->end(); ++h) {
                 hdr = request.getHeader(h->c_str());
                 if (!hdr.empty())
                     hin.addmember(h->c_str()).unsafe_string(hdr.c_str());
@@ -424,7 +426,7 @@ pair<bool,long> RemotedHandler::unwrap(SPRequest& request, DDF& out) const
         istringstream s(h["data"].string());
         return make_pair(true, request.sendResponse(s, h["status"].integer()));
     }
-    return make_pair(false,0L);
+    return make_pair(false, 0L);
 }
 
 HTTPRequest* RemotedHandler::getRequest(DDF& in) const
index b8f7471..545dda1 100644 (file)
@@ -33,6 +33,8 @@
 # include "SessionCache.h"
 # include "TransactionLog.h"
 # include "attribute/resolver/ResolutionContext.h"
+# include <boost/scoped_ptr.hpp>
+# include <boost/iterator/indirect_iterator.hpp>
 # include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/binding/SecurityPolicy.h>
@@ -46,6 +48,7 @@
 using namespace opensaml::saml1;
 using namespace opensaml::saml1p;
 using namespace opensaml;
+using namespace boost;
 using saml2::NameID;
 using saml2::NameIDBuilder;
 using saml2md::EntityDescriptor;
@@ -72,17 +75,12 @@ namespace shibsp {
         SAML1Consumer(const DOMElement* e, const char* appId)
             : AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".SSO.SAML1")) {
 #ifndef SHIBSP_LITE
-            m_ssoRule = nullptr;
             m_post = XMLString::equals(getString("Binding").second, samlconstants::SAML1_PROFILE_BROWSER_POST);
             if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
-                m_ssoRule = SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(SAML1BROWSERSSO_POLICY_RULE, e);
-#endif
-        }
-        virtual ~SAML1Consumer() {
-#ifndef SHIBSP_LITE
-            delete m_ssoRule;
+                m_ssoRule.reset(SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(SAML1BROWSERSSO_POLICY_RULE, e));
 #endif
         }
+        virtual ~SAML1Consumer() {}
 
 #ifndef SHIBSP_LITE
         void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
@@ -102,7 +100,7 @@ namespace shibsp {
             ) const;
 
         bool m_post;
-        SecurityPolicyRule* m_ssoRule;
+        scoped_ptr<SecurityPolicyRule> m_ssoRule;
 #else
         const XMLCh* getProtocolFamily() const {
             return samlconstants::SAML11_PROTOCOL_ENUM;
@@ -195,16 +193,17 @@ void SAML1Consumer::implementProtocol(
 
     // Ensure the BrowserSSO rule is in the policy set.
     if (find_if(policy.getRules(), _rulenamed(SAML1BROWSERSSO_POLICY_RULE)) == nullptr)
-        policy.getRules().push_back(m_ssoRule);
+        policy.getRules().push_back(m_ssoRule.get());
 
     // Populate recipient as audience.
     policy.getAudiences().push_back(application.getRelyingParty(entity)->getXMLString("entityID").second);
 
     time_t now = time(nullptr);
-    for (vector<saml1::Assertion*>::const_iterator a = assertions.begin(); a!=assertions.end(); ++a) {
+    for (indirect_iterator<vector<saml1::Assertion*>::const_iterator> a = make_indirect_iterator(assertions.begin());
+            a != make_indirect_iterator(assertions.end()); ++a) {
         try {
             // Skip unsigned assertion?
-            if (!(*a)->getSignature() && flag.first && flag.second)
+            if (!a->getSignature() && flag.first && flag.second)
                 throw SecurityPolicyException("The incoming assertion was unsigned, violating local security policy.");
 
             // We clear the security flag, so we can tell whether the token was secured on its own.
@@ -213,48 +212,48 @@ void SAML1Consumer::implementProtocol(
 
             // Extract message bits and re-verify Issuer information.
             extractMessageDetails(
-                *(*a),
-                (minor.first && minor.second==0) ? samlconstants::SAML10_PROTOCOL_ENUM : samlconstants::SAML11_PROTOCOL_ENUM, policy
+                *a, (minor.first && minor.second==0) ? samlconstants::SAML10_PROTOCOL_ENUM : samlconstants::SAML11_PROTOCOL_ENUM, policy
                 );
 
             // Run the policy over the assertion. Handles replay, freshness, and
             // signature verification, assuming the relevant rules are configured,
             // along with condition and profile enforcement.
-            policy.evaluate(*(*a), &httpRequest);
+            policy.evaluate(*a, &httpRequest);
 
             // If no security is in place now, we kick it.
             if (!alreadySecured && !policy.isAuthenticated())
                 throw SecurityPolicyException("Unable to establish security of incoming assertion.");
 
             // Track it as a valid token.
-            tokens.push_back(*a);
+            tokens.push_back(&(*a));
 
             // Save off the first valid SSO statement.
             const vector<AuthenticationStatement*>& statements =
-                    const_cast<const saml1::Assertion*>(*a)->getAuthenticationStatements();
-            for (vector<AuthenticationStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
-                if ((*s)->getAuthenticationInstant() &&
-                        (*s)->getAuthenticationInstantEpoch() - XMLToolingConfig::getConfig().clock_skew_secs > now) {
+                    const_cast<const saml1::Assertion&>(*a).getAuthenticationStatements();
+            for (indirect_iterator<vector<AuthenticationStatement*>::const_iterator> s = make_indirect_iterator(statements.begin());
+                    s != make_indirect_iterator(statements.end()); ++s) {
+                if (s->getAuthenticationInstant() &&
+                        s->getAuthenticationInstantEpoch() - XMLToolingConfig::getConfig().clock_skew_secs > now) {
                     contextualError = "The login time at your identity provider was future-dated.";
                 }
-                else if (authnskew.first && authnskew.second && (*s)->getAuthenticationInstant() &&
-                        (*s)->getAuthenticationInstantEpoch() <= now && (now - (*s)->getAuthenticationInstantEpoch() > authnskew.second)) {
+                else if (authnskew.first && authnskew.second && s->getAuthenticationInstant() &&
+                        s->getAuthenticationInstantEpoch() <= now && (now - s->getAuthenticationInstantEpoch() > authnskew.second)) {
                     contextualError = "The gap between now and the time you logged into your identity provider exceeds the allowed limit.";
                 }
-                else if (authnskew.first && authnskew.second && (*s)->getAuthenticationInstant() == nullptr) {
+                else if (authnskew.first && authnskew.second && s->getAuthenticationInstant() == nullptr) {
                     contextualError = "Your identity provider did not supply a time of login, violating local policy.";
                 }
                 else if (!ssoStatement) {
-                    ssoStatement = *s;
+                    ssoStatement = &(*s);
                     break;
                 }
             }
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.warn("detected a problem with assertion: %s", ex.what());
             if (!ssoStatement)
                 contextualError = ex.what();
-            badtokens.push_back(*a);
+            badtokens.push_back(&(*a));
         }
     }
 
@@ -286,7 +285,7 @@ void SAML1Consumer::implementProtocol(
     // To complete processing, we need to extract and resolve attributes and then create the session.
 
     // Normalize the SAML 1.x NameIdentifier...
-    auto_ptr<NameID> nameid(n ? NameIDBuilder::buildNameID() : nullptr);
+    scoped_ptr<NameID> nameid(n ? NameIDBuilder::buildNameID() : nullptr);
     if (n) {
         nameid->setName(n->getName());
         nameid->setFormat(n->getFormat());
@@ -294,7 +293,7 @@ void SAML1Consumer::implementProtocol(
     }
 
     // The context will handle deleting attributes and new tokens.
-    auto_ptr<ResolutionContext> ctx(
+    scoped_ptr<ResolutionContext> ctx(
         resolveAttributes(
             application,
             policy.getIssuerMetadata(),
@@ -310,7 +309,7 @@ void SAML1Consumer::implementProtocol(
             )
         );
 
-    if (ctx.get()) {
+    if (ctx) {
         // Copy over any new tokens, but leave them in the context for cleanup.
         tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end());
     }
@@ -334,11 +333,11 @@ void SAML1Consumer::implementProtocol(
         ssoStatement->getAuthenticationMethod(),
         nullptr,
         &tokens,
-        ctx.get() ? &ctx->getResolvedAttributes() : nullptr
+        ctx ? &ctx->getResolvedAttributes() : nullptr
         );
 
-    auto_ptr<LoginEvent> login_event(newLoginEvent(application, httpRequest));
-    if (login_event.get()) {
+    scoped_ptr<LoginEvent> login_event(newLoginEvent(application, httpRequest));
+    if (login_event) {
         login_event->m_sessionID = session_id.c_str();
         login_event->m_peer = entity;
         auto_ptr_char prot(
@@ -349,7 +348,7 @@ void SAML1Consumer::implementProtocol(
         login_event->m_nameID = nameid.get();
         login_event->m_saml1AuthnStatement = ssoStatement;
         login_event->m_saml1Response = response;
-        if (ctx.get())
+        if (ctx)
             login_event->m_attributes = &ctx->getResolvedAttributes();
         application.getServiceProvider().getTransactionLog()->write(*login_event);
     }
index 1afb9cf..a267af5 100644 (file)
@@ -53,12 +53,14 @@ using namespace opensaml;
 # include "lite/SAMLConstants.h"
 #endif
 
+#include <boost/scoped_ptr.hpp>
 #include <xmltooling/soap/SOAP.h>
 
 using namespace shibspconstants;
 using namespace shibsp;
 using namespace soap11;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -72,7 +74,7 @@ namespace shibsp {
     {
     public:
         SAML2ArtifactResolution(const DOMElement* e, const char* appId);
-        virtual ~SAML2ArtifactResolution();
+        virtual ~SAML2ArtifactResolution() {}
 
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
         void receive(DDF& in, ostream& out);
@@ -104,11 +106,12 @@ namespace shibsp {
             hurl += loc;
             auto_ptr_XMLCh widen(hurl.c_str());
 
-            ArtifactResolutionService* ep = ArtifactResolutionServiceBuilder::buildArtifactResolutionService();
+            auto_ptr<ArtifactResolutionService> ep(ArtifactResolutionServiceBuilder::buildArtifactResolutionService());
             ep->setLocation(widen.get());
             ep->setBinding(getXMLString("Binding").second);
             ep->setIndex(ix.second);
-            role.getArtifactResolutionServices().push_back(ep);
+            role.getArtifactResolutionServices().push_back(ep.get());
+            ep.release();
         }
 #endif
         const XMLCh* getProtocolFamily() const {
@@ -122,9 +125,8 @@ namespace shibsp {
             const Application& app, const ArtifactResolve& request, HTTPResponse& httpResponse, const EntityDescriptor* recipient
             ) const;
 
-        MessageEncoder* m_encoder;
-        MessageDecoder* m_decoder;
-        xmltooling::QName m_role;
+        scoped_ptr<MessageEncoder> m_encoder;
+        scoped_ptr<MessageDecoder> m_decoder;
 #endif
     };
 
@@ -141,26 +143,19 @@ namespace shibsp {
 
 SAML2ArtifactResolution::SAML2ArtifactResolution(const DOMElement* e, const char* appId)
     : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".ArtifactResolution.SAML2"))
-#ifndef SHIBSP_LITE
-        ,m_encoder(nullptr), m_decoder(nullptr), m_role(samlconstants::SAML20MD_NS, opensaml::saml2md::IDPSSODescriptor::LOCAL_NAME)
-#endif
 {
 #ifndef SHIBSP_LITE
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-        try {
-            m_encoder = SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
-                getString("Binding").second,pair<const DOMElement*,const XMLCh*>(e,nullptr)
-                );
-            m_decoder = SAMLConfig::getConfig().MessageDecoderManager.newPlugin(
-                getString("Binding").second,pair<const DOMElement*,const XMLCh*>(e,nullptr)
-                );
-        }
-        catch (exception&) {
-            m_log.error("error building MessageEncoder/Decoder pair for binding (%s)", getString("Binding").second);
-            delete m_encoder;
-            delete m_decoder;
-            throw;
-        }
+        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)
+                )
+            );
     }
 #endif
     string address(appId);
@@ -169,14 +164,6 @@ SAML2ArtifactResolution::SAML2ArtifactResolution(const DOMElement* e, const char
     setAddress(address.c_str());
 }
 
-SAML2ArtifactResolution::~SAML2ArtifactResolution()
-{
-#ifndef SHIBSP_LITE
-    delete m_encoder;
-    delete m_decoder;
-#endif
-}
-
 pair<bool,long> SAML2ArtifactResolution::run(SPRequest& request, bool isHandler) const
 {
     string relayState;
@@ -192,11 +179,11 @@ pair<bool,long> SAML2ArtifactResolution::run(SPRequest& request, bool isHandler)
             DDF out,in = wrap(request, nullptr, true);
             DDFJanitor jin(in), jout(out);
             
-            out=request.getServiceProvider().getListenerService()->send(in);
+            out = request.getServiceProvider().getListenerService()->send(in);
             return unwrap(request, out);
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error while processing request: %s", ex.what());
 
         // Build a SOAP fault around the error.
@@ -216,10 +203,11 @@ pair<bool,long> SAML2ArtifactResolution::run(SPRequest& request, bool isHandler)
         return make_pair(true, ret);
 #else
         // Brute force the fault to avoid library dependency.
-        auto_ptr<Envelope> env(EnvelopeBuilder::buildEnvelope());
+        scoped_ptr<Envelope> env(EnvelopeBuilder::buildEnvelope());
         Body* body = BodyBuilder::buildBody();
         env->setBody(body);
-        body->getUnknownXMLObjects().push_back(fault.release());
+        body->getUnknownXMLObjects().push_back(fault.get());
+        fault.release();
         string xmlbuf;
         XMLHelper::serialize(env->marshall(), xmlbuf);
         istringstream s(xmlbuf);
@@ -241,22 +229,22 @@ void SAML2ArtifactResolution::receive(DDF& in, ostream& out)
     }
     
     // Unpack the request.
-    auto_ptr<HTTPRequest> req(getRequest(in));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
     //m_log.debug("found %d client certificates", req->getClientCertificates().size());
 
     // Wrap a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
         
     try {
         // Since we're remoted, the result should either be a throw, a false/0 return,
         // which we just return as an empty structure, or a response/redirect,
         // which we capture in the facade and send back.
-        processMessage(*app, *req.get(), *resp.get());
+        processMessage(*app, *req, *resp);
         out << ret;
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
 #ifndef SHIBSP_LITE
         m_log.error("error while processing request: %s", ex.what());
 
@@ -270,7 +258,7 @@ void SAML2ArtifactResolution::receive(DDF& in, ostream& out)
         pair<bool,bool> flag = getBool("detailedErrors", m_configNS.get());
         auto_ptr_XMLCh msg((flag.first && flag.second) ? ex.what() : "Error processing request.");
         fs->setString(msg.get());
-        m_encoder->encode(*resp.get(), fault.get(), nullptr);
+        m_encoder->encode(*resp, fault.get(), nullptr);
         fault.release();
         out << ret;
 #else
@@ -297,14 +285,14 @@ pair<bool,long> SAML2ArtifactResolution::processMessage(const Application& appli
     Locker metadataLocker(application.getMetadataProvider());
 
     // Create the policy.
-    auto_ptr<SecurityPolicy> policy(
-        application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, &m_role, policyId.second)
+    scoped_ptr<SecurityPolicy> policy(
+        application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, &IDPSSODescriptor::ELEMENT_QNAME, policyId.second)
         );
     
     // Decode the message and verify that it's a secured ArtifactResolve request.
     string relayState;
-    auto_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, *policy.get()));
-    if (!msg.get())
+    scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, *policy));
+    if (!msg)
         throw BindingException("Failed to decode a SAML request.");
     const ArtifactResolve* req = dynamic_cast<const ArtifactResolve*>(msg.get());
     if (!req)
@@ -321,7 +309,7 @@ pair<bool,long> SAML2ArtifactResolution::processMessage(const Application& appli
         m_log.info("resolving artifact (%s) for (%s)", artifact.get(), issuer.get() ? issuer.get() : "unknown");
 
         // Parse the artifact and retrieve the object.
-        auto_ptr<SAMLArtifact> artobj(SAMLArtifact::parse(artifact.get()));
+        scoped_ptr<SAMLArtifact> artobj(SAMLArtifact::parse(artifact.get()));
         auto_ptr<XMLObject> payload(artmap->retrieveContent(artobj.get(), issuer.get()));
 
         if (!policy->isAuthenticated()) {
@@ -336,15 +324,16 @@ pair<bool,long> SAML2ArtifactResolution::processMessage(const Application& appli
         resp->setInResponseTo(req->getID());
         Issuer* me = IssuerBuilder::buildIssuer();
         me->setName(application.getRelyingParty(entity)->getXMLString("entityID").second);
-        resp->setPayload(payload.release());
+        resp->setPayload(payload.get());
+        payload.release();
 
         long ret = sendMessage(
             *m_encoder, resp.get(), relayState.c_str(), nullptr, policy->getIssuerMetadata(), application, httpResponse, "signResponses"
             );
         resp.release();  // freed by encoder
-        return make_pair(true,ret);
+        return make_pair(true, ret);
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         // Trap localized errors.
         m_log.error("error processing artifact request: %s", ex.what());
         return emptyResponse(application, *req, httpResponse, entity);
@@ -363,9 +352,9 @@ pair<bool,long> SAML2ArtifactResolution::emptyResponse(
     resp->setInResponseTo(request.getID());
     Issuer* me = IssuerBuilder::buildIssuer();
     me->setName(app.getRelyingParty(recipient)->getXMLString("entityID").second);
-    fillStatus(*resp.get(), StatusCode::SUCCESS);
+    fillStatus(*resp, StatusCode::SUCCESS);
     long ret = m_encoder->encode(httpResponse, resp.get(), nullptr);
     resp.release();  // freed by encoder
-    return make_pair(true,ret);
+    return make_pair(true, ret);
 }
 #endif
index 47ebc4f..98f9522 100644 (file)
@@ -33,6 +33,8 @@
 # include "SessionCache.h"
 # include "TransactionLog.h"
 # include "attribute/resolver/ResolutionContext.h"
+# include <boost/scoped_ptr.hpp>
+# include <boost/iterator/indirect_iterator.hpp>
 # include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/binding/SecurityPolicyRule.h>
@@ -47,6 +49,7 @@ using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
 using namespace opensaml;
+using namespace boost;
 # ifndef min
 #  define min(a,b)            (((a) < (b)) ? (a) : (b))
 # endif
@@ -71,16 +74,11 @@ namespace shibsp {
         SAML2Consumer(const DOMElement* e, const char* appId)
             : AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".SSO.SAML2")) {
 #ifndef SHIBSP_LITE
-            m_ssoRule = nullptr;
             if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
-                m_ssoRule = SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(BEARER_POLICY_RULE, e);
-#endif
-        }
-        virtual ~SAML2Consumer() {
-#ifndef SHIBSP_LITE
-            delete m_ssoRule;
+                m_ssoRule.reset(SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(BEARER_POLICY_RULE, e));
 #endif
         }
+        virtual ~SAML2Consumer() {}
 
 #ifndef SHIBSP_LITE
         void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
@@ -98,7 +96,7 @@ namespace shibsp {
             const XMLObject& xmlObject
             ) const;
 
-        SecurityPolicyRule* m_ssoRule;
+        scoped_ptr<SecurityPolicyRule> m_ssoRule;
 #else
         const XMLCh* getProtocolFamily() const {
             return samlconstants::SAML20P_NS;
@@ -169,7 +167,7 @@ void SAML2Consumer::implementProtocol(
     vector<const opensaml::Assertion*> badtokens;
 
     // And also track "owned" tokens that we decrypt here.
-    vector<saml2::Assertion*> ownedtokens;
+    vector< boost::shared_ptr<saml2::Assertion> > ownedtokens;
 
     // With this flag on, we ignore any unsigned assertions.
     const EntityDescriptor* entity = nullptr;
@@ -188,16 +186,17 @@ void SAML2Consumer::implementProtocol(
 
     // Ensure the Bearer rule is in the policy set.
     if (find_if(policy.getRules(), _rulenamed(BEARER_POLICY_RULE)) == nullptr)
-        policy.getRules().push_back(m_ssoRule);
+        policy.getRules().push_back(m_ssoRule.get());
 
     // Populate recipient as audience.
     policy.getAudiences().push_back(application.getRelyingParty(entity)->getXMLString("entityID").second);
 
     time_t now = time(nullptr);
-    for (vector<saml2::Assertion*>::const_iterator a = assertions.begin(); a!=assertions.end(); ++a) {
+    for (indirect_iterator<vector<saml2::Assertion*>::const_iterator> a = make_indirect_iterator(assertions.begin());
+            a != make_indirect_iterator(assertions.end()); ++a) {
         try {
             // Skip unsigned assertion?
-            if (!(*a)->getSignature() && flag.first && flag.second)
+            if (!a->getSignature() && flag.first && flag.second)
                 throw SecurityPolicyException("The incoming assertion was unsigned, violating local security policy.");
 
             // We clear the security flag, so we can tell whether the token was secured on its own.
@@ -205,12 +204,12 @@ void SAML2Consumer::implementProtocol(
             policy.reset(true);
 
             // Extract message bits and re-verify Issuer information.
-            extractMessageDetails(*(*a), samlconstants::SAML20P_NS, policy);
+            extractMessageDetails(*a, samlconstants::SAML20P_NS, policy);
 
             // Run the policy over the assertion. Handles replay, freshness, and
             // signature verification, assuming the relevant rules are configured,
             // along with condition and profile enforcement.
-            policy.evaluate(*(*a), &httpRequest);
+            policy.evaluate(*a, &httpRequest);
 
             // If no security is in place now, we kick it.
             if (!alreadySecured && !policy.isAuthenticated())
@@ -220,7 +219,7 @@ void SAML2Consumer::implementProtocol(
             if (!entity && policy.getIssuerMetadata()) {
                 entity = dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent());
                 flag = application.getRelyingParty(entity)->getBool("requireSignedAssertions");
-                if (!(*a)->getSignature() && flag.first && flag.second)
+                if (!a->getSignature() && flag.first && flag.second)
                     throw SecurityPolicyException("The incoming assertion was unsigned, violating local security policy.");
             }
 
@@ -234,35 +233,36 @@ void SAML2Consumer::implementProtocol(
             }
 
             // Track it as a valid token.
-            tokens.push_back(*a);
+            tokens.push_back(&(*a));
 
             // Save off the first valid SSO statement, but favor the "soonest" session expiration.
-            const vector<AuthnStatement*>& statements = const_cast<const saml2::Assertion*>(*a)->getAuthnStatements();
-            for (vector<AuthnStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
-                if ((*s)->getAuthnInstant() && (*s)->getAuthnInstantEpoch() - XMLToolingConfig::getConfig().clock_skew_secs > now) {
+            const vector<AuthnStatement*>& statements = const_cast<const saml2::Assertion&>(*a).getAuthnStatements();
+            for (indirect_iterator<vector<AuthnStatement*>::const_iterator> s = make_indirect_iterator(statements.begin());
+                    s != make_indirect_iterator(statements.end()); ++s) {
+                if (s->getAuthnInstant() && s->getAuthnInstantEpoch() - XMLToolingConfig::getConfig().clock_skew_secs > now) {
                     contextualError = "The login time at your identity provider was future-dated.";
                 }
-                else if (authnskew.first && authnskew.second && (*s)->getAuthnInstant() &&
-                        (*s)->getAuthnInstantEpoch() <= now && (now - (*s)->getAuthnInstantEpoch() > authnskew.second)) {
+                else if (authnskew.first && authnskew.second && s->getAuthnInstant() &&
+                        s->getAuthnInstantEpoch() <= now && (now - s->getAuthnInstantEpoch() > authnskew.second)) {
                     contextualError = "The gap between now and the time you logged into your identity provider exceeds the allowed limit.";
                 }
-                else if (authnskew.first && authnskew.second && (*s)->getAuthnInstant() == nullptr) {
+                else if (authnskew.first && authnskew.second && s->getAuthnInstant() == nullptr) {
                     contextualError = "Your identity provider did not supply a time of login, violating local policy.";
                 }
-                else if (!ssoStatement || (*s)->getSessionNotOnOrAfterEpoch() < ssoStatement->getSessionNotOnOrAfterEpoch()) {
-                    ssoStatement = *s;
+                else if (!ssoStatement || s->getSessionNotOnOrAfterEpoch() < ssoStatement->getSessionNotOnOrAfterEpoch()) {
+                    ssoStatement = &(*s);
                 }
             }
 
             // Save off the first valid Subject, but favor an unencrypted NameID over anything else.
-            if (!ssoSubject || (!ssoSubject->getNameID() && (*a)->getSubject()->getNameID()))
-                ssoSubject = (*a)->getSubject();
+            if (!ssoSubject || (!ssoSubject->getNameID() && a->getSubject()->getNameID()))
+                ssoSubject = a->getSubject();
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.warn("detected a problem with assertion: %s", ex.what());
             if (!ssoStatement)
                 contextualError = ex.what();
-            badtokens.push_back(*a);
+            badtokens.push_back(&(*a));
         }
     }
 
@@ -271,24 +271,24 @@ void SAML2Consumer::implementProtocol(
     if (!cr && !encassertions.empty())
         m_log.warn("found encrypted assertions, but no CredentialResolver was available");
 
-    for (vector<saml2::EncryptedAssertion*>::const_iterator ea = encassertions.begin(); cr && ea!=encassertions.end(); ++ea) {
+    for (indirect_iterator<vector<saml2::EncryptedAssertion*>::const_iterator> ea = make_indirect_iterator(encassertions.begin());
+            ea != make_indirect_iterator(encassertions.end()); ++ea) {
         // Attempt to decrypt it.
-        saml2::Assertion* decrypted=nullptr;
+        boost::shared_ptr<saml2::Assertion> decrypted;
         try {
             Locker credlocker(cr);
-            auto_ptr<MetadataCredentialCriteria> mcc(
+            scoped_ptr<MetadataCredentialCriteria> mcc(
                 policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : nullptr
                 );
-            auto_ptr<XMLObject> wrapper((*ea)->decrypt(*cr, application.getRelyingParty(entity)->getXMLString("entityID").second, mcc.get()));
-            decrypted = dynamic_cast<saml2::Assertion*>(wrapper.get());
+            boost::shared_ptr<XMLObject> wrapper(ea->decrypt(*cr, application.getRelyingParty(entity)->getXMLString("entityID").second, mcc.get()));
+            decrypted = dynamic_pointer_cast<saml2::Assertion>(wrapper);
             if (decrypted) {
-                wrapper.release();
                 ownedtokens.push_back(decrypted);
                 if (m_log.isDebugEnabled())
                     m_log.debugStream() << "decrypted Assertion: " << *decrypted << logging::eol;
             }
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error(ex.what());
         }
         if (!decrypted)
@@ -332,38 +332,38 @@ void SAML2Consumer::implementProtocol(
             }
 
             // Track it as a valid token.
-            tokens.push_back(decrypted);
+            tokens.push_back(decrypted.get());
 
             // Save off the first valid SSO statement, but favor the "soonest" session expiration.
-            const vector<AuthnStatement*>& statements = const_cast<const saml2::Assertion*>(decrypted)->getAuthnStatements();
-            for (vector<AuthnStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
-                if (authnskew.first && authnskew.second && (*s)->getAuthnInstant() && (now - (*s)->getAuthnInstantEpoch() > authnskew.second))
+            const vector<AuthnStatement*>& statements = const_cast<const saml2::Assertion*>(decrypted.get())->getAuthnStatements();
+            for (indirect_iterator<vector<AuthnStatement*>::const_iterator> s = make_indirect_iterator(statements.begin());
+                    s != make_indirect_iterator(statements.end()); ++s) {
+                if (authnskew.first && authnskew.second && s->getAuthnInstant() && (now - s->getAuthnInstantEpoch() > authnskew.second))
                     contextualError = "The gap between now and the time you logged into your identity provider exceeds the limit.";
-                else if (!ssoStatement || (*s)->getSessionNotOnOrAfterEpoch() < ssoStatement->getSessionNotOnOrAfterEpoch())
-                    ssoStatement = *s;
+                else if (!ssoStatement || s->getSessionNotOnOrAfterEpoch() < ssoStatement->getSessionNotOnOrAfterEpoch())
+                    ssoStatement = &(*s);
             }
 
             // Save off the first valid Subject, but favor an unencrypted NameID over anything else.
             if (!ssoSubject || (!ssoSubject->getNameID() && decrypted->getSubject()->getNameID()))
                 ssoSubject = decrypted->getSubject();
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.warn("detected a problem with assertion: %s", ex.what());
             if (!ssoStatement)
                 contextualError = ex.what();
-            badtokens.push_back(decrypted);
+            badtokens.push_back(decrypted.get());
         }
     }
 
     if (!ssoStatement) {
-        for_each(ownedtokens.begin(), ownedtokens.end(), xmltooling::cleanup<saml2::Assertion>());
         if (contextualError.empty())
             throw FatalProfileException("A valid authentication statement was not found in the incoming message.");
         throw FatalProfileException(contextualError.c_str());
     }
 
     // May need to decrypt NameID.
-    bool ownedName = false;
+    scoped_ptr<XMLObject> decryptedID;
     NameID* ssoName = ssoSubject->getNameID();
     if (!ssoName) {
         EncryptedID* encname = ssoSubject->getEncryptedID();
@@ -372,20 +372,18 @@ void SAML2Consumer::implementProtocol(
                 m_log.warn("found encrypted NameID, but no decryption credential was available");
             else {
                 Locker credlocker(cr);
-                auto_ptr<MetadataCredentialCriteria> mcc(
+                scoped_ptr<MetadataCredentialCriteria> mcc(
                     policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : nullptr
                     );
                 try {
-                    auto_ptr<XMLObject> decryptedID(encname->decrypt(*cr,application.getRelyingParty(entity)->getXMLString("entityID").second,mcc.get()));
+                    decryptedID.reset(encname->decrypt(*cr, application.getRelyingParty(entity)->getXMLString("entityID").second, mcc.get()));
                     ssoName = dynamic_cast<NameID*>(decryptedID.get());
                     if (ssoName) {
-                        ownedName = true;
-                        decryptedID.release();
                         if (m_log.isDebugEnabled())
                             m_log.debugStream() << "decrypted NameID: " << *ssoName << logging::eol;
                     }
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     m_log.error(ex.what());
                 }
             }
@@ -412,81 +410,69 @@ void SAML2Consumer::implementProtocol(
 
     const AuthnContext* authnContext = ssoStatement->getAuthnContext();
 
-    try {
-        // The context will handle deleting attributes and new tokens.
-        auto_ptr<ResolutionContext> ctx(
-            resolveAttributes(
-                application,
-                policy.getIssuerMetadata(),
-                samlconstants::SAML20P_NS,
-                nullptr,
-                nullptr,
-                ssoName,
-                ssoStatement,
-                (authnContext && authnContext->getAuthnContextClassRef()) ? authnContext->getAuthnContextClassRef()->getReference() : nullptr,
-                (authnContext && authnContext->getAuthnContextDeclRef()) ? authnContext->getAuthnContextDeclRef()->getReference() : nullptr,
-                &tokens
-                )
-            );
-
-        if (ctx.get()) {
-            // Copy over any new tokens, but leave them in the context for cleanup.
-            tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end());
-        }
-
-        // Now merge in bad tokens for caching.
-        tokens.insert(tokens.end(), badtokens.begin(), badtokens.end());
-
-        string session_id;
-        application.getServiceProvider().getSessionCache()->insert(
-            session_id,
+    // The context will handle deleting attributes and new tokens.
+    scoped_ptr<ResolutionContext> ctx(
+        resolveAttributes(
             application,
-            httpRequest,
-            httpResponse,
-            sessionExp,
-            entity,
+            policy.getIssuerMetadata(),
             samlconstants::SAML20P_NS,
+            nullptr,
+            nullptr,
             ssoName,
-            ssoStatement->getAuthnInstant() ? ssoStatement->getAuthnInstant()->getRawData() : nullptr,
-            ssoStatement->getSessionIndex(),
+            ssoStatement,
             (authnContext && authnContext->getAuthnContextClassRef()) ? authnContext->getAuthnContextClassRef()->getReference() : nullptr,
             (authnContext && authnContext->getAuthnContextDeclRef()) ? authnContext->getAuthnContextDeclRef()->getReference() : nullptr,
-            &tokens,
-            ctx.get() ? &ctx->getResolvedAttributes() : nullptr
-            );
+            &tokens
+            )
+        );
 
-        try {
-            auto_ptr<TransactionLog::Event> event(newLoginEvent(application, httpRequest));
-            LoginEvent* login_event = dynamic_cast<LoginEvent*>(event.get());
-            if (login_event) {
-                login_event->m_sessionID = session_id.c_str();
-                login_event->m_peer = entity;
-                auto_ptr_char prot(getProtocolFamily());
-                login_event->m_protocol = prot.get();
-                login_event->m_nameID = ssoName;
-                login_event->m_saml2AuthnStatement = ssoStatement;
-                login_event->m_saml2Response = response;
-                if (ctx.get())
-                    login_event->m_attributes = &ctx->getResolvedAttributes();
-                application.getServiceProvider().getTransactionLog()->write(*login_event);
-            }
-            else {
-                m_log.warn("unable to audit event, log event object was of an incorrect type");
-            }
+    if (ctx) {
+        // Copy over any new tokens, but leave them in the context for cleanup.
+        tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end());
+    }
+
+    // Now merge in bad tokens for caching.
+    tokens.insert(tokens.end(), badtokens.begin(), badtokens.end());
+
+    string session_id;
+    application.getServiceProvider().getSessionCache()->insert(
+        session_id,
+        application,
+        httpRequest,
+        httpResponse,
+        sessionExp,
+        entity,
+        samlconstants::SAML20P_NS,
+        ssoName,
+        ssoStatement->getAuthnInstant() ? ssoStatement->getAuthnInstant()->getRawData() : nullptr,
+        ssoStatement->getSessionIndex(),
+        (authnContext && authnContext->getAuthnContextClassRef()) ? authnContext->getAuthnContextClassRef()->getReference() : nullptr,
+        (authnContext && authnContext->getAuthnContextDeclRef()) ? authnContext->getAuthnContextDeclRef()->getReference() : nullptr,
+        &tokens,
+        ctx ? &ctx->getResolvedAttributes() : nullptr
+        );
+
+    try {
+        scoped_ptr<TransactionLog::Event> event(newLoginEvent(application, httpRequest));
+        LoginEvent* login_event = dynamic_cast<LoginEvent*>(event.get());
+        if (login_event) {
+            login_event->m_sessionID = session_id.c_str();
+            login_event->m_peer = entity;
+            auto_ptr_char prot(getProtocolFamily());
+            login_event->m_protocol = prot.get();
+            login_event->m_nameID = ssoName;
+            login_event->m_saml2AuthnStatement = ssoStatement;
+            login_event->m_saml2Response = response;
+            if (ctx)
+                login_event->m_attributes = &ctx->getResolvedAttributes();
+            application.getServiceProvider().getTransactionLog()->write(*login_event);
         }
-        catch (exception& ex) {
-            m_log.warn("exception auditing event: %s", ex.what());
+        else {
+            m_log.warn("unable to audit event, log event object was of an incorrect type");
         }
-
-        if (ownedName)
-            delete ssoName;
-        for_each(ownedtokens.begin(), ownedtokens.end(), xmltooling::cleanup<saml2::Assertion>());
     }
-    catch (exception&) {
-        if (ownedName)
-            delete ssoName;
-        for_each(ownedtokens.begin(), ownedtokens.end(), xmltooling::cleanup<saml2::Assertion>());
-        throw;
+    catch (std::exception& ex) {
+        m_log.warn("exception auditing event: %s", ex.what());
     }
 }
 
index 7901106..a5371aa 100644 (file)
 # include "security/SecurityPolicyProvider.h"
 # include "metadata/MetadataProviderCriteria.h"
 # include <fstream>
+# include <boost/algorithm/string.hpp>
+# include <boost/iterator/indirect_iterator.hpp>
+# include <boost/lambda/bind.hpp>
+# include <boost/lambda/if.hpp>
+# include <boost/lambda/lambda.hpp>
 # include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/saml2/core/Protocols.h>
@@ -50,12 +55,16 @@ using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
 using namespace opensaml;
+using namespace boost::lambda;
 #else
 # include "lite/SAMLConstants.h"
 #endif
 
+#include <boost/scoped_ptr.hpp>
+
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -69,15 +78,7 @@ namespace shibsp {
     {
     public:
         SAML2Logout(const DOMElement* e, const char* appId);
-        virtual ~SAML2Logout() {
-#ifndef SHIBSP_LITE
-            if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-                delete m_decoder;
-                XMLString::release(&m_outgoing);
-                for_each(m_encoders.begin(), m_encoders.end(), cleanup_pair<const XMLCh*,MessageEncoder>());
-            }
-#endif
-        }
+        virtual ~SAML2Logout() {}
 
         void receive(DDF& in, ostream& out);
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
@@ -131,11 +132,9 @@ namespace shibsp {
             return e;
         }
 
-        xmltooling::QName m_role;
-        MessageDecoder* m_decoder;
-        XMLCh* m_outgoing;
-        vector<const XMLCh*> m_bindings;
-        map<const XMLCh*,MessageEncoder*> m_encoders;
+        scoped_ptr<MessageDecoder> m_decoder;
+        vector<string> m_bindings;
+        map< string,boost::shared_ptr<MessageEncoder> > m_encoders;
         auto_ptr_char m_protocol;
 #endif
     };
@@ -153,7 +152,7 @@ namespace shibsp {
 SAML2Logout::SAML2Logout(const DOMElement* e, const char* appId)
     : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".Logout.SAML2"))
 #ifndef SHIBSP_LITE
-        ,m_role(samlconstants::SAML20MD_NS, IDPSSODescriptor::LOCAL_NAME), m_decoder(nullptr), m_outgoing(nullptr), m_protocol(samlconstants::SAML20P_NS)
+        ,m_protocol(samlconstants::SAML20P_NS)
 #endif
 {
     m_initiator = false;
@@ -166,60 +165,51 @@ SAML2Logout::SAML2Logout(const DOMElement* e, const char* appId)
         SAMLConfig& conf = SAMLConfig::getConfig();
 
         // Handle incoming binding.
-        m_decoder = conf.MessageDecoderManager.newPlugin(
-            getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
+        m_decoder.reset(
+            conf.MessageDecoderManager.newPlugin(
+                getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
+                )
             );
         m_decoder->setArtifactResolver(SPConfig::getConfig().getArtifactResolver());
 
         if (m_decoder->isUserAgentPresent()) {
             // Handle front-channel binding setup.
-            pair<bool,const XMLCh*> outgoing = getXMLString("outgoingBindings", m_configNS.get());
+            string dupBindings;
+            pair<bool,const char*> outgoing = getString("outgoingBindings", m_configNS.get());
             if (outgoing.first) {
-                m_outgoing = XMLString::replicate(outgoing.second);
-                XMLString::trim(m_outgoing);
+                dupBindings = outgoing.second;
             }
             else {
                 // No override, so we'll install a default binding precedence.
-                string prec = string(samlconstants::SAML20_BINDING_HTTP_REDIRECT) + ' ' + samlconstants::SAML20_BINDING_HTTP_POST + ' ' +
+                dupBindings = string(samlconstants::SAML20_BINDING_HTTP_REDIRECT) + ' ' + samlconstants::SAML20_BINDING_HTTP_POST + ' ' +
                     samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN + ' ' + samlconstants::SAML20_BINDING_HTTP_ARTIFACT;
-                m_outgoing = XMLString::transcode(prec.c_str());
             }
 
-            int pos;
-            XMLCh* start = m_outgoing;
-            while (start && *start) {
-                pos = XMLString::indexOf(start,chSpace);
-                if (pos != -1)
-                    *(start + pos)=chNull;
-                m_bindings.push_back(start);
+            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 {
-                    auto_ptr_char b(start);
-                    MessageEncoder * encoder = conf.MessageEncoderManager.newPlugin(
-                        b.get(), pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
+                    boost::shared_ptr<MessageEncoder> encoder(
+                        conf.MessageEncoderManager.newPlugin(*b, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS))
                         );
                     if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
-                        m_encoders[start] = encoder;
-                        m_log.debug("supporting outgoing binding (%s)", b.get());
+                        m_encoders[*b] = encoder;
+                        m_log.debug("supporting outgoing binding (%s)", b->c_str());
                     }
                     else {
-                        delete encoder;
-                        m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b.get());
+                        m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b->c_str());
                     }
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     m_log.error("error building MessageEncoder: %s", ex.what());
                 }
-                if (pos != -1)
-                    start = start + pos + 1;
-                else
-                    break;
             }
         }
         else {
-            MessageEncoder* encoder = conf.MessageEncoderManager.newPlugin(
-                getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
+            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))
                 );
-            m_encoders.insert(pair<const XMLCh*,MessageEncoder*>(nullptr, encoder));
+            m_encoders[b.second] = encoder;
         }
     }
 #endif
@@ -256,8 +246,8 @@ pair<bool,long> SAML2Logout::run(SPRequest& request, bool isHandler) const
 void SAML2Logout::receive(DDF& in, ostream& out)
 {
     // Find application.
-    const char* aid=in["application_id"].string();
-    const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+    const char* aid = in["application_id"].string();
+    const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
     if (!app) {
         // Something's horribly wrong.
         m_log.error("couldn't find application (%s) for logout", aid ? aid : "(missing)");
@@ -265,17 +255,17 @@ void SAML2Logout::receive(DDF& in, ostream& out)
     }
 
     // Unpack the request.
-    auto_ptr<HTTPRequest> req(getRequest(in));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
 
     // Wrap a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     // Since we're remoted, the result should either be a throw, which we pass on,
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    doRequest(*app, *req.get(), *resp.get());
+    doRequest(*app, *req, *resp);
     out << ret;
 }
 
@@ -287,7 +277,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
     SessionCacheEx* cacheex = dynamic_cast<SessionCacheEx*>(cache);
     string session_id = cache->active(application, request);
 
-    auto_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &request));
+    scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &request));
     if (logout_event.get() && !session_id.empty())
         logout_event->m_sessions.push_back(session_id);
 
@@ -308,7 +298,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
                 cache->remove(application, request, &response);
                 worked2 = true;
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("error removing session (%s): %s", session_id.c_str(), ex.what());
             }
         }
@@ -376,19 +366,19 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
     Locker metadataLocker(application.getMetadataProvider());
 
     // Create the policy.
-    auto_ptr<SecurityPolicy> policy(
-        application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, &m_role, policyId.second)
+    scoped_ptr<SecurityPolicy> policy(
+        application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, &IDPSSODescriptor::ELEMENT_QNAME, policyId.second)
         );
 
     // Decode the message.
     string relayState;
-    auto_ptr<XMLObject> msg(m_decoder->decode(relayState, request, *policy.get()));
+    scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, request, *policy));
     const LogoutRequest* logoutRequest = dynamic_cast<LogoutRequest*>(msg.get());
     if (logoutRequest) {
         if (!policy->isAuthenticated())
             throw SecurityPolicyException("Security of LogoutRequest not established.");
 
-        if (logout_event.get()) {
+        if (logout_event) {
             logout_event->m_saml2Request = logoutRequest;
             if (policy->getIssuerMetadata())
                 logout_event->m_peer = dynamic_cast<const EntityDescriptor*>(policy->getIssuerMetadata()->getParent());
@@ -413,7 +403,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
                 );
         }
 
-        bool ownedName = false;
+        scoped_ptr<XMLObject> decryptedID;
         NameID* nameid = logoutRequest->getNameID();
         if (!nameid) {
             // Check for EncryptedID.
@@ -424,11 +414,11 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
                     m_log.warn("found encrypted NameID, but no decryption credential was available");
                 else {
                     Locker credlocker(cr);
-                    auto_ptr<MetadataCredentialCriteria> mcc(
+                    scoped_ptr<MetadataCredentialCriteria> mcc(
                         policy->getIssuerMetadata() ? new MetadataCredentialCriteria(*policy->getIssuerMetadata()) : nullptr
                         );
                     try {
-                        auto_ptr<XMLObject> decryptedID(
+                        decryptedID.reset(
                             encname->decrypt(
                                 *cr,
                                 application.getRelyingParty(
@@ -439,12 +429,8 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
                                 )
                             );
                         nameid = dynamic_cast<NameID*>(decryptedID.get());
-                        if (nameid) {
-                            ownedName = true;
-                            decryptedID.release();
-                        }
                     }
-                    catch (exception& ex) {
+                    catch (std::exception& ex) {
                         m_log.error(ex.what());
                     }
                 }
@@ -465,14 +451,13 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
                 );
         }
 
-        auto_ptr<NameID> namewrapper(ownedName ? nameid : nullptr);
-
         // Suck indexes out of the request for next steps.
         set<string> indexes;
         EntityDescriptor* entity = policy->getIssuerMetadata() ? dynamic_cast<EntityDescriptor*>(policy->getIssuerMetadata()->getParent()) : nullptr;
         const vector<SessionIndex*> sindexes = logoutRequest->getSessionIndexs();
-        for (vector<SessionIndex*>::const_iterator i = sindexes.begin(); i != sindexes.end(); ++i) {
-            auto_ptr_char sindex((*i)->getSessionIndex());
+        for (indirect_iterator<vector<SessionIndex*>::const_iterator> i = make_indirect_iterator(sindexes.begin());
+                i != make_indirect_iterator(sindexes.end()); ++i) {
+            auto_ptr_char sindex(i->getSessionIndex());
             indexes.insert(sindex.get());
         }
 
@@ -504,9 +489,10 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
 
                 // Now we actually terminate everything except for the active session,
                 // if this is front-channel, for notification purposes.
-                for (vector<string>::const_iterator sit = sessions.begin(); sit != sessions.end(); ++sit)
-                    if (*sit != session_id)
-                        cacheex->remove(application, sit->c_str());   // using the ID-based removal operation
+                for_each(
+                    sessions.begin(), sessions.end(),
+                    if_(_1 != session_id)[lambda::bind(&SessionCacheEx::remove, cacheex, boost::ref(application), lambda::bind(&string::c_str, _1))]
+                    );
             }
             else {
                 m_log.warn("session cache does not support extended API, can't implement indirect logout of sessions");
@@ -514,9 +500,9 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
                     sessions.push_back(session_id);
             }
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error("error while logging out matching sessions: %s", ex.what());
-            if (logout_event.get()) {
+            if (logout_event) {
                 logout_event->m_nameID = nameid;
                 logout_event->m_sessions = sessions;
                 logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_PARTIAL;
@@ -557,13 +543,13 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
             try {
                 cache->remove(application, request, &response);
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 worked2 = false;
                 m_log.error("error removing active session (%s): %s", session_id.c_str(), ex.what());
             }
         }
 
-        if (logout_event.get()) {
+        if (logout_event) {
             logout_event->m_nameID = nameid;
             logout_event->m_sessions = sessions;
             logout_event->m_logoutType = (worked1 && worked2) ? LogoutEvent::LOGOUT_EVENT_PARTIAL : LogoutEvent::LOGOUT_EVENT_GLOBAL;
@@ -592,7 +578,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
             ex.raise();
         }
  
-        if (logout_event.get()) {
+        if (logout_event) {
             logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_PARTIAL;
             logout_event->m_saml2Response = logoutResponse;
             if (policy->getIssuerMetadata())
@@ -602,8 +588,8 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
         try {
             checkError(logoutResponse, policy->getIssuerMetadata()); // throws if Status doesn't look good...
         }
-        catch (exception& ex) {
-            if (logout_event.get()) {
+        catch (std::exception& ex) {
+            if (logout_event) {
                 logout_event->m_exception = &ex;
                 application.getServiceProvider().getTransactionLog()->write(*logout_event);
             }
@@ -618,12 +604,12 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
         const StatusCode* sc = logoutResponse->getStatus() ? logoutResponse->getStatus()->getStatusCode() : nullptr;
         sc = sc ? sc->getStatusCode() : nullptr;
         if (sc && XMLString::equals(sc->getValue(), StatusCode::PARTIAL_LOGOUT)) {
-            if (logout_event.get())
+            if (logout_event)
                 application.getServiceProvider().getTransactionLog()->write(*logout_event);
             return sendLogoutPage(application, request, response, "partial");
         }
 
-        if (logout_event.get()) {
+        if (logout_event) {
             logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_GLOBAL;
             application.getServiceProvider().getTransactionLog()->write(*logout_event);
         }
@@ -667,11 +653,12 @@ pair<bool,long> SAML2Logout::sendResponse(
     const MessageEncoder* encoder = nullptr;
     if (front) {
         const IDPSSODescriptor* idp = dynamic_cast<const IDPSSODescriptor*>(role);
-        for (vector<const XMLCh*>::const_iterator b = m_bindings.begin(); idp && b!=m_bindings.end(); ++b) {
-            if ((ep=EndpointManager<SingleLogoutService>(idp->getSingleLogoutServices()).getByBinding(*b))) {
-                map<const XMLCh*,MessageEncoder*>::const_iterator enc = m_encoders.find(*b);
-                if (enc!=m_encoders.end())
-                    encoder = enc->second;
+        for (vector<string>::const_iterator b = m_bindings.begin(); idp && b != m_bindings.end(); ++b) {
+            auto_ptr_XMLCh wideb(b->c_str());
+            if ((ep = EndpointManager<SingleLogoutService>(idp->getSingleLogoutServices()).getByBinding(wideb.get()))) {
+                map< string,boost::shared_ptr<MessageEncoder> >::const_iterator enc = m_encoders.find(*b);
+                if (enc != m_encoders.end())
+                    encoder = enc->second.get();
                 break;
             }
         }
@@ -683,7 +670,7 @@ pair<bool,long> SAML2Logout::sendResponse(
         }
     }
     else {
-        encoder = m_encoders.begin()->second;
+        encoder = m_encoders.begin()->second.get();
     }
 
     // Prepare response.
@@ -698,7 +685,7 @@ pair<bool,long> SAML2Logout::sendResponse(
     Issuer* issuer = IssuerBuilder::buildIssuer();
     logout->setIssuer(issuer);
     issuer->setName(application.getRelyingParty(dynamic_cast<EntityDescriptor*>(role->getParent()))->getXMLString("entityID").second);
-    fillStatus(*logout.get(), code, subcode, msg);
+    fillStatus(*logout, code, subcode, msg);
     logout->setID(SAMLConfig::getConfig().generateIdentifier());
     logout->setIssueInstant(time(nullptr));
 
@@ -711,7 +698,7 @@ pair<bool,long> SAML2Logout::sendResponse(
     auto_ptr_char dest(logout->getDestination());
     long ret = sendMessage(*encoder, logout.get(), relayState, dest.get(), role, application, httpResponse, front);
     logout.release();  // freed by encoder
-    return make_pair(true,ret);
+    return make_pair(true, ret);
 }
 
 #endif
index 895479d..9896d3a 100644 (file)
@@ -36,6 +36,8 @@
 # include "binding/SOAPClient.h"
 # include "metadata/MetadataProviderCriteria.h"
 # include "security/SecurityPolicy.h"
+# include <boost/algorithm/string.hpp>
+# include <boost/iterator/indirect_iterator.hpp>
 # include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/saml2/core/Protocols.h>
@@ -51,8 +53,11 @@ using namespace opensaml;
 # include "lite/SAMLConstants.h"
 #endif
 
+#include <boost/scoped_ptr.hpp>
+
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -66,14 +71,7 @@ namespace shibsp {
     {
     public:
         SAML2LogoutInitiator(const DOMElement* e, const char* appId);
-        virtual ~SAML2LogoutInitiator() {
-#ifndef SHIBSP_LITE
-            if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-                XMLString::release(&m_outgoing);
-                for_each(m_encoders.begin(), m_encoders.end(), cleanup_pair<const XMLCh*,MessageEncoder>());
-            }
-#endif
-        }
+        virtual ~SAML2LogoutInitiator() {}
 
         void init(const char* location);    // encapsulates actions that need to run either in the c'tor or setParent
 
@@ -92,7 +90,7 @@ namespace shibsp {
 
         string m_appId;
 #ifndef SHIBSP_LITE
-        LogoutRequest* buildRequest(
+        auto_ptr<LogoutRequest> buildRequest(
             const Application& application, const Session& session, const RoleDescriptor& role, const MessageEncoder* encoder=nullptr
             ) const;
 
@@ -105,9 +103,8 @@ namespace shibsp {
             return e;
         }
 
-        XMLCh* m_outgoing;
-        vector<const XMLCh*> m_bindings;
-        map<const XMLCh*,MessageEncoder*> m_encoders;
+        vector<string> m_bindings;
+        map< string,boost::shared_ptr<MessageEncoder> > m_encoders;
 #endif
         auto_ptr_char m_protocol;
     };
@@ -123,11 +120,7 @@ namespace shibsp {
 };
 
 SAML2LogoutInitiator::SAML2LogoutInitiator(const DOMElement* e, const char* appId)
-    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".LogoutInitiator.SAML2")), m_appId(appId),
-#ifndef SHIBSP_LITE
-        m_outgoing(nullptr),
-#endif
-        m_protocol(samlconstants::SAML20P_NS)
+    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".LogoutInitiator.SAML2")), m_appId(appId), m_protocol(samlconstants::SAML20P_NS)
 {
     // If Location isn't set, defer initialization until the setParent call.
     pair<bool,const char*> loc = getString("Location");
@@ -155,46 +148,33 @@ void SAML2LogoutInitiator::init(const char* location)
 
 #ifndef SHIBSP_LITE
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-        // Handle outgoing binding setup.
-        pair<bool,const XMLCh*> outgoing = getXMLString("outgoingBindings");
+        string dupBindings;
+        pair<bool,const char*> outgoing = getString("outgoingBindings");
         if (outgoing.first) {
-            m_outgoing = XMLString::replicate(outgoing.second);
-            XMLString::trim(m_outgoing);
+            dupBindings = outgoing.second;
         }
         else {
             // No override, so we'll install a default binding precedence.
-            string prec = string(samlconstants::SAML20_BINDING_HTTP_REDIRECT) + ' ' + samlconstants::SAML20_BINDING_HTTP_POST + ' ' +
+            dupBindings = string(samlconstants::SAML20_BINDING_HTTP_REDIRECT) + ' ' + samlconstants::SAML20_BINDING_HTTP_POST + ' ' +
                 samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN + ' ' + samlconstants::SAML20_BINDING_HTTP_ARTIFACT;
-            m_outgoing = XMLString::transcode(prec.c_str());
         }
-
-        int pos;
-        XMLCh* start = m_outgoing;
-        while (start && *start) {
-            pos = XMLString::indexOf(start,chSpace);
-            if (pos != -1)
-                *(start + pos)=chNull;
-            m_bindings.push_back(start);
+        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 {
-                auto_ptr_char b(start);
-                MessageEncoder * encoder =
-                    SAMLConfig::getConfig().MessageEncoderManager.newPlugin(b.get(), pair<const DOMElement*,const XMLCh*>(getElement(), nullptr));
+                boost::shared_ptr<MessageEncoder> encoder(
+                    SAMLConfig::getConfig().MessageEncoderManager.newPlugin(*b, pair<const DOMElement*,const XMLCh*>(getElement(),nullptr))
+                    );
                 if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
-                    m_encoders[start] = encoder;
-                    m_log.debug("supporting outgoing binding (%s)", b.get());
+                    m_encoders[*b] = encoder;
+                    m_log.debug("supporting outgoing binding (%s)", b->c_str());
                 }
                 else {
-                    delete encoder;
-                    m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b.get());
+                    m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b->c_str());
                 }
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("error building MessageEncoder: %s", ex.what());
             }
-            if (pos != -1)
-                start = start + pos + 1;
-            else
-                break;
         }
     }
 #endif
@@ -215,17 +195,17 @@ pair<bool,long> SAML2LogoutInitiator::run(SPRequest& request, bool isHandler) co
     try {
         session = request.getSession(false, true, false);  // don't cache it and ignore all checks
         if (!session)
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
 
         // We only handle SAML 2.0 sessions.
         if (!XMLString::equals(session->getProtocol(), m_protocol.get())) {
             session->unlock();
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error accessing current session: %s", ex.what());
-        return make_pair(false,0L);
+        return make_pair(false, 0L);
     }
 
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
@@ -260,18 +240,18 @@ void SAML2LogoutInitiator::receive(DDF& in, ostream& out)
     }
 
     // Unpack the request.
-    auto_ptr<HTTPRequest> req(getRequest(in));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
 
     // Set up a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     Session* session = nullptr;
     try {
-         session = app->getServiceProvider().getSessionCache()->find(*app, *req.get(), nullptr, nullptr);
+         session = app->getServiceProvider().getSessionCache()->find(*app, *req, nullptr, nullptr);
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error accessing current session: %s", ex.what());
     }
 
@@ -281,12 +261,12 @@ void SAML2LogoutInitiator::receive(DDF& in, ostream& out)
             // Since we're remoted, the result should either be a throw, which we pass on,
             // a false/0 return, which we just return as an empty structure, or a response/redirect,
             // which we capture in the facade and send back.
-            doRequest(*app, *req.get(), *resp.get(), session);
+            doRequest(*app, *req, *resp, session);
         }
         else {
-            m_log.log(getParent() ? Priority::WARN : Priority::ERROR, "bypassing SAML 2.0 logout, no NameID or issuing entityID found in session");
             session->unlock();
-            app->getServiceProvider().getSessionCache()->remove(*app, *req.get(), resp.get());
+            m_log.log(getParent() ? Priority::WARN : Priority::ERROR, "bypassing SAML 2.0 logout, no NameID or issuing entityID found in session");
+            app->getServiceProvider().getSessionCache()->remove(*app, *req, resp.get());
         }
     }
     out << ret;
@@ -299,26 +279,28 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
     const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, Session* session
     ) const
 {
+    Locker sessionLocker(session, false);
 #ifndef SHIBSP_LITE
-    auto_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
+    scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
 #endif
 
     // Do back channel notification.
     vector<string> sessions(1, session->getID());
     if (!notifyBackChannel(application, httpRequest.getRequestURL(), sessions, false)) {
 #ifndef SHIBSP_LITE
-        if (logout_event.get()) {
+        if (logout_event) {
             logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_PARTIAL;
             application.getServiceProvider().getTransactionLog()->write(*logout_event);
         }
 #endif
-        session->unlock();
+        sessionLocker.assign();
+        session = nullptr;
         application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
         return sendLogoutPage(application, httpRequest, httpResponse, "partial");
     }
 
 #ifndef SHIBSP_LITE
-    pair<bool,long> ret = make_pair(false,0L);
+    pair<bool,long> ret = make_pair(false, 0L);
     try {
         // With a session in hand, we can create a LogoutRequest message, if we can find a compatible endpoint.
         MetadataProvider* m = application.getMetadataProvider();
@@ -343,14 +325,14 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
                 );
         }
 
-        const EndpointType* ep=nullptr;
-        const MessageEncoder* encoder=nullptr;
-        vector<const XMLCh*>::const_iterator b;
-        for (b = m_bindings.begin(); b!=m_bindings.end(); ++b) {
-            if (ep=EndpointManager<SingleLogoutService>(role->getSingleLogoutServices()).getByBinding(*b)) {
-                map<const XMLCh*,MessageEncoder*>::const_iterator enc = m_encoders.find(*b);
-                if (enc!=m_encoders.end())
-                    encoder = enc->second;
+        const EndpointType* ep = nullptr;
+        const MessageEncoder* encoder = nullptr;
+        for (vector<string>::const_iterator b = m_bindings.begin(); b != m_bindings.end(); ++b) {
+            auto_ptr_XMLCh wideb(b->c_str());
+            if (ep = EndpointManager<SingleLogoutService>(role->getSingleLogoutServices()).getByBinding(wideb.get())) {
+                map< string,boost::shared_ptr<MessageEncoder> >::const_iterator enc = m_encoders.find(*b);
+                if (enc != m_encoders.end())
+                    encoder = enc->second.get();
                 break;
             }
         }
@@ -360,32 +342,33 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
             shibsp::SOAPClient soaper(policy);
             MetadataCredentialCriteria mcc(*role);
 
-            LogoutResponse* logoutResponse=nullptr;
+            LogoutResponse* logoutResponse = nullptr;
+            scoped_ptr<StatusResponseType> srt;
             auto_ptr_XMLCh binding(samlconstants::SAML20_BINDING_SOAP);
-            const vector<SingleLogoutService*>& endpoints=role->getSingleLogoutServices();
-            for (vector<SingleLogoutService*>::const_iterator epit=endpoints.begin(); !logoutResponse && epit!=endpoints.end(); ++epit) {
+            const vector<SingleLogoutService*>& endpoints = role->getSingleLogoutServices();
+            for (indirect_iterator<vector<SingleLogoutService*>::const_iterator> epit = make_indirect_iterator(endpoints.begin());
+                    !logoutResponse && epit != make_indirect_iterator(endpoints.end()); ++epit) {
                 try {
-                    if (!XMLString::equals((*epit)->getBinding(),binding.get()))
+                    if (!XMLString::equals(epit->getBinding(), binding.get()))
                         continue;
-                    LogoutRequest* msg = buildRequest(application, *session, *role);
+                    auto_ptr<LogoutRequest> msg(buildRequest(application, *session, *role));
 
                     // Log the request.
-                    if (logout_event.get()) {
+                    if (logout_event) {
                         logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_UNKNOWN;
-                        logout_event->m_saml2Request = msg;
+                        logout_event->m_saml2Request = msg.get();
                         application.getServiceProvider().getTransactionLog()->write(*logout_event);
                     }
 
-                    auto_ptr_char dest((*epit)->getLocation());
+                    auto_ptr_char dest(epit->getLocation());
                     SAML2SOAPClient client(soaper, false);
-                    client.sendSAML(msg, application.getId(), mcc, dest.get());
-                    StatusResponseType* srt = client.receiveSAML();
-                    if (!(logoutResponse = dynamic_cast<LogoutResponse*>(srt))) {
-                        delete srt;
+                    client.sendSAML(msg.release(), application.getId(), mcc, dest.get());
+                    srt.reset(client.receiveSAML());
+                    if (!(logoutResponse = dynamic_cast<LogoutResponse*>(srt.get()))) {
                         break;
                     }
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     m_log.error("error sending LogoutRequest message: %s", ex.what());
                     soaper.reset();
                 }
@@ -399,7 +382,7 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
                     m_log.warn("IdP didn't respond to logout request");
 
                 // Log the end result.
-                if (logout_event.get()) {
+                if (logout_event) {
                     logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_PARTIAL;
                     application.getServiceProvider().getTransactionLog()->write(*logout_event);
                 }
@@ -416,13 +399,12 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
                 }
 
                 // Log the end result.
-                if (logout_event.get()) {
+                if (logout_event) {
                     logout_event->m_logoutType = partial ? LogoutEvent::LOGOUT_EVENT_PARTIAL : LogoutEvent::LOGOUT_EVENT_GLOBAL;
                     logout_event->m_saml2Response = logoutResponse;
                     application.getServiceProvider().getTransactionLog()->write(*logout_event);
                 }
 
-                delete logoutResponse;
                 if (partial)
                     ret = sendLogoutPage(application, httpRequest, httpResponse, "partial");
                 else {
@@ -437,7 +419,7 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
             }
 
             if (session) {
-                session->unlock();
+                sessionLocker.assign();
                 session = nullptr;
                 application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
             }
@@ -458,7 +440,7 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
         msg->setDestination(ep->getLocation());
 
         // Log the request.
-        if (logout_event.get()) {
+        if (logout_event) {
             logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_UNKNOWN;
             logout_event->m_saml2Request = msg.get();
             application.getServiceProvider().getTransactionLog()->write(*logout_event);
@@ -470,7 +452,7 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
         msg.release();  // freed by encoder
 
         if (session) {
-            session->unlock();
+            sessionLocker.assign();
             session = nullptr;
             application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
         }
@@ -479,23 +461,19 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
         // Less noise for IdPs that don't support logout (i.e. most)
         m_log.info("unable to issue SAML 2.0 logout request: %s", mex.what());
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error issuing SAML 2.0 logout request: %s", ex.what());
     }
 
-    if (session)
-        session->unlock();
     return ret;
 #else
-    if (session)
-        session->unlock();
     throw ConfigurationException("Cannot perform logout using lite version of shibsp library.");
 #endif
 }
 
 #ifndef SHIBSP_LITE
 
-LogoutRequest* SAML2LogoutInitiator::buildRequest(
+auto_ptr<LogoutRequest> SAML2LogoutInitiator::buildRequest(
     const Application& application, const Session& session, const RoleDescriptor& role, const MessageEncoder* encoder
     ) const
 {
@@ -525,7 +503,8 @@ LogoutRequest* SAML2LogoutInitiator::buildRequest(
             encoder ? encoder->isCompact() : false,
             relyingParty->getXMLString("encryptionAlg").second
             );
-        msg->setEncryptedID(encrypted.release());
+        msg->setEncryptedID(encrypted.get());
+        encrypted.release();
     }
     else {
         msg->setNameID(nameid->cloneNameID());
@@ -534,7 +513,7 @@ LogoutRequest* SAML2LogoutInitiator::buildRequest(
     msg->setID(SAMLConfig::getConfig().generateIdentifier());
     msg->setIssueInstant(time(nullptr));
 
-    return msg.release();
+    return msg;
 }
 
 #endif
index a724a51..f2e91b2 100644 (file)
@@ -38,6 +38,8 @@
 # include "security/SecurityPolicy.h"
 # include "security/SecurityPolicyProvider.h"
 # include <fstream>
+# include <boost/algorithm/string.hpp>
+# include <boost/iterator/indirect_iterator.hpp>
 # include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/saml2/core/Protocols.h>
@@ -53,8 +55,11 @@ using namespace opensaml;
 # include "lite/SAMLConstants.h"
 #endif
 
+#include <boost/scoped_ptr.hpp>
+
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -68,15 +73,7 @@ namespace shibsp {
     {
     public:
         SAML2NameIDMgmt(const DOMElement* e, const char* appId);
-        virtual ~SAML2NameIDMgmt() {
-#ifndef SHIBSP_LITE
-            if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-                delete m_decoder;
-                XMLString::release(&m_outgoing);
-                for_each(m_encoders.begin(), m_encoders.end(), cleanup_pair<const XMLCh*,MessageEncoder>());
-            }
-#endif
-        }
+        virtual ~SAML2NameIDMgmt() {}
 
         void receive(DDF& in, ostream& out);
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
@@ -122,11 +119,9 @@ namespace shibsp {
             bool front
             ) const;
 
-        xmltooling::QName m_role;
-        MessageDecoder* m_decoder;
-        XMLCh* m_outgoing;
-        vector<const XMLCh*> m_bindings;
-        map<const XMLCh*,MessageEncoder*> m_encoders;
+        scoped_ptr<MessageDecoder> m_decoder;
+        vector<string> m_bindings;
+        map< string,boost::shared_ptr<MessageEncoder> > m_encoders;
 #endif
     };
 
@@ -142,69 +137,57 @@ namespace shibsp {
 
 SAML2NameIDMgmt::SAML2NameIDMgmt(const DOMElement* e, const char* appId)
     : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".NameIDMgmt.SAML2"))
-#ifndef SHIBSP_LITE
-        ,m_role(samlconstants::SAML20MD_NS, IDPSSODescriptor::LOCAL_NAME), m_decoder(nullptr), m_outgoing(nullptr)
-#endif
 {
 #ifndef SHIBSP_LITE
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
         SAMLConfig& conf = SAMLConfig::getConfig();
 
         // Handle incoming binding.
-        m_decoder = conf.MessageDecoderManager.newPlugin(
-            getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
+        m_decoder.reset(
+            conf.MessageDecoderManager.newPlugin(
+                getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
+                )
             );
         m_decoder->setArtifactResolver(SPConfig::getConfig().getArtifactResolver());
 
         if (m_decoder->isUserAgentPresent()) {
             // Handle front-channel binding setup.
-            pair<bool,const XMLCh*> outgoing = getXMLString("outgoingBindings", m_configNS.get());
+            string dupBindings;
+            pair<bool,const char*> outgoing = getString("outgoingBindings", m_configNS.get());
             if (outgoing.first) {
-                m_outgoing = XMLString::replicate(outgoing.second);
-                XMLString::trim(m_outgoing);
+                dupBindings = outgoing.second;
             }
             else {
                 // No override, so we'll install a default binding precedence.
-                string prec = string(samlconstants::SAML20_BINDING_HTTP_REDIRECT) + ' ' + samlconstants::SAML20_BINDING_HTTP_POST + ' ' +
+                dupBindings = string(samlconstants::SAML20_BINDING_HTTP_REDIRECT) + ' ' + samlconstants::SAML20_BINDING_HTTP_POST + ' ' +
                     samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN + ' ' + samlconstants::SAML20_BINDING_HTTP_ARTIFACT;
-                m_outgoing = XMLString::transcode(prec.c_str());
             }
 
-            int pos;
-            XMLCh* start = m_outgoing;
-            while (start && *start) {
-                pos = XMLString::indexOf(start,chSpace);
-                if (pos != -1)
-                    *(start + pos)=chNull;
-                m_bindings.push_back(start);
+            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 {
-                    auto_ptr_char b(start);
-                    MessageEncoder * encoder = conf.MessageEncoderManager.newPlugin(
-                        b.get(), pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
+                    boost::shared_ptr<MessageEncoder> encoder(
+                        conf.MessageEncoderManager.newPlugin(*b, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS))
                         );
                     if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
-                        m_encoders[start] = encoder;
-                        m_log.debug("supporting outgoing binding (%s)", b.get());
+                        m_encoders[*b] = encoder;
+                        m_log.debug("supporting outgoing binding (%s)", b->c_str());
                     }
                     else {
-                        delete encoder;
-                        m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b.get());
+                        m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b->c_str());
                     }
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     m_log.error("error building MessageEncoder: %s", ex.what());
                 }
-                if (pos != -1)
-                    start = start + pos + 1;
-                else
-                    break;
             }
         }
         else {
-            MessageEncoder* encoder = conf.MessageEncoderManager.newPlugin(
-                getString("Binding").second, pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
+            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))
                 );
-            m_encoders.insert(pair<const XMLCh*,MessageEncoder*>(nullptr, encoder));
+            m_encoders[b.second] = encoder;
         }
     }
 #endif
@@ -235,8 +218,8 @@ pair<bool,long> SAML2NameIDMgmt::run(SPRequest& request, bool isHandler) const
 void SAML2NameIDMgmt::receive(DDF& in, ostream& out)
 {
     // Find application.
-    const char* aid=in["application_id"].string();
-    const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+    const char* aid = in["application_id"].string();
+    const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
     if (!app) {
         // Something's horribly wrong.
         m_log.error("couldn't find application (%s) for NameID mgmt", aid ? aid : "(missing)");
@@ -244,23 +227,21 @@ void SAML2NameIDMgmt::receive(DDF& in, ostream& out)
     }
 
     // Unpack the request.
-    auto_ptr<HTTPRequest> req(getRequest(in));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
 
     // Wrap a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     // Since we're remoted, the result should either be a throw, which we pass on,
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    doRequest(*app, *req.get(), *resp.get());
+    doRequest(*app, *req, *resp);
     out << ret;
 }
 
-pair<bool,long> SAML2NameIDMgmt::doRequest(
-    const Application& application, const HTTPRequest& request, HTTPResponse& response
-    ) const
+pair<bool,long> SAML2NameIDMgmt::doRequest(const Application& application, const HTTPRequest& request, HTTPResponse& response) const
 {
 #ifndef SHIBSP_LITE
     SessionCache* cache = application.getServiceProvider().getSessionCache();
@@ -274,13 +255,13 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
     Locker metadataLocker(application.getMetadataProvider());
 
     // Create the policy.
-    auto_ptr<SecurityPolicy> policy(
-        application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, &m_role, policyId.second)
+    scoped_ptr<SecurityPolicy> policy(
+        application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(application, &IDPSSODescriptor::ELEMENT_QNAME, policyId.second)
         );
 
     // Decode the message.
     string relayState;
-    auto_ptr<XMLObject> msg(m_decoder->decode(relayState, request, *policy.get()));
+    scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, request, *policy));
     const ManageNameIDRequest* mgmtRequest = dynamic_cast<ManageNameIDRequest*>(msg.get());
     if (mgmtRequest) {
         if (!policy->isAuthenticated())
@@ -305,7 +286,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
 
         EntityDescriptor* entity = policy->getIssuerMetadata() ? dynamic_cast<EntityDescriptor*>(policy->getIssuerMetadata()->getParent()) : nullptr;
 
-        bool ownedName = false;
+        scoped_ptr<XMLObject> decryptedID;
         NameID* nameid = mgmtRequest->getNameID();
         if (!nameid) {
             // Check for EncryptedID.
@@ -316,20 +297,14 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
                     m_log.warn("found encrypted NameID, but no decryption credential was available");
                 else {
                     Locker credlocker(cr);
-                    auto_ptr<MetadataCredentialCriteria> mcc(
+                    scoped_ptr<MetadataCredentialCriteria> mcc(
                         policy->getIssuerMetadata() ? new MetadataCredentialCriteria(*policy->getIssuerMetadata()) : nullptr
                         );
                     try {
-                        auto_ptr<XMLObject> decryptedID(
-                            encname->decrypt(*cr,application.getRelyingParty(entity)->getXMLString("entityID").second,mcc.get())
-                            );
+                        decryptedID.reset(encname->decrypt(*cr, application.getRelyingParty(entity)->getXMLString("entityID").second, mcc.get()));
                         nameid = dynamic_cast<NameID*>(decryptedID.get());
-                        if (nameid) {
-                            ownedName = true;
-                            decryptedID.release();
-                        }
                     }
-                    catch (exception& ex) {
+                    catch (std::exception& ex) {
                         m_log.error(ex.what());
                     }
                 }
@@ -349,8 +324,6 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
                 );
         }
 
-        auto_ptr<NameID> namewrapper(ownedName ? nameid : nullptr);
-
         // For a front-channel request, we have to match the information in the request
         // against the current session.
         if (!session_id.empty()) {
@@ -369,7 +342,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
         }
 
         // Determine what's happening...
-        bool ownedNewID = false;
+        scoped_ptr<XMLObject> newDecryptedID;
         NewID* newid = nullptr;
         if (!mgmtRequest->getTerminate()) {
             // Better be a NewID in there.
@@ -383,20 +356,14 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
                         m_log.warn("found encrypted NewID, but no decryption credential was available");
                     else {
                         Locker credlocker(cr);
-                        auto_ptr<MetadataCredentialCriteria> mcc(
+                        scoped_ptr<MetadataCredentialCriteria> mcc(
                             policy->getIssuerMetadata() ? new MetadataCredentialCriteria(*policy->getIssuerMetadata()) : nullptr
                             );
                         try {
-                            auto_ptr<XMLObject> decryptedID(
-                                encnewid->decrypt(*cr,application.getRelyingParty(entity)->getXMLString("entityID").second,mcc.get())
-                                );
-                            newid = dynamic_cast<NewID*>(decryptedID.get());
-                            if (newid) {
-                                ownedNewID = true;
-                                decryptedID.release();
-                            }
+                            newDecryptedID.reset(encnewid->decrypt(*cr, application.getRelyingParty(entity)->getXMLString("entityID").second, mcc.get()));
+                            newid = dynamic_cast<NewID*>(newDecryptedID.get());
                         }
-                        catch (exception& ex) {
+                        catch (std::exception& ex) {
                             m_log.error(ex.what());
                         }
                     }
@@ -418,8 +385,6 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
             }
         }
 
-        auto_ptr<NewID> newwrapper(ownedNewID ? newid : nullptr);
-
         // TODO: maybe support in-place modification of sessions?
         /*
         vector<string> sessions;
@@ -448,7 +413,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
         */
 
         // Do back-channel app notifications.
-        // Not supporting front-channel due to privacy fears.
+        // Not supporting front-channel due to privacy concerns.
         bool worked = notifyBackChannel(application, request.getRequestURL(), *nameid, newid);
 
         return sendResponse(
@@ -485,7 +450,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
     if (policy->getIssuerMetadata())
         annotateException(&ex, policy->getIssuerMetadata()); // throws it
     ex.raise();
-    return make_pair(false,0L);  // never happen, satisfies compiler
+    return make_pair(false, 0L);  // never happen, satisfies compiler
 #else
     throw ConfigurationException("Cannot process NameID mgmt message using lite version of shibsp library.");
 #endif
@@ -510,11 +475,12 @@ pair<bool,long> SAML2NameIDMgmt::sendResponse(
     const MessageEncoder* encoder = nullptr;
     if (front) {
         const IDPSSODescriptor* idp = dynamic_cast<const IDPSSODescriptor*>(role);
-        for (vector<const XMLCh*>::const_iterator b = m_bindings.begin(); idp && b!=m_bindings.end(); ++b) {
-            if ((ep=EndpointManager<ManageNameIDService>(idp->getManageNameIDServices()).getByBinding(*b))) {
-                map<const XMLCh*,MessageEncoder*>::const_iterator enc = m_encoders.find(*b);
-                if (enc!=m_encoders.end())
-                    encoder = enc->second;
+        for (vector<string>::const_iterator b = m_bindings.begin(); idp && b != m_bindings.end(); ++b) {
+            auto_ptr_XMLCh wideb(b->c_str());
+            if ((ep = EndpointManager<ManageNameIDService>(idp->getManageNameIDServices()).getByBinding(wideb.get()))) {
+                map< string,boost::shared_ptr<MessageEncoder> >::const_iterator enc = m_encoders.find(*b);
+                if (enc != m_encoders.end())
+                    encoder = enc->second.get();
                 break;
             }
         }
@@ -526,7 +492,7 @@ pair<bool,long> SAML2NameIDMgmt::sendResponse(
         }
     }
     else {
-        encoder = m_encoders.begin()->second;
+        encoder = m_encoders.begin()->second.get();
     }
 
     // Prepare response.
@@ -541,13 +507,13 @@ pair<bool,long> SAML2NameIDMgmt::sendResponse(
     Issuer* issuer = IssuerBuilder::buildIssuer();
     nim->setIssuer(issuer);
     issuer->setName(application.getRelyingParty(dynamic_cast<EntityDescriptor*>(role->getParent()))->getXMLString("entityID").second);
-    fillStatus(*nim.get(), code, subcode, msg);
+    fillStatus(*nim, code, subcode, msg);
 
     auto_ptr_char dest(nim->getDestination());
 
     long ret = sendMessage(*encoder, nim.get(), relayState, dest.get(), role, application, httpResponse);
     nim.release();  // freed by encoder
-    return make_pair(true,ret);
+    return make_pair(true, ret);
 }
 
 #include "util/SPConstants.h"
@@ -570,7 +536,6 @@ namespace {
             HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(&transport);
             if (http) {
                 http->useChunkedEncoding(false);
-                http->setRequestHeader("User-Agent", PACKAGE_NAME);
                 http->setRequestHeader(PACKAGE_NAME, PACKAGE_VERSION);
             }
         }
@@ -586,7 +551,7 @@ bool SAML2NameIDMgmt::notifyBackChannel(
     if (endpoint.empty())
         return true;
 
-    auto_ptr<Envelope> env(EnvelopeBuilder::buildEnvelope());
+    scoped_ptr<Envelope> env(EnvelopeBuilder::buildEnvelope());
     Body* body = BodyBuilder::buildBody();
     env->setBody(body);
     ElementProxy* msg = new AnyElementImpl(shibspconstants::SHIB2SPNOTIFY_NS, NameIDNotification);
@@ -601,10 +566,10 @@ bool SAML2NameIDMgmt::notifyBackChannel(
     SOAPNotifier soaper;
     while (!endpoint.empty()) {
         try {
-            soaper.send(*env.get(), SOAPTransport::Address(application.getId(), application.getId(), endpoint.c_str()));
+            soaper.send(*env, SOAPTransport::Address(application.getId(), application.getId(), endpoint.c_str()));
             delete soaper.receive();
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error("error notifying application of logout event: %s", ex.what());
             result = false;
         }
index 7dc1b8c..a3377e8 100644 (file)
@@ -35,6 +35,9 @@
 
 #ifndef SHIBSP_LITE
 # include "metadata/MetadataProviderCriteria.h"
+# include <boost/bind.hpp>
+# include <boost/algorithm/string.hpp>
+# include <boost/iterator/indirect_iterator.hpp>
 # include <saml/SAMLConfig.h>
 # include <saml/saml2/core/Protocols.h>
 # include <saml/saml2/metadata/EndpointManager.h>
@@ -49,9 +52,12 @@ using namespace opensaml::saml2md;
 # include <xercesc/util/XMLUniDefs.hpp>
 #endif
 
+#include <boost/scoped_ptr.hpp>
+
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -65,16 +71,7 @@ namespace shibsp {
     {
     public:
         SAML2SessionInitiator(const DOMElement* e, const char* appId);
-        virtual ~SAML2SessionInitiator() {
-#ifndef SHIBSP_LITE
-            if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-                XMLString::release(&m_outgoing);
-                for_each(m_encoders.begin(), m_encoders.end(), cleanup_pair<const XMLCh*,MessageEncoder>());
-                delete m_requestTemplate;
-                delete m_ecp;
-            }
-#endif
-        }
+        virtual ~SAML2SessionInitiator() {}
 
         void init(const char* location);    // encapsulates actions that need to run either in the c'tor or setParent
 
@@ -110,11 +107,10 @@ namespace shibsp {
         auto_ptr_char m_paosNS,m_ecpNS;
         auto_ptr_XMLCh m_paosBinding;
 #ifndef SHIBSP_LITE
-        XMLCh* m_outgoing;
-        vector<const XMLCh*> m_bindings;
-        map<const XMLCh*,MessageEncoder*> m_encoders;
-        MessageEncoder* m_ecp;
-        AuthnRequest* m_requestTemplate;
+        vector<string> m_bindings;
+        map< string,boost::shared_ptr<MessageEncoder> > m_encoders;
+        scoped_ptr<MessageEncoder> m_ecp;
+        scoped_ptr<AuthnRequest> m_requestTemplate;
 #else
         bool m_ecp;
 #endif
@@ -133,11 +129,9 @@ namespace shibsp {
 
 SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* appId)
     : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.SAML2"), nullptr, &m_remapper), m_appId(appId),
-        m_paosNS(samlconstants::PAOS_NS), m_ecpNS(samlconstants::SAML20ECP_NS), m_paosBinding(samlconstants::SAML20_BINDING_PAOS),
-#ifndef SHIBSP_LITE
-        m_outgoing(nullptr), m_ecp(nullptr), m_requestTemplate(nullptr)
-#else
-        m_ecp(false)
+        m_paosNS(samlconstants::PAOS_NS), m_ecpNS(samlconstants::SAML20ECP_NS), m_paosBinding(samlconstants::SAML20_BINDING_PAOS)
+#ifdef SHIBSP_LITE
+        ,m_ecp(false)
 #endif
 {
 #ifndef SHIBSP_LITE
@@ -145,7 +139,7 @@ SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* ap
         // Check for a template AuthnRequest to build from.
         DOMElement* child = XMLHelper::getFirstChildElement(e, samlconstants::SAML20P_NS, AuthnRequest::LOCAL_NAME);
         if (child)
-            m_requestTemplate = dynamic_cast<AuthnRequest*>(AuthnRequestBuilder::buildOneFromElement(child));
+            m_requestTemplate.reset(dynamic_cast<AuthnRequest*>(AuthnRequestBuilder::buildOneFromElement(child)));
     }
 #endif
 
@@ -179,63 +173,49 @@ void SAML2SessionInitiator::init(const char* location)
 #ifdef SHIBSP_LITE
     m_ecp = flag.first && flag.second;
 #else
-    m_outgoing=nullptr;
-    m_ecp = nullptr;
 
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
         // If directed, build an ECP encoder.
         if (flag.first && flag.second) {
             try {
-                m_ecp = 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, pair<const DOMElement*,const XMLCh*>(getElement(), nullptr)
+                        )
                     );
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("error building PAOS/ECP MessageEncoder: %s", ex.what());
             }
         }
 
-        // Handle outgoing binding setup.
-        pair<bool,const XMLCh*> outgoing = getXMLString("outgoingBindings");
+        string dupBindings;
+        pair<bool,const char*> outgoing = getString("outgoingBindings");
         if (outgoing.first) {
-            m_outgoing = XMLString::replicate(outgoing.second);
-            XMLString::trim(m_outgoing);
+            dupBindings = outgoing.second;
         }
         else {
             // No override, so we'll install a default binding precedence.
-            string prec = string(samlconstants::SAML20_BINDING_HTTP_REDIRECT) + ' ' + samlconstants::SAML20_BINDING_HTTP_POST + ' ' +
+            dupBindings = string(samlconstants::SAML20_BINDING_HTTP_REDIRECT) + ' ' + samlconstants::SAML20_BINDING_HTTP_POST + ' ' +
                 samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN + ' ' + samlconstants::SAML20_BINDING_HTTP_ARTIFACT;
-            m_outgoing = XMLString::transcode(prec.c_str());
         }
-
-        int pos;
-        XMLCh* start = m_outgoing;
-        while (start && *start) {
-            pos = XMLString::indexOf(start,chSpace);
-            if (pos != -1)
-                *(start + pos)=chNull;
-            m_bindings.push_back(start);
+        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 {
-                auto_ptr_char b(start);
-                MessageEncoder * encoder = SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
-                    b.get(),pair<const DOMElement*,const XMLCh*>(getElement(), nullptr)
+                boost::shared_ptr<MessageEncoder> encoder(
+                    SAMLConfig::getConfig().MessageEncoderManager.newPlugin(*b, pair<const DOMElement*,const XMLCh*>(getElement(),nullptr))
                     );
                 if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
-                    m_encoders[start] = encoder;
-                    m_log.debug("supporting outgoing binding (%s)", b.get());
+                    m_encoders[*b] = encoder;
+                    m_log.debug("supporting outgoing binding (%s)", b->c_str());
                 }
                 else {
-                    delete encoder;
-                    m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b.get());
+                    m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b->c_str());
                 }
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("error building MessageEncoder: %s", ex.what());
             }
-            if (pos != -1)
-                start = start + pos + 1;
-            else
-                break;
         }
     }
 #endif
@@ -253,14 +233,14 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
 
     // We have to know the IdP to function unless this is ECP.
     if ((!ECP && entityID.empty()) || !checkCompatibility(request, isHandler))
-        return make_pair(false,0L);
+        return make_pair(false, 0L);
 
     string target;
     pair<bool,const char*> prop;
-    const Handler* ACS=nullptr;
+    const Handler* ACS = nullptr;
     pair<bool,const char*> acClass, acComp, nidFormat, spQual;
     bool isPassive=false,forceAuthn=false;
-    const Application& app=request.getApplication();
+    const Application& app = request.getApplication();
 
     // ECP means the ACS will be by value no matter what.
     pair<bool,bool> acsByIndex = ECP ? make_pair(true,false) : getBool("acsByIndex");
@@ -370,7 +350,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", 5)) {
+            if (!strncmp(ACSloc.c_str(), "https://", 8)) {
                ix = ACS->getXMLString("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS);
                if (!ix.first)
                        ix = ACS->getXMLString("index");
@@ -443,7 +423,7 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
     if (acsByIndex.first && acsByIndex.second) {
         // Determine index to use.
         pair<bool,const char*> ix = pair<bool,const char*>(false,nullptr);
-        if (!strncmp(ACSloc.c_str(), "https", 5)) {
+        if (!strncmp(ACSloc.c_str(), "https://", 8)) {
                ix = ACS->getString("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS);
                if (!ix.first)
                        ix = ACS->getString("index");
@@ -497,8 +477,8 @@ pair<bool,long> SAML2SessionInitiator::unwrap(SPRequest& request, DDF& out) cons
 void SAML2SessionInitiator::receive(DDF& in, ostream& out)
 {
     // Find application.
-    const char* aid=in["application_id"].string();
-    const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+    const char* aid = in["application_id"].string();
+    const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
     if (!app) {
         // Something's horribly wrong.
         m_log.error("couldn't find application (%s) to generate AuthnRequest", aid ? aid : "(missing)");
@@ -509,7 +489,7 @@ void SAML2SessionInitiator::receive(DDF& in, ostream& out)
     DDFJanitor jout(ret);
 
     // Wrap the outgoing object with a Response facade.
-    auto_ptr<HTTPResponse> http(getResponse(ret));
+    scoped_ptr<HTTPResponse> http(getResponse(ret));
 
     auto_ptr_XMLCh index(in["acsIndex"].string());
     auto_ptr_XMLCh bind(in["acsBinding"].string());
@@ -521,7 +501,7 @@ void SAML2SessionInitiator::receive(DDF& in, ostream& out)
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
     doRequest(
-        *app, nullptr, *http.get(), in["entity_id"].string(),
+        *app, nullptr, *http, in["entity_id"].string(),
         index.get(),
         (in["artifact"].integer() != 0),
         in["acsLocation"].string(), bind.get(),
@@ -536,18 +516,6 @@ void SAML2SessionInitiator::receive(DDF& in, ostream& out)
     out << ret;
 }
 
-#ifndef SHIBSP_LITE
-namespace {
-    class _sameIdP : public binary_function<const IDPEntry*, const XMLCh*, bool>
-    {
-    public:
-        bool operator()(const IDPEntry* entry, const XMLCh* entityID) const {
-            return entry ? XMLString::equals(entry->getProviderID(), entityID) : false;
-        }
-    };
-};
-#endif
-
 pair<bool,long> SAML2SessionInitiator::doRequest(
     const Application& app,
     const HTTPRequest* httpRequest,
@@ -575,20 +543,20 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
     const MessageEncoder* encoder = nullptr;
 
     // We won't need this for ECP, but safety dictates we get the lock here.
-    MetadataProvider* m=app.getMetadataProvider();
+    MetadataProvider* m = app.getMetadataProvider();
     Locker locker(m);
 
     if (ECP) {
-        encoder = m_ecp;
+        encoder = m_ecp.get();
         if (!encoder) {
             m_log.error("MessageEncoder for PAOS binding not available");
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
         }
     }
     else {
         // Use metadata to locate the IdP's SSO service.
         MetadataProviderCriteria mc(app, entityID, &IDPSSODescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS);
-        entity=m->getEntityDescriptor(mc);
+        entity = m->getEntityDescriptor(mc);
         if (!entity.first) {
             m_log.warn("unable to locate metadata for provider (%s)", entityID);
             throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID));
@@ -596,31 +564,31 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
         else if (!entity.second) {
             m_log.log(getParent() ? Priority::INFO : Priority::WARN, "unable to locate SAML 2.0 identity provider role for provider (%s)", entityID);
             if (getParent())
-                return make_pair(false,0L);
+                return make_pair(false, 0L);
             throw MetadataException("Unable to locate SAML 2.0 identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
         }
         else if (artifactInbound && !SPConfig::getConfig().getArtifactResolver()->isSupported(dynamic_cast<const SSODescriptorType&>(*entity.second))) {
             m_log.warn("artifact binding selected for response, but identity provider lacks support");
             if (getParent())
-                return make_pair(false,0L);
+                return make_pair(false, 0L);
             throw MetadataException("Identity provider ($entityID) lacks SAML 2.0 artifact support.", namedparams(1, "entityID", entityID));
         }
 
         // Loop over the supportable outgoing bindings.
         role = dynamic_cast<const IDPSSODescriptor*>(entity.second);
-        vector<const XMLCh*>::const_iterator b;
-        for (b = m_bindings.begin(); b!=m_bindings.end(); ++b) {
-            if (ep=EndpointManager<SingleSignOnService>(role->getSingleSignOnServices()).getByBinding(*b)) {
-                map<const XMLCh*,MessageEncoder*>::const_iterator enc = m_encoders.find(*b);
-                if (enc!=m_encoders.end())
-                    encoder = enc->second;
+        for (vector<string>::const_iterator b = m_bindings.begin(); b != m_bindings.end(); ++b) {
+            auto_ptr_XMLCh wideb(b->c_str());
+            if (ep=EndpointManager<SingleSignOnService>(role->getSingleSignOnServices()).getByBinding(wideb.get())) {
+                map< string,boost::shared_ptr<MessageEncoder> >::const_iterator enc = m_encoders.find(*b);
+                if (enc != m_encoders.end())
+                    encoder = enc->second.get();
                 break;
             }
         }
         if (!ep || !encoder) {
             m_log.warn("unable to locate compatible SSO service for provider (%s)", entityID);
             if (getParent())
-                return make_pair(false,0L);
+                return make_pair(false, 0L);
             throw MetadataException("Unable to locate compatible SSO service for provider ($entityID)", namedparams(1, "entityID", entityID));
         }
     }
@@ -674,23 +642,16 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
         }
         if (authnContextClassRef) {
             reqContext->getAuthnContextDeclRefs().clear();
-            XMLCh* wideclass = XMLString::transcode(authnContextClassRef);
-            XMLString::trim(wideclass);
-            int pos;
-            XMLCh* start = wideclass;
-            while (start && *start) {
-                pos = XMLString::indexOf(start, chSpace);
-                if (pos != -1)
-                    *(start + pos) = chNull;
-                AuthnContextClassRef* cref = AuthnContextClassRefBuilder::buildAuthnContextClassRef();
-                cref->setReference(start);
-                reqContext->getAuthnContextClassRefs().push_back(cref);
-                if (pos != -1)
-                    start = start + pos + 1;
-                else
-                    break;
+            string dup(authnContextClassRef);
+            vector<string> contexts;
+            split(contexts, dup, is_space(), algorithm::token_compress_on);
+            for (vector<string>::const_iterator ac = contexts.begin(); ac != contexts.end(); ++ac) {
+                auto_ptr_XMLCh wideac(ac->c_str());
+                auto_ptr<AuthnContextClassRef> cref(AuthnContextClassRefBuilder::buildAuthnContextClassRef());
+                cref->setReference(wideac.get());
+                reqContext->getAuthnContextClassRefs().push_back(cref.get());
+                cref.release();
             }
-            XMLString::release(&wideclass);
         }
 
         if (reqContext->getAuthnContextClassRefs().empty() && reqContext->getAuthnContextDeclRefs().empty()) {
@@ -733,7 +694,8 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
             scoping->setIDPList(idplist);
         }
         VectorOf(IDPEntry) entries = idplist->getIDPEntrys();
-        if (find_if(entries, bind2nd(_sameIdP(), wideid.get())) == nullptr) {
+        static bool (*wideequals)(const XMLCh*,const XMLCh*) = &XMLString::equals;
+        if (find_if(entries, boost::bind(wideequals, boost::bind(&IDPEntry::getProviderID, _1), wideid.get())) == nullptr) {
             IDPEntry* entry = IDPEntryBuilder::buildIDPEntry();
             entry->setProviderID(wideid.get());
             entries.push_back(entry);
@@ -743,8 +705,8 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
     req->setID(SAMLConfig::getConfig().generateIdentifier());
     req->setIssueInstant(time(nullptr));
 
-    auto_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
-    if (ar_event.get()) {
+    scoped_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
+    if (ar_event) {
         auto_ptr_char b(ep ? ep->getBinding() : nullptr);
         ar_event->m_binding = b.get() ? b.get() : samlconstants::SAML20_BINDING_SOAP;
         auto_ptr_char prot(getProtocolFamily());
@@ -765,8 +727,8 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
         *encoder, req.get(), relayState.c_str(), dest.get(), role, app, httpResponse, role ? role->WantAuthnRequestsSigned() : false
         );
     req.release();  // freed by encoder
-    return make_pair(true,ret);
+    return make_pair(true, ret);
 #else
-    return make_pair(false,0L);
+    return make_pair(false, 0L);
 #endif
 }
index 992682e..ed5b293 100644 (file)
 #include "handler/AbstractHandler.h"
 #include "handler/SessionInitiator.h"
 
+#include <boost/algorithm/string.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/URLEncoder.h>
 
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 #ifndef SHIBSP_LITE
@@ -132,15 +134,8 @@ SAMLDSSessionInitiator::SAMLDSSessionInitiator(const DOMElement* e, const char*
 
     pair<bool,const char*> options = getString("preservedOptions");
     if (options.first) {
-        int j = 0;
         string opt = options.second;
-        for (unsigned int i = 0;  i < opt.length();  i++) {
-            if (opt.at(i) == ' ') {
-                m_preservedOptions.push_back(opt.substr(j, i-j));
-                j = i+1;
-            }
-        }
-        m_preservedOptions.push_back(opt.substr(j, opt.length()-j));
+        split(m_preservedOptions, opt, is_space(), algorithm::token_compress_on);
     }
     else {
         m_preservedOptions.push_back("isPassive");
@@ -164,8 +159,8 @@ pair<bool,long> SAMLDSSessionInitiator::run(SPRequest& request, string& entityID
 
     string target;
     pair<bool,const char*> prop;
-    bool isPassive=false;
-    const Application& app=request.getApplication();
+    bool isPassive = false;
+    const Application& app = request.getApplication();
     pair<bool,const char*> discoveryURL = pair<bool,const char*>(true, m_url);
 
     if (isHandler) {
index ec0f57b..721fcb7 100644 (file)
 #include "util/IPRange.h"
 
 #include <ctime>
+#include <boost/bind.hpp>
+#include <boost/algorithm/string.hpp>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -71,6 +74,15 @@ namespace shibsp {
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
     private:
+        void parseACL(const string& acl) {
+            try {
+                m_acl.push_back(IPRange::parseCIDRBlock(acl.c_str()));
+            }
+            catch (std::exception& ex) {
+                m_log.error("invalid CIDR block (%s): %s", acl.c_str(), ex.what());
+            }
+        }
+
         bool m_values;
         vector<IPRange> m_acl;
     };
@@ -92,25 +104,9 @@ SessionHandler::SessionHandler(const DOMElement* e, const char* appId)
     pair<bool,const char*> acl = getString("acl");
     if (acl.first) {
         string aclbuf=acl.second;
-        int j = 0;
-        for (unsigned int i=0;  i < aclbuf.length();  ++i) {
-            if (aclbuf.at(i)==' ') {
-                try {
-                    m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, i-j).c_str()));
-                }
-                catch (exception& ex) {
-                    m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, i-j).c_str(), ex.what());
-                }
-                j = i + 1;
-            }
-        }
-        try {
-            m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, aclbuf.length()-j).c_str()));
-        }
-        catch (exception& ex) {
-            m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, aclbuf.length()-j).c_str(), ex.what());
-        }
-
+        vector<string> aclarray;
+        split(aclarray, aclbuf, is_space(), algorithm::token_compress_on);
+        for_each(aclarray.begin(), aclarray.end(), boost::bind(&SessionHandler::parseACL, this, _1));
         if (m_acl.empty()) {
             m_log.warn("invalid CIDR range(s) in Session handler acl property, allowing 127.0.0.1 as a fall back");
             m_acl.push_back(IPRange::parseCIDRBlock("127.0.0.1"));
@@ -125,11 +121,8 @@ SessionHandler::SessionHandler(const DOMElement* e, const char* appId)
 pair<bool,long> SessionHandler::run(SPRequest& request, bool isHandler) const
 {
     if (!m_acl.empty()) {
-        bool found = false;
-        for (vector<IPRange>::const_iterator acl = m_acl.begin(); !found && acl != m_acl.end(); ++acl) {
-            found = acl->contains(request.getRemoteAddr().c_str());
-        }
-        if (!found) {
+        static bool (IPRange::* contains)(const char*) const = &IPRange::contains;
+        if (find_if(m_acl.begin(), m_acl.end(), boost::bind(contains, _1, request.getRemoteAddr().c_str())) == m_acl.end()) {
             m_log.error("session handler request blocked from invalid address (%s)", request.getRemoteAddr().c_str());
             istringstream msg("Session Handler Blocked");
             return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
@@ -141,7 +134,7 @@ pair<bool,long> SessionHandler::run(SPRequest& request, bool isHandler) const
 
     Session* session = nullptr;
     try {
-        session = request.getSession();
+        session = request.getSession(); // caches the locked session in the request so it's unlocked automatically
         if (!session) {
             s << "A valid session was not found.</pre></body></html>" << endl;
             request.setContentType("text/html");
@@ -150,7 +143,7 @@ pair<bool,long> SessionHandler::run(SPRequest& request, bool isHandler) const
             return make_pair(true, request.sendResponse(s));
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         s << "Exception while retrieving active session:" << endl
             << '\t' << ex.what() << "</pre></body></html>" << endl;
         request.setContentType("text/html");
index 0b9962d..7a7d61d 100644 (file)
 
 #ifndef SHIBSP_LITE
 # include "metadata/MetadataProviderCriteria.h"
+# include <boost/lexical_cast.hpp>
 # include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/EndpointManager.h>
 # include <saml/util/SAMLConstants.h>
 #else
 # include "lite/SAMLConstants.h"
 #endif
+#include <boost/scoped_ptr.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/URLEncoder.h>
 
@@ -48,6 +50,7 @@ using namespace shibsp;
 using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -121,11 +124,11 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
 {
     // We have to know the IdP to function.
     if (entityID.empty() || !checkCompatibility(request, isHandler))
-        return make_pair(false,0L);
+        return make_pair(false, 0L);
 
     string target;
     pair<bool,const char*> prop;
-    const Handler* ACS=nullptr;
+    const Handler* ACS = nullptr;
     const Application& app = request.getApplication();
 
     if (isHandler) {
@@ -227,8 +230,8 @@ pair<bool,long> Shib1SessionInitiator::unwrap(SPRequest& request, DDF& out) cons
 void Shib1SessionInitiator::receive(DDF& in, ostream& out)
 {
     // Find application.
-    const char* aid=in["application_id"].string();
-    const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+    const char* aid = in["application_id"].string();
+    const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
     if (!app) {
         // Something's horribly wrong.
         m_log.error("couldn't find application (%s) to generate AuthnRequest", aid ? aid : "(missing)");
@@ -244,14 +247,14 @@ void Shib1SessionInitiator::receive(DDF& in, ostream& out)
     DDFJanitor jout(ret);
 
     // Wrap the outgoing object with a Response facade.
-    auto_ptr<HTTPResponse> http(getResponse(ret));
+    scoped_ptr<HTTPResponse> http(getResponse(ret));
 
     string relayState(in["RelayState"].string() ? in["RelayState"].string() : "");
 
     // Since we're remoted, the result should either be a throw, which we pass on,
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    doRequest(*app, nullptr, *http.get(), entityID, acsLocation, (in["artifact"].integer() != 0), relayState);
+    doRequest(*app, nullptr, *http, entityID, acsLocation, (in["artifact"].integer() != 0), relayState);
     if (!ret.isstruct())
         ret.structure();
     ret.addmember("RelayState").unsafe_string(relayState.c_str());
@@ -270,7 +273,7 @@ pair<bool,long> Shib1SessionInitiator::doRequest(
 {
 #ifndef SHIBSP_LITE
     // Use metadata to invoke the SSO service directly.
-    MetadataProvider* m=app.getMetadataProvider();
+    MetadataProvider* m = app.getMetadataProvider();
     Locker locker(m);
     MetadataProviderCriteria mc(app, entityID, &IDPSSODescriptor::ELEMENT_QNAME, shibspconstants::SHIB1_PROTOCOL_ENUM);
     pair<const EntityDescriptor*,const RoleDescriptor*> entity = m->getEntityDescriptor(mc);
@@ -281,30 +284,30 @@ pair<bool,long> Shib1SessionInitiator::doRequest(
     else if (!entity.second) {
         m_log.log(getParent() ? Priority::INFO : Priority::WARN, "unable to locate Shibboleth-aware identity provider role for provider (%s)", entityID);
         if (getParent())
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
         throw MetadataException("Unable to locate Shibboleth-aware identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
     }
     else if (artifact && !SPConfig::getConfig().getArtifactResolver()->isSupported(dynamic_cast<const SSODescriptorType&>(*entity.second))) {
         m_log.warn("artifact profile selected for response, but identity provider lacks support");
         if (getParent())
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
         throw MetadataException("Identity provider ($entityID) lacks SAML artifact support.", namedparams(1, "entityID", entityID));
     }
 
-    const EndpointType* ep=EndpointManager<SingleSignOnService>(
+    const EndpointType* ep = EndpointManager<SingleSignOnService>(
         dynamic_cast<const IDPSSODescriptor*>(entity.second)->getSingleSignOnServices()
         ).getByBinding(shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI);
     if (!ep) {
         m_log.warn("unable to locate compatible SSO service for provider (%s)", entityID);
         if (getParent())
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
         throw MetadataException("Unable to locate compatible SSO service for provider ($entityID)", namedparams(1, "entityID", entityID));
     }
 
     preserveRelayState(app, httpResponse, relayState);
 
-    auto_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
-    if (ar_event.get()) {
+    scoped_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
+    if (ar_event) {
         auto_ptr_char prot(getProtocolFamily());
         ar_event->m_protocol = prot.get();
         auto_ptr_char b(shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI);
@@ -317,12 +320,10 @@ pair<bool,long> Shib1SessionInitiator::doRequest(
     if (relayState.empty())
         relayState = "default";
 
-    char timebuf[16];
-    sprintf(timebuf,"%lu",time(nullptr));
     const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
     auto_ptr_char dest(ep->getLocation());
     string req=string(dest.get()) + (strchr(dest.get(),'?') ? '&' : '?') + "shire=" + urlenc->encode(acsLocation) +
-        "&time=" + timebuf + "&target=" + urlenc->encode(relayState.c_str()) +
+        "&time=" + lexical_cast<string>(time(nullptr)) + "&target=" + urlenc->encode(relayState.c_str()) +
         "&providerId=" + urlenc->encode(app.getRelyingParty(entity.first)->getString("entityID").second);
 
     if (httpRequest) {
@@ -332,6 +333,6 @@ pair<bool,long> Shib1SessionInitiator::doRequest(
 
     return make_pair(true, httpResponse.sendRedirect(req.c_str()));
 #else
-    return make_pair(false,0L);
+    return make_pair(false, 0L);
 #endif
 }
index 9a57870..4f549c2 100644 (file)
 #include "util/IPRange.h"
 #include "util/CGIParser.h"
 
+#include <boost/bind.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/algorithm/string.hpp>
 #include <xmltooling/version.h>
 #include <xmltooling/util/DateTime.h>
 
@@ -54,6 +58,7 @@ using namespace opensaml;
 using namespace xmlsignature;
 #endif
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -90,6 +95,14 @@ namespace shibsp {
     private:
         pair<bool,long> processMessage(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
         ostream& systemInfo(ostream& os) const;
+        void parseACL(const string& acl) {
+            try {
+                m_acl.push_back(IPRange::parseCIDRBlock(acl.c_str()));
+            }
+            catch (std::exception& ex) {
+                m_log.error("invalid CIDR block (%s): %s", acl.c_str(), ex.what());
+            }
+        }
 
         vector<IPRange> m_acl;
     };
@@ -124,25 +137,27 @@ namespace shibsp {
     public:
         DummyRequest(const char* url) : m_parser(nullptr), m_url(url), m_scheme(nullptr), m_query(nullptr), m_port(0) {
 #ifdef HAVE_STRCASECMP
-            if (url && !strncasecmp(url,"http://",7)) {
-                m_scheme="http";
-                url+=7;
+            if (url && !strncasecmp(url,"http://", 7)) {
+                m_scheme = "http";
+                m_port = 80;
+                url += 7;
             }
-            else if (url && !strncasecmp(url,"https://",8)) {
-                m_scheme="https";
-                url+=8;
+            else if (url && !strncasecmp(url,"https://", 8)) {
+                m_scheme = "https";
+                m_port = 443;
+                url += 8;
             }
             else
 #else
-            if (url && !strnicmp(url,"http://",7)) {
-                m_scheme="http";
+            if (url && !strnicmp(url,"http://", 7)) {
+                m_scheme = "http";
                 m_port = 80;
-                url+=7;
+                url += 7;
             }
-            else if (url && !strnicmp(url,"https://",8)) {
+            else if (url && !strnicmp(url,"https://", 8)) {
                 m_scheme="https";
                 m_port = 443;
-                url+=8;
+                url += 8;
             }
             else
 #endif
@@ -182,9 +197,7 @@ namespace shibsp {
             }
         }
 
-        virtual ~DummyRequest() {
-            delete m_parser;
-        }
+        virtual ~DummyRequest() {}
 
         const char* getRequestURL() const {
             return m_url;
@@ -225,18 +238,18 @@ namespace shibsp {
         const char* getParameter(const char* name) const
         {
             if (!m_parser)
-                m_parser=new CGIParser(*this);
+                m_parser.reset(new CGIParser(*this));
 
-            pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
-            return (bounds.first==bounds.second) ? nullptr : bounds.first->second;
+            pair<CGIParser::walker,CGIParser::walker> bounds = m_parser->getParameters(name);
+            return (bounds.first == bounds.second) ? nullptr : bounds.first->second;
         }
         vector<const char*>::size_type getParameters(const char* name, vector<const char*>& values) const
         {
             if (!m_parser)
-                m_parser=new CGIParser(*this);
+                m_parser.reset(new CGIParser(*this));
 
-            pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
-            while (bounds.first!=bounds.second) {
+            pair<CGIParser::walker,CGIParser::walker> bounds = m_parser->getParameters(name);
+            while (bounds.first != bounds.second) {
                 values.push_back(bounds.first->second);
                 ++bounds.first;
             }
@@ -256,7 +269,7 @@ namespace shibsp {
         }
 
     private:
-        mutable CGIParser* m_parser;
+        mutable scoped_ptr<CGIParser> m_parser;
         const char* m_url;
         const char* m_scheme;
         const char* m_query;
@@ -272,25 +285,9 @@ StatusHandler::StatusHandler(const DOMElement* e, const char* appId)
         pair<bool,const char*> acl = getString("acl");
         if (acl.first) {
             string aclbuf=acl.second;
-            int j = 0;
-            for (unsigned int i=0;  i < aclbuf.length();  i++) {
-                if (aclbuf.at(i)==' ') {
-                    try {
-                        m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, i-j).c_str()));
-                    }
-                    catch (exception& ex) {
-                        m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, i-j).c_str(), ex.what());
-                    }
-                    j = i + 1;
-                }
-            }
-            try {
-                m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, aclbuf.length()-j).c_str()));
-            }
-            catch (exception& ex) {
-                m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, aclbuf.length()-j).c_str(), ex.what());
-            }
-
+            vector<string> aclarray;
+            split(aclarray, aclbuf, is_space(), algorithm::token_compress_on);
+            for_each(aclarray.begin(), aclarray.end(), boost::bind(&StatusHandler::parseACL, this, _1));
             if (m_acl.empty()) {
                 m_log.warn("invalid CIDR range(s) in Status handler acl property, allowing 127.0.0.1 as a fall back");
                 m_acl.push_back(IPRange::parseCIDRBlock("127.0.0.1"));
@@ -307,11 +304,8 @@ pair<bool,long> StatusHandler::run(SPRequest& request, bool isHandler) const
 {
     SPConfig& conf = SPConfig::getConfig();
     if (conf.isEnabled(SPConfig::InProcess) && !m_acl.empty()) {
-        bool found = false;
-        for (vector<IPRange>::const_iterator acl = m_acl.begin(); !found && acl != m_acl.end(); ++acl) {
-            found = acl->contains(request.getRemoteAddr().c_str());
-        }
-        if (!found) {
+        static bool (IPRange::* contains)(const char*) const = &IPRange::contains;
+        if (find_if(m_acl.begin(), m_acl.end(), boost::bind(contains, _1, request.getRemoteAddr().c_str())) == m_acl.end()) {
             m_log.error("status handler request blocked from invalid address (%s)", request.getRemoteAddr().c_str());
             istringstream msg("Status Handler Blocked");
             return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
@@ -345,7 +339,7 @@ pair<bool,long> StatusHandler::run(SPRequest& request, bool isHandler) const
             msg << '>' << target << "</RequestSettings>";
             msg << "<Status><OK/></Status>";
         msg << "</StatusHandler>";
-        return make_pair(true,request.sendResponse(msg));
+        return make_pair(true, request.sendResponse(msg));
     }
 
     try {
@@ -378,9 +372,9 @@ pair<bool,long> StatusHandler::run(SPRequest& request, bool isHandler) const
                 << "' Shibboleth='" << PACKAGE_VERSION << "'/>";
             systemInfo(msg) << "<Status><Exception type='" << ex.getClassName() << "'>" << ex.what() << "</Exception></Status>";
         msg << "</StatusHandler>";
-        return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
+        return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error while processing request: %s", ex.what());
         DateTime now(time(nullptr));
         now.parseDateTime();
@@ -397,15 +391,15 @@ pair<bool,long> StatusHandler::run(SPRequest& request, bool isHandler) const
                 << "' Shibboleth='" << PACKAGE_VERSION << "'/>";
             systemInfo(msg) << "<Status><Exception type='std::exception'>" << ex.what() << "</Exception></Status>";
         msg << "</StatusHandler>";
-        return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
+        return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
     }
 }
 
 void StatusHandler::receive(DDF& in, ostream& out)
 {
     // Find application.
-    const char* aid=in["application_id"].string();
-    const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+    const char* aid = in["application_id"].string();
+    const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
     if (!app) {
         // Something's horribly wrong.
         m_log.error("couldn't find application (%s) for status request", aid ? aid : "(missing)");
@@ -415,13 +409,13 @@ void StatusHandler::receive(DDF& in, ostream& out)
     // Wrap a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPRequest> req(getRequest(in));
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     // Since we're remoted, the result should either be a throw, a false/0 return,
     // which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    processMessage(*app, *req.get(), *resp.get());
+    processMessage(*app, *req, *resp);
     out << ret;
 }
 
@@ -467,7 +461,7 @@ pair<bool,long> StatusHandler::processMessage(
             s << "<SessionCache><Exception type='" << ex.getClassName() << "'>" << ex.what() << "</Exception></SessionCache>";
             status = "<Partial/>";
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             s << "<SessionCache><Exception type='std::exception'>" << ex.what() << "</Exception></SessionCache>";
             status = "<Partial/>";
         }
@@ -475,7 +469,7 @@ pair<bool,long> StatusHandler::processMessage(
         MetadataProvider* m = application.getMetadataProvider();
         Locker mlock(m);
 
-        const PropertySet* relyingParty=nullptr;
+        const PropertySet* relyingParty = nullptr;
         param=httpRequest.getParameter("entityID");
         if (param)
             relyingParty = application.getRelyingParty(m->getEntityDescriptor(MetadataProviderCriteria(application, param)).first);
@@ -489,15 +483,16 @@ pair<bool,long> StatusHandler::processMessage(
         s << "<Handlers>";
         vector<const Handler*> handlers;
         application.getHandlers(handlers);
-        for (vector<const Handler*>::const_iterator h = handlers.begin(); h != handlers.end(); ++h) {
-            s << "<Handler type='" << (*h)->getType() << "' Location='" << (*h)->getString("Location").second << "'";
-            if ((*h)->getString("Binding").first)
-                s << " Binding='" << (*h)->getString("Binding").second << "'";
+        for (indirect_iterator<vector<const Handler*>::const_iterator> h = make_indirect_iterator(handlers.begin());
+                h != make_indirect_iterator(handlers.end()); ++h) {
+            s << "<Handler type='" << h->getType() << "' Location='" << h->getString("Location").second << "'";
+            if (h->getString("Binding").first)
+                s << " Binding='" << h->getString("Binding").second << "'";
             s << "/>";
         }
         s << "</Handlers>";
 
-        CredentialResolver* credResolver=application.getCredentialResolver();
+        CredentialResolver* credResolver = application.getCredentialResolver();
         if (credResolver) {
             Locker credLocker(credResolver);
             CredentialCriteria cc;
@@ -506,11 +501,11 @@ pair<bool,long> StatusHandler::processMessage(
             if (keyName.first)
                 cc.getKeyNames().insert(keyName.second);
             vector<const Credential*> creds;
-            credResolver->resolve(creds,&cc);
+            credResolver->resolve(creds, &cc);
             for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
                 KeyInfo* kinfo = (*c)->getKeyInfo();
                 if (kinfo) {
-                    auto_ptr<KeyDescriptor> kd(KeyDescriptorBuilder::buildKeyDescriptor());
+                    scoped_ptr<KeyDescriptor> kd(KeyDescriptorBuilder::buildKeyDescriptor());
                     kd->setUse(KeyDescriptor::KEYTYPE_SIGNING);
                     kd->setKeyInfo(kinfo);
                     s << *(kd.get());
@@ -520,11 +515,11 @@ pair<bool,long> StatusHandler::processMessage(
             cc.setUsage(Credential::ENCRYPTION_CREDENTIAL);
             creds.clear();
             cc.getKeyNames().clear();
-            credResolver->resolve(creds,&cc);
+            credResolver->resolve(creds, &cc);
             for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
                 KeyInfo* kinfo = (*c)->getKeyInfo();
                 if (kinfo) {
-                    auto_ptr<KeyDescriptor> kd(KeyDescriptorBuilder::buildKeyDescriptor());
+                    scoped_ptr<KeyDescriptor> kd(KeyDescriptorBuilder::buildKeyDescriptor());
                     kd->setUse(KeyDescriptor::KEYTYPE_ENCRYPTION);
                     kd->setKeyInfo(kinfo);
                     s << *(kd.get());
@@ -538,7 +533,7 @@ pair<bool,long> StatusHandler::processMessage(
     httpResponse.setContentType("text/xml");
     return make_pair(true, httpResponse.sendResponse(s));
 #else
-    return make_pair(false,0L);
+    return make_pair(false, 0L);
 #endif
 }
 
index 8283a6d..baaf4b0 100644 (file)
@@ -38,6 +38,7 @@
 # include "metadata/MetadataProviderCriteria.h"
 # include <saml/saml2/metadata/Metadata.h>
 #endif
+#include <boost/tuple/tuple.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/URLEncoder.h>
 #include <xercesc/util/XMLUniDefs.hpp>
@@ -47,6 +48,7 @@ using namespace shibsp;
 using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -97,19 +99,17 @@ namespace shibsp {
                 e = XMLHelper::getFirstChildElement(e);
                 while (e) {
                     if (e->hasChildNodes()) {
-                        const XMLCh* flag = e->getAttributeNS(nullptr, force);
-                        if (!flag)
-                            flag = &chNull;
+                        bool flag = XMLHelper::getAttrBool(e, false, force);
                         if (XMLString::equals(e->getLocalName(), Subst)) {
-                            auto_ptr_char temp(e->getFirstChild()->getNodeValue());
+                            auto_ptr_char temp(e->getTextContent());
                             if (temp.get() && *temp.get())
-                                m_subst.push_back(pair<bool,string>((*flag==chDigit_1 || *flag==chLatin_t), temp.get()));
+                                m_subst.push_back(pair<bool,string>(flag, temp.get()));
                         }
                         else if (XMLString::equals(e->getLocalName(), Regex) && e->hasAttributeNS(nullptr, match)) {
                             auto_ptr_char m(e->getAttributeNS(nullptr, match));
-                            auto_ptr_char repl(e->getFirstChild()->getNodeValue());
+                            auto_ptr_char repl(e->getTextContent());
                             if (m.get() && *m.get() && repl.get() && *repl.get())
-                                m_regex.push_back(make_pair((*flag==chDigit_1 || *flag==chLatin_t), pair<string,string>(m.get(), repl.get())));
+                                m_regex.push_back(tuple<bool,string,string>(flag, m.get(), repl.get()));
                         }
                         else {
                             m_log.warn("Unknown element found in Transform SessionInitiator configuration, check for errors.");
@@ -133,7 +133,7 @@ namespace shibsp {
 #ifndef SHIBSP_LITE
         bool m_alwaysRun;
         vector< pair<bool, string> > m_subst;
-        vector< pair< bool, pair<string,string> > > m_regex;
+        vector< tuple<bool,string,string> > m_regex;
 #endif
     };
 
@@ -165,9 +165,9 @@ pair<bool,long> TransformSessionInitiator::run(SPRequest& request, string& entit
 {
     // We have to have a candidate name to function.
     if (entityID.empty() || !checkCompatibility(request, isHandler))
-        return make_pair(false,0L);
+        return make_pair(false, 0L);
 
-    const Application& app=request.getApplication();
+    const Application& app = request.getApplication();
 
     m_log.debug("attempting to transform input (%s) into a valid entityID", entityID.c_str());
 
@@ -186,14 +186,14 @@ pair<bool,long> TransformSessionInitiator::run(SPRequest& request, string& entit
             entityID = out.string();
     }
     
-    return make_pair(false,0L);
+    return make_pair(false, 0L);
 }
 
 void TransformSessionInitiator::receive(DDF& in, ostream& out)
 {
     // Find application.
-    const char* aid=in["application_id"].string();
-    const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+    const char* aid = in["application_id"].string();
+    const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
     if (!app) {
         // Something's horribly wrong.
         m_log.error("couldn't find application (%s) to generate AuthnRequest", aid ? aid : "(missing)");
@@ -214,7 +214,7 @@ void TransformSessionInitiator::receive(DDF& in, ostream& out)
 void TransformSessionInitiator::doRequest(const Application& application, string& entityID) const
 {
 #ifndef SHIBSP_LITE
-    MetadataProvider* m=application.getMetadataProvider();
+    MetadataProvider* m = application.getMetadataProvider();
     Locker locker(m);
 
     MetadataProviderCriteria mc(application, entityID.c_str(), &IDPSSODescriptor::ELEMENT_QNAME);
@@ -254,10 +254,10 @@ void TransformSessionInitiator::doRequest(const Application& application, string
     }
 
     // Now try regexs.
-    for (vector< pair< bool, pair<string,string> > >::const_iterator r = m_regex.begin(); r != m_regex.end(); ++r) {
+    for (vector< tuple<bool,string,string> >::const_iterator r = m_regex.begin(); r != m_regex.end(); ++r) {
         try {
-            RegularExpression exp(r->second.first.c_str());
-            XMLCh* temp = exp.replace(entityID.c_str(), r->second.second.c_str());
+            RegularExpression exp(r->get<1>().c_str());
+            XMLCh* temp = exp.replace(entityID.c_str(), r->get<2>().c_str());
             if (temp) {
                 auto_ptr_char narrow(temp);
                 XMLString::release(&temp);
@@ -266,7 +266,7 @@ void TransformSessionInitiator::doRequest(const Application& application, string
                 if (entityID == narrow.get())
                     continue;
 
-                if (r->first) {
+                if (r->get<0>()) {
                     m_log.info("forcibly transformed entityID from (%s) to (%s)", entityID.c_str(), narrow.get());
                     entityID = narrow.get();
                 }
@@ -277,7 +277,7 @@ void TransformSessionInitiator::doRequest(const Application& application, string
                 entity = m->getEntityDescriptor(mc);
                 if (entity.first) {
                     m_log.info("transformed entityID from (%s) to (%s)", entityID.c_str(), narrow.get());
-                    if (!r->first)
+                    if (!r->get<0>())
                         entityID = narrow.get();
                     return;
                 }
index bfb8abb..879e54e 100644 (file)
 #endif
 
 #include <ctime>
+#include <boost/lexical_cast.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/URLEncoder.h>
 
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -91,12 +93,12 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
     // The IdP CANNOT be specified for us to run. Otherwise, we'd be redirecting to a WAYF
     // anytime the IdP's metadata was wrong.
     if (!entityID.empty() || !checkCompatibility(request, isHandler))
-        return make_pair(false,0L);
+        return make_pair(false, 0L);
 
     string target;
     pair<bool,const char*> prop;
-    const Handler* ACS=nullptr;
-    const Application& app=request.getApplication();
+    const Handler* ACS = nullptr;
+    const Application& app = request.getApplication();
     pair<bool,const char*> discoveryURL = pair<bool,const char*>(true, m_url);
 
     if (isHandler) {
@@ -175,11 +177,9 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
     if (target.empty())
         target = "default";
 
-    char timebuf[16];
-    sprintf(timebuf,"%lu",time(nullptr));
     const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
     string req=string(discoveryURL.second) + (strchr(discoveryURL.second,'?') ? '&' : '?') + "shire=" + urlenc->encode(ACSloc.c_str()) +
-        "&time=" + timebuf + "&target=" + urlenc->encode(target.c_str()) +
+        "&time=" + lexical_cast<string>(time(nullptr)) + "&target=" + urlenc->encode(target.c_str()) +
         "&providerId=" + urlenc->encode(app.getString("entityID").second);
 
     return make_pair(true, request.sendRedirect(req.c_str()));
index a3987ab..2795462 100644 (file)
@@ -348,7 +348,7 @@ namespace shibsp {
         DDF m_obj;
 #ifndef SHIBSP_LITE
         scoped_ptr<saml2::NameID> m_nameid;
-        mutable map<string,boost::shared_ptr<Assertion>> m_tokens;
+        mutable map< string,boost::shared_ptr<Assertion> > m_tokens;
 #endif
         mutable vector<Attribute*> m_attributes;
         mutable multimap<string,const Attribute*> m_attributeIndex;
index 8336474..f5b7042 100644 (file)
@@ -109,7 +109,7 @@ CGIParser::CGIParser(const HTTPRequest& request, bool queryOnly)
 
 CGIParser::~CGIParser()
 {
-    for_each(kvp_map.begin(), kvp_map.end(), boost::bind(&free, boost::bind(&multimap<string,char*>::value_type::second, _1)));
+    for_each(kvp_map.begin(), kvp_map.end(), boost::bind<void>(&free, boost::bind(&multimap<string,char*>::value_type::second, _1)));
 }
 
 void CGIParser::parse(const char* pch)
index dc17b35..7ec1f49 100644 (file)
@@ -160,7 +160,7 @@ void DOMPropertySet::load(
 
 pair<bool,bool> DOMPropertySet::getBool(const char* name, const char* ns) const
 {
-    map<string,pair<char*,const XMLCh*> >::const_iterator i;
+    map< string,pair<char*,const XMLCh*> >::const_iterator i;
 
     if (ns)
         i=m_map.find(string("{") + ns + '}' + name);
@@ -177,7 +177,7 @@ pair<bool,bool> DOMPropertySet::getBool(const char* name, const char* ns) const
 pair<bool,const char*> DOMPropertySet::getString(const char* name, const char* ns) const
 {
     pair<bool,const char*> ret(false,nullptr);
-    map<string,pair<char*,const XMLCh*> >::const_iterator i;
+    map< string,pair<char*,const XMLCh*> >::const_iterator i;
 
     if (ns)
         i=m_map.find(string("{") + ns + '}' + name);
@@ -193,7 +193,7 @@ pair<bool,const char*> DOMPropertySet::getString(const char* name, const char* n
 
 pair<bool,const XMLCh*> DOMPropertySet::getXMLString(const char* name, const char* ns) const
 {
-    map<string,pair<char*,const XMLCh*> >::const_iterator i;
+    map< string,pair<char*,const XMLCh*> >::const_iterator i;
 
     if (ns)
         i=m_map.find(string("{") + ns + '}' + name);
@@ -225,7 +225,7 @@ pair<bool,unsigned int> DOMPropertySet::getUnsignedInt(const char* name, const c
 
 pair<bool,int> DOMPropertySet::getInt(const char* name, const char* ns) const
 {
-    map<string,pair<char*,const XMLCh*> >::const_iterator i;
+    map< string,pair<char*,const XMLCh*> >::const_iterator i;
 
     if (ns)
         i=m_map.find(string("{") + ns + '}' + name);
@@ -249,7 +249,7 @@ void DOMPropertySet::getAll(std::map<std::string,const char*>& properties) const
 
 const PropertySet* DOMPropertySet::getPropertySet(const char* name, const char* ns) const
 {
-    map<string,boost::shared_ptr<DOMPropertySet>>::const_iterator i;
+    map< string,boost::shared_ptr<DOMPropertySet> >::const_iterator i;
 
     if (ns)
         i = m_nested.find(string("{") + ns + '}' + name);
index 5d51a1b..91b8498 100644 (file)
@@ -85,7 +85,7 @@ namespace shibsp {
         const PropertySet* m_parent;
         const xercesc::DOMElement* m_root;
         std::map<std::string,std::pair<char*,const XMLCh*> > m_map;
-        std::map<std::string,boost::shared_ptr<DOMPropertySet>> m_nested;
+        std::map< std::string,boost::shared_ptr<DOMPropertySet> > m_nested;
         std::vector<xmltooling::xstring> m_injected;
     };