From d1747a3becf22265e6568aba9721a888c7ffdd0b Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Sun, 5 Aug 2007 21:42:40 +0000 Subject: [PATCH] Revise attribute APIs to use vectors in place of multimaps. --- adfs/adfs.cpp | 10 ++--- apache/mod_apache.cpp | 4 +- shibsp/ServiceProvider.cpp | 4 +- shibsp/SessionCache.h | 13 ++++-- shibsp/attribute/filtering/AttributeFilter.h | 4 +- shibsp/attribute/filtering/BasicFilteringContext.h | 8 ++-- .../filtering/impl/ChainingAttributeFilter.cpp | 2 +- .../filtering/impl/XMLAttributeFilter.cpp | 48 ++++++++++++---------- shibsp/attribute/resolver/AttributeExtractor.h | 4 +- shibsp/attribute/resolver/AttributeResolver.h | 4 +- shibsp/attribute/resolver/ResolutionContext.h | 2 +- .../resolver/impl/ChainingAttributeResolver.cpp | 10 ++--- .../resolver/impl/QueryAttributeResolver.cpp | 14 +++---- .../resolver/impl/XMLAttributeExtractor.cpp | 28 ++++++------- shibsp/handler/AssertionConsumerService.h | 2 +- shibsp/handler/impl/AssertionConsumerService.cpp | 2 +- shibsp/handler/impl/SAML1Consumer.cpp | 10 ++--- shibsp/handler/impl/SAML2Consumer.cpp | 10 ++--- shibsp/impl/RemotedSessionCache.cpp | 18 +++++--- shibsp/impl/StorageServiceSessionCache.cpp | 33 +++++++++------ shibsp/impl/XMLAccessControl.cpp | 4 +- 21 files changed, 133 insertions(+), 101 deletions(-) diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp index 6570271..cbbd56d 100644 --- a/adfs/adfs.cpp +++ b/adfs/adfs.cpp @@ -561,7 +561,7 @@ string ADFSConsumer::implementProtocol( // We've successfully "accepted" the SSO token. // To complete processing, we need to extract and resolve attributes and then create the session. - multimap resolvedAttributes; + vector resolvedAttributes; AttributeExtractor* extractor = application.getAttributeExtractor(); if (extractor) { m_log.debug("extracting pushed attributes..."); @@ -591,7 +591,7 @@ string ADFSConsumer::implementProtocol( catch (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(), cleanup_pair()); + for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup()); resolvedAttributes.clear(); } } @@ -625,7 +625,7 @@ string ADFSConsumer::implementProtocol( tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end()); // Copy over new attributes, and transfer ownership. - resolvedAttributes.insert(ctx->getResolvedAttributes().begin(), ctx->getResolvedAttributes().end()); + resolvedAttributes.insert(resolvedAttributes.end(), ctx->getResolvedAttributes().begin(), ctx->getResolvedAttributes().end()); ctx->getResolvedAttributes().clear(); } @@ -644,11 +644,11 @@ string ADFSConsumer::implementProtocol( &tokens, &resolvedAttributes ); - for_each(resolvedAttributes.begin(), resolvedAttributes.end(), cleanup_pair()); + for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup()); return key; } catch (exception&) { - for_each(resolvedAttributes.begin(), resolvedAttributes.end(), cleanup_pair()); + for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup()); throw; } } diff --git a/apache/mod_apache.cpp b/apache/mod_apache.cpp index b7be829..dc638f9 100644 --- a/apache/mod_apache.cpp +++ b/apache/mod_apache.cpp @@ -964,8 +964,8 @@ bool htAccessControl::authorized(const SPRequest& request, const Session* sessio } // Find the attribute(s) matching the require rule. - pair::const_iterator,multimap::const_iterator> attrs = - session->getAttributes().equal_range(w); + pair::const_iterator,multimap::const_iterator> attrs = + session->getIndexedAttributes().equal_range(w); if (attrs.first == attrs.second) { request.log(SPRequest::SPWarn, string("htAccessControl rule requires attribute (") + w + "), not found in session"); continue; diff --git a/shibsp/ServiceProvider.cpp b/shibsp/ServiceProvider.cpp index 4b74096..5af4e4b 100644 --- a/shibsp/ServiceProvider.cpp +++ b/shibsp/ServiceProvider.cpp @@ -380,8 +380,8 @@ pair ServiceProvider::doExport(SPRequest& request, bool requireSessio // Export the attributes. bool remoteUserSet = false; - const multimap& attributes = session->getAttributes(); - for (multimap::const_iterator a = attributes.begin(); a!=attributes.end(); ++a) { + const multimap& attributes = session->getIndexedAttributes(); + for (multimap::const_iterator a = attributes.begin(); a!=attributes.end(); ++a) { const vector& vals = a->second->getSerializedValues(); // See if this needs to be set as the REMOTE_USER value. diff --git a/shibsp/SessionCache.h b/shibsp/SessionCache.h index 930b2a7..91de942 100644 --- a/shibsp/SessionCache.h +++ b/shibsp/SessionCache.h @@ -115,9 +115,16 @@ namespace shibsp { /** * Returns the resolved attributes associated with the session. * + * @return an immutable array of attributes + */ + virtual const std::vector& getAttributes() const=0; + + /** + * Returns the resolved attributes associated with the session, indexed by ID + * * @return an immutable map of attributes keyed by attribute ID */ - virtual const std::multimap& getAttributes() const=0; + virtual const std::multimap& getIndexedAttributes() const=0; /** * Returns the identifiers of the assertion(s) cached by the session. @@ -203,7 +210,7 @@ namespace shibsp { * @param authncontext_class method/category of authentication event, if known * @param authncontext_decl specifics of authentication event, if known * @param tokens assertions to cache with session, if any - * @param attributes optional map of resolved Attributes to cache with session + * @param attributes optional array of resolved Attributes to cache with session * @return newly created session's key */ virtual std::string insert( @@ -218,7 +225,7 @@ namespace shibsp { const XMLCh* authncontext_class=NULL, const XMLCh* authncontext_decl=NULL, const std::vector* tokens=NULL, - const std::multimap* attributes=NULL + const std::vector* attributes=NULL )=0; /** diff --git a/shibsp/attribute/filtering/AttributeFilter.h b/shibsp/attribute/filtering/AttributeFilter.h index 7eeb63d..75521a3 100644 --- a/shibsp/attribute/filtering/AttributeFilter.h +++ b/shibsp/attribute/filtering/AttributeFilter.h @@ -44,11 +44,11 @@ namespace shibsp { * Filters values out of a set of attributes. * * @param context a FilteringContext interface - * @param attributes a mutable map containing the attributes to filter + * @param attributes a mutable array containing the attributes to filter * * @throws AttributeFileringException thrown if there is a problem filtering attributes */ - virtual void filterAttributes(const FilteringContext& context, std::multimap& attributes) const=0; + virtual void filterAttributes(const FilteringContext& context, std::vector& attributes) const=0; }; /** diff --git a/shibsp/attribute/filtering/BasicFilteringContext.h b/shibsp/attribute/filtering/BasicFilteringContext.h index 721d638..2207941 100644 --- a/shibsp/attribute/filtering/BasicFilteringContext.h +++ b/shibsp/attribute/filtering/BasicFilteringContext.h @@ -41,13 +41,15 @@ namespace shibsp { */ BasicFilteringContext( const Application& app, - const std::multimap& attributes, + const std::vector& attributes, const opensaml::saml2md::RoleDescriptor* role=NULL, const XMLCh* authncontext_class=NULL, const XMLCh* authncontext_decl=NULL - ) : m_app(app), m_attributes(attributes), m_role(role), m_issuer(NULL), m_class(authncontext_class), m_decl(authncontext_decl) { + ) : m_app(app), m_role(role), m_issuer(NULL), m_class(authncontext_class), m_decl(authncontext_decl) { if (role) m_issuer = dynamic_cast(role->getParent())->getEntityID(); + for (std::vector::const_iterator a = attributes.begin(); a != attributes.end(); ++a) + m_attributes.insert(std::make_pair((*a)->getId(), *a)); } virtual ~BasicFilteringContext() {} @@ -79,7 +81,7 @@ namespace shibsp { private: const Application& m_app; - const std::multimap& m_attributes; + std::multimap m_attributes; const opensaml::saml2md::RoleDescriptor* m_role; const XMLCh* m_issuer; const XMLCh* m_class; diff --git a/shibsp/attribute/filtering/impl/ChainingAttributeFilter.cpp b/shibsp/attribute/filtering/impl/ChainingAttributeFilter.cpp index 7842a59..f9ba21e 100644 --- a/shibsp/attribute/filtering/impl/ChainingAttributeFilter.cpp +++ b/shibsp/attribute/filtering/impl/ChainingAttributeFilter.cpp @@ -47,7 +47,7 @@ namespace shibsp { void unlock() { } - void filterAttributes(const FilteringContext& context, multimap& attributes) const { + void filterAttributes(const FilteringContext& context, vector& attributes) const { for (vector::const_iterator i=m_filters.begin(); i!=m_filters.end(); ++i) { Locker locker(*i); (*i)->filterAttributes(context, attributes); diff --git a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp index 743a322..0e50fbb 100644 --- a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp +++ b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp @@ -69,7 +69,7 @@ namespace shibsp { m_document = doc; } - void filterAttributes(const FilteringContext& context, multimap& attributes) const; + void filterAttributes(const FilteringContext& context, vector& attributes) const; private: MatchFunctor* buildFunctor( @@ -95,7 +95,7 @@ namespace shibsp { delete m_impl; } - void filterAttributes(const FilteringContext& context, multimap& attributes) const { + void filterAttributes(const FilteringContext& context, vector& attributes) const { m_impl->filterAttributes(context, attributes); } @@ -280,7 +280,7 @@ pair XMLFilterImpl::buildAttributeRule(const DOMElem return make_pair(string(),(MatchFunctor*)NULL); } -void XMLFilterImpl::filterAttributes(const FilteringContext& context, multimap& attributes) const +void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector& attributes) const { auto_ptr_char issuer(context.getAttributeIssuer()); @@ -288,7 +288,7 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, multimap()); + for_each(attributes.begin(), attributes.end(), xmltooling::cleanup()); attributes.clear(); return; } @@ -299,26 +299,30 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, multimap::const_iterator p=m_policies.begin(); p!=m_policies.end(); ++p) { if (p->m_applies->evaluatePolicyRequirement(context)) { // Loop over the attributes and look for possible rules to run. - for (multimap::iterator a=attributes.begin(); a!=attributes.end();) { + for (vector::size_type a=0; a rules = p->m_rules.equal_range(a->second->getId()); + Attribute* attr = attributes[a]; + pair rules = p->m_rules.equal_range(attr->getId()); if (rules.first != rules.second) { ruleFound = true; // Run each rule in sequence. - m_log.debug("applying filtering rule(s) for attribute (%s) from (%s)", a->second->getId(), issuer.get() ? issuer.get() : "unknown source"); + m_log.debug( + "applying filtering rule(s) for attribute (%s) from (%s)", + attr->getId(), issuer.get() ? issuer.get() : "unknown source" + ); for (; rules.first!=rules.second; ++rules.first) { - count = a->second->valueCount(); + count = attr->valueCount(); for (index=0; index < count;) { // The return value tells us whether to index past the accepted value, or stay put and decrement the count. - if (rules.first->second->evaluatePermitValue(context, *(a->second), index)) { + if (rules.first->second->evaluatePermitValue(context, *attr, index)) { index++; } else { m_log.warn( "filtered value at position (%lu) of attribute (%s) from (%s)", - index, a->second->getId(), issuer.get() ? issuer.get() : "unknown source" + index, attr->getId(), issuer.get() ? issuer.get() : "unknown source" ); - a->second->removeValue(index); + attr->removeValue(index); count--; } } @@ -329,39 +333,41 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, multimapsecond->getId(), issuer.get() ? issuer.get() : "unknown source"); + m_log.debug( + "applying wildcard rule(s) for attribute (%s) from (%s)", + attr->getId(), issuer.get() ? issuer.get() : "unknown source" + ); ruleFound = true; } for (; rules.first!=rules.second; ++rules.first) { - count = a->second->valueCount(); + count = attr->valueCount(); for (index=0; index < count;) { // The return value tells us whether to index past the accepted value, or stay put and decrement the count. - if (rules.first->second->evaluatePermitValue(context, *(a->second), index)) { + if (rules.first->second->evaluatePermitValue(context, *attr, index)) { index++; } else { m_log.warn( "filtered value at position (%lu) of attribute (%s) from (%s)", - index, a->second->getId(), issuer.get() ? issuer.get() : "unknown source" + index, attr->getId(), issuer.get() ? issuer.get() : "unknown source" ); - a->second->removeValue(index); + attr->removeValue(index); count--; } } } } - if (!ruleFound || a->second->valueCount() == 0) { + if (!ruleFound || attr->valueCount() == 0) { if (!ruleFound) { // No rule found, so we're filtering it out. m_log.warn( "no rule found, filtering out values of attribute (%s) from (%s)", - a->second->getId(), issuer.get() ? issuer.get() : "unknown source" + attr->getId(), issuer.get() ? issuer.get() : "unknown source" ); } - multimap::iterator dead = a++; - delete dead->second; - attributes.erase(dead); + delete attr; + attributes.erase(attributes.begin() + a); } else { ++a; diff --git a/shibsp/attribute/resolver/AttributeExtractor.h b/shibsp/attribute/resolver/AttributeExtractor.h index 7975f8c..e5adb5a 100644 --- a/shibsp/attribute/resolver/AttributeExtractor.h +++ b/shibsp/attribute/resolver/AttributeExtractor.h @@ -49,7 +49,7 @@ namespace shibsp { * @param application Application performing the extraction * @param issuer source of object, if known * @param xmlObject object to extract - * @param attributes a map to populate with the extracted attributes, keyed by id + * @param attributes an array to populate with the extracted attributes * * @throws AttributeExtractionException thrown if there is a problem extracting attributes */ @@ -57,7 +57,7 @@ namespace shibsp { const Application& application, const opensaml::saml2md::RoleDescriptor* issuer, const xmltooling::XMLObject& xmlObject, - std::multimap& attributes + std::vector& attributes ) const=0; /** diff --git a/shibsp/attribute/resolver/AttributeResolver.h b/shibsp/attribute/resolver/AttributeResolver.h index 4376c89..41646ce 100644 --- a/shibsp/attribute/resolver/AttributeResolver.h +++ b/shibsp/attribute/resolver/AttributeResolver.h @@ -65,7 +65,7 @@ namespace shibsp { * @param authncontext_class method/category of authentication event, if known * @param authncontext_decl specifics of authentication event, if known * @param tokens assertions initiating the Session, if any - * @param attributes map of previously resolved attributes, if any + * @param attributes array of previously resolved attributes, if any * @return newly created ResolutionContext, owned by caller */ virtual ResolutionContext* createResolutionContext( @@ -76,7 +76,7 @@ namespace shibsp { const XMLCh* authncontext_class=NULL, const XMLCh* authncontext_decl=NULL, const std::vector* tokens=NULL, - const std::multimap* attributes=NULL + const std::vector* attributes=NULL ) const=0; /** diff --git a/shibsp/attribute/resolver/ResolutionContext.h b/shibsp/attribute/resolver/ResolutionContext.h index ecd20f1..760246a 100644 --- a/shibsp/attribute/resolver/ResolutionContext.h +++ b/shibsp/attribute/resolver/ResolutionContext.h @@ -51,7 +51,7 @@ namespace shibsp { * * @return a mutable array of Attributes. */ - virtual std::multimap& getResolvedAttributes()=0; + virtual std::vector& getResolvedAttributes()=0; /** * Returns the set of assertions resolved and added to the context. diff --git a/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp b/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp index 6579762..117c1a9 100644 --- a/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp +++ b/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp @@ -42,11 +42,11 @@ namespace shibsp { { ~ChainingContext() { for_each(m_contexts.begin(), m_contexts.end(), xmltooling::cleanup()); - for_each(m_attributes.begin(), m_attributes.end(), cleanup_pair()); + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); for_each(m_assertions.begin(), m_assertions.end(), xmltooling::cleanup()); } - multimap& getResolvedAttributes() { + vector& getResolvedAttributes() { return m_attributes; } vector& getResolvedAssertions() { @@ -54,7 +54,7 @@ namespace shibsp { } vector m_contexts; - multimap m_attributes; + vector m_attributes; vector m_assertions; }; @@ -82,7 +82,7 @@ namespace shibsp { const XMLCh* authncontext_class=NULL, const XMLCh* authncontext_decl=NULL, const vector* tokens=NULL, - const multimap* attributes=NULL + const vector* attributes=NULL ) const { auto_ptr chain(new ChainingContext()); for (vector::const_iterator i=m_resolvers.begin(); i!=m_resolvers.end(); ++i) @@ -147,7 +147,7 @@ void ChainingAttributeResolver::resolveAttributes(ResolutionContext& ctx) const vector::iterator ictx = chain.m_contexts.begin(); for (vector::const_iterator i=m_resolvers.begin(); i!=m_resolvers.end(); ++i, ++ictx) { (*i)->resolveAttributes(*(*ictx)); - chain.getResolvedAttributes().insert((*ictx)->getResolvedAttributes().begin(), (*ictx)->getResolvedAttributes().end()); + chain.getResolvedAttributes().insert(chain.getResolvedAttributes().end(), (*ictx)->getResolvedAttributes().begin(), (*ictx)->getResolvedAttributes().end()); (*ictx)->getResolvedAttributes().clear(); chain.getResolvedAssertions().insert(chain.getResolvedAssertions().end(), (*ictx)->getResolvedAssertions().begin(), (*ictx)->getResolvedAssertions().end()); (*ictx)->getResolvedAssertions().clear(); diff --git a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp index f0debc4..825af50 100644 --- a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp +++ b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp @@ -78,7 +78,7 @@ namespace shibsp { const XMLCh* authncontext_class=NULL, const XMLCh* authncontext_decl=NULL, const vector* tokens=NULL, - const multimap* attributes=NULL + const vector* attributes=NULL ) : m_query(true), m_app(application), m_session(NULL), m_metadata(NULL), m_entity(issuer), m_protocol(protocol), m_nameid(nameid), m_class(authncontext_class), m_decl(authncontext_decl) { @@ -106,7 +106,7 @@ namespace shibsp { } if (m_metadata) m_metadata->unlock(); - for_each(m_attributes.begin(), m_attributes.end(), cleanup_pair()); + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); for_each(m_assertions.begin(), m_assertions.end(), xmltooling::cleanup()); } @@ -144,7 +144,7 @@ namespace shibsp { const Session* getSession() const { return m_session; } - multimap& getResolvedAttributes() { + vector& getResolvedAttributes() { return m_attributes; } vector& getResolvedAssertions() { @@ -161,7 +161,7 @@ namespace shibsp { const NameID* m_nameid; const XMLCh* m_class; const XMLCh* m_decl; - multimap m_attributes; + vector m_attributes; vector m_assertions; }; @@ -185,7 +185,7 @@ namespace shibsp { const XMLCh* authncontext_class=NULL, const XMLCh* authncontext_decl=NULL, const vector* tokens=NULL, - const multimap* attributes=NULL + const vector* attributes=NULL ) const { return new QueryContext(application,issuer,protocol,nameid,authncontext_class,authncontext_decl,tokens,attributes); } @@ -364,7 +364,7 @@ bool QueryResolver::SAML1Query(QueryContext& ctx) const } catch (exception& ex) { m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what()); - for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), cleanup_pair()); + for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup()); ctx.getResolvedAttributes().clear(); } @@ -481,7 +481,7 @@ bool QueryResolver::SAML2Query(QueryContext& ctx) const } catch (exception& ex) { m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what()); - for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), cleanup_pair()); + for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup()); ctx.getResolvedAttributes().clear(); } diff --git a/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp index 44bf5e4..e0942e2 100644 --- a/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp +++ b/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp @@ -67,16 +67,16 @@ namespace shibsp { } void extractAttributes( - const Application& application, const char* assertingParty, const NameIdentifier& nameid, multimap& attributes + const Application& application, const char* assertingParty, const NameIdentifier& nameid, vector& attributes ) const; void extractAttributes( - const Application& application, const char* assertingParty, const NameID& nameid, multimap& attributes + const Application& application, const char* assertingParty, const NameID& nameid, vector& attributes ) const; void extractAttributes( - const Application& application, const char* assertingParty, const saml1::Attribute& attr, multimap& attributes + const Application& application, const char* assertingParty, const saml1::Attribute& attr, vector& attributes ) const; void extractAttributes( - const Application& application, const char* assertingParty, const saml2::Attribute& attr, multimap& attributes + const Application& application, const char* assertingParty, const saml2::Attribute& attr, vector& attributes ) const; void getAttributeIds(vector& attributes) const { @@ -106,7 +106,7 @@ namespace shibsp { } void extractAttributes( - const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, multimap& attributes + const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector& attributes ) const; void getAttributeIds(std::vector& attributes) const { @@ -231,7 +231,7 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log) : m_log(l } void XMLExtractorImpl::extractAttributes( - const Application& application, const char* assertingParty, const NameIdentifier& nameid, multimap& attributes + const Application& application, const char* assertingParty, const NameIdentifier& nameid, vector& attributes ) const { #ifdef HAVE_GOOD_STL @@ -251,12 +251,12 @@ void XMLExtractorImpl::extractAttributes( #endif Attribute* a = rule->second.first->decode(rule->second.second.c_str(), &nameid, assertingParty, application.getString("entityID").second); if (a) - attributes.insert(make_pair(rule->second.second, a)); + attributes.push_back(a); } } void XMLExtractorImpl::extractAttributes( - const Application& application, const char* assertingParty, const NameID& nameid, multimap& attributes + const Application& application, const char* assertingParty, const NameID& nameid, vector& attributes ) const { #ifdef HAVE_GOOD_STL @@ -276,12 +276,12 @@ void XMLExtractorImpl::extractAttributes( #endif Attribute* a = rule->second.first->decode(rule->second.second.c_str(), &nameid, assertingParty, application.getString("entityID").second); if (a) - attributes.insert(make_pair(rule->second.second, a)); + attributes.push_back(a); } } void XMLExtractorImpl::extractAttributes( - const Application& application, const char* assertingParty, const saml1::Attribute& attr, multimap& attributes + const Application& application, const char* assertingParty, const saml1::Attribute& attr, vector& attributes ) const { #ifdef HAVE_GOOD_STL @@ -305,12 +305,12 @@ void XMLExtractorImpl::extractAttributes( #endif Attribute* a = rule->second.first->decode(rule->second.second.c_str(), &attr, assertingParty, application.getString("entityID").second); if (a) - attributes.insert(make_pair(rule->second.second, a)); + attributes.push_back(a); } } void XMLExtractorImpl::extractAttributes( - const Application& application, const char* assertingParty, const saml2::Attribute& attr, multimap& attributes + const Application& application, const char* assertingParty, const saml2::Attribute& attr, vector& attributes ) const { #ifdef HAVE_GOOD_STL @@ -336,12 +336,12 @@ void XMLExtractorImpl::extractAttributes( #endif Attribute* a = rule->second.first->decode(rule->second.second.c_str(), &attr, assertingParty, application.getString("entityID").second); if (a) - attributes.insert(make_pair(rule->second.second, a)); + attributes.push_back(a); } } void XMLExtractor::extractAttributes( - const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, multimap& attributes + const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector& attributes ) const { if (!m_impl) diff --git a/shibsp/handler/AssertionConsumerService.h b/shibsp/handler/AssertionConsumerService.h index bbedd6c..c933c89 100644 --- a/shibsp/handler/AssertionConsumerService.h +++ b/shibsp/handler/AssertionConsumerService.h @@ -106,7 +106,7 @@ namespace shibsp { const XMLCh* authncontext_class=NULL, const XMLCh* authncontext_decl=NULL, const std::vector* tokens=NULL, - const std::multimap* attributes=NULL + const std::vector* attributes=NULL ) const; #endif diff --git a/shibsp/handler/impl/AssertionConsumerService.cpp b/shibsp/handler/impl/AssertionConsumerService.cpp index c8037b7..8d7c0fe 100644 --- a/shibsp/handler/impl/AssertionConsumerService.cpp +++ b/shibsp/handler/impl/AssertionConsumerService.cpp @@ -249,7 +249,7 @@ ResolutionContext* AssertionConsumerService::resolveAttributes( const XMLCh* authncontext_class, const XMLCh* authncontext_decl, const vector* tokens, - const multimap* attributes + const vector* attributes ) const { try { diff --git a/shibsp/handler/impl/SAML1Consumer.cpp b/shibsp/handler/impl/SAML1Consumer.cpp index 8b44d5c..a4e5303 100644 --- a/shibsp/handler/impl/SAML1Consumer.cpp +++ b/shibsp/handler/impl/SAML1Consumer.cpp @@ -206,7 +206,7 @@ string SAML1Consumer::implementProtocol( // We've successfully "accepted" at least one SSO token, along with any additional valid tokens. // To complete processing, we need to extract and resolve attributes and then create the session. - multimap resolvedAttributes; + vector resolvedAttributes; AttributeExtractor* extractor = application.getAttributeExtractor(); if (extractor) { m_log.debug("extracting pushed attributes..."); @@ -238,7 +238,7 @@ string SAML1Consumer::implementProtocol( catch (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(), cleanup_pair()); + for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup()); resolvedAttributes.clear(); } } @@ -273,7 +273,7 @@ string SAML1Consumer::implementProtocol( tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end()); // Copy over new attributes, and transfer ownership. - resolvedAttributes.insert(ctx->getResolvedAttributes().begin(), ctx->getResolvedAttributes().end()); + resolvedAttributes.insert(resolvedAttributes.end(), ctx->getResolvedAttributes().begin(), ctx->getResolvedAttributes().end()); ctx->getResolvedAttributes().clear(); } @@ -296,11 +296,11 @@ string SAML1Consumer::implementProtocol( &tokens, &resolvedAttributes ); - for_each(resolvedAttributes.begin(), resolvedAttributes.end(), cleanup_pair()); + for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup()); return key; } catch (exception&) { - for_each(resolvedAttributes.begin(), resolvedAttributes.end(), cleanup_pair()); + for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup()); throw; } } diff --git a/shibsp/handler/impl/SAML2Consumer.cpp b/shibsp/handler/impl/SAML2Consumer.cpp index 2bae0f5..a82b3be 100644 --- a/shibsp/handler/impl/SAML2Consumer.cpp +++ b/shibsp/handler/impl/SAML2Consumer.cpp @@ -335,7 +335,7 @@ string SAML2Consumer::implementProtocol( else sessionExp = min(sessionExp, now + lifetime.second); // Use the lowest. - multimap resolvedAttributes; + vector resolvedAttributes; AttributeExtractor* extractor = application.getAttributeExtractor(); if (extractor) { m_log.debug("extracting pushed attributes..."); @@ -374,7 +374,7 @@ string SAML2Consumer::implementProtocol( catch (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(), cleanup_pair()); + for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup()); resolvedAttributes.clear(); } } @@ -400,7 +400,7 @@ string SAML2Consumer::implementProtocol( tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end()); // Copy over new attributes, and transfer ownership. - resolvedAttributes.insert(ctx->getResolvedAttributes().begin(), ctx->getResolvedAttributes().end()); + resolvedAttributes.insert(resolvedAttributes.end(), ctx->getResolvedAttributes().begin(), ctx->getResolvedAttributes().end()); ctx->getResolvedAttributes().clear(); } @@ -425,14 +425,14 @@ string SAML2Consumer::implementProtocol( if (ownedName) delete ssoName; for_each(ownedtokens.begin(), ownedtokens.end(), xmltooling::cleanup()); - for_each(resolvedAttributes.begin(), resolvedAttributes.end(), cleanup_pair()); + for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup()); return key; } catch (exception&) { if (ownedName) delete ssoName; for_each(ownedtokens.begin(), ownedtokens.end(), xmltooling::cleanup()); - for_each(resolvedAttributes.begin(), resolvedAttributes.end(), cleanup_pair()); + for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup()); throw; } } diff --git a/shibsp/impl/RemotedSessionCache.cpp b/shibsp/impl/RemotedSessionCache.cpp index 04364e0..e7bdbc9 100644 --- a/shibsp/impl/RemotedSessionCache.cpp +++ b/shibsp/impl/RemotedSessionCache.cpp @@ -61,7 +61,7 @@ namespace shibsp { ~RemotedSession() { delete m_lock; m_obj.destroy(); - for_each(m_attributes.begin(), m_attributes.end(), cleanup_pair()); + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); } Lockable* lock() { @@ -99,11 +99,16 @@ namespace shibsp { const char* getAuthnContextDeclRef() const { return m_obj["authncontext_decl"].string(); } - const multimap& getAttributes() const { + const vector& getAttributes() const { if (m_attributes.empty()) unmarshallAttributes(); return m_attributes; } + const multimap& getIndexedAttributes() const { + if (m_attributes.empty()) + unmarshallAttributes(); + return m_attributeIndex; + } const vector& getAssertionIDs() const { if (m_ids.empty()) { DDF ids = m_obj["assertions"]; @@ -125,7 +130,8 @@ namespace shibsp { int m_version; mutable DDF m_obj; - mutable multimap m_attributes; + mutable vector m_attributes; + mutable multimap m_attributeIndex; mutable vector m_ids; time_t m_expires,m_lastAccess; RemotedCache* m_cache; @@ -170,7 +176,8 @@ void RemotedSession::unmarshallAttributes() const while (!attr.isnull()) { try { attribute = Attribute::unmarshall(attr); - m_attributes.insert(make_pair(attribute->getId(),attribute)); + m_attributes.push_back(attribute); + m_attributeIndex.insert(make_pair(attribute->getId(),attribute)); if (m_cache->m_log.isDebugEnabled()) m_cache->m_log.debug("unmarshalled attribute (ID: %s) with %d value%s", attribute->getId(), attr.first().integer(), attr.first().integer()!=1 ? "s" : ""); @@ -237,8 +244,9 @@ void RemotedSession::validate(const Application& application, const char* client if (out.isstruct()) { // We got an updated record back. m_ids.clear(); - for_each(m_attributes.begin(), m_attributes.end(), cleanup_const_pair()); + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); m_attributes.clear(); + m_attributeIndex.clear(); m_obj.destroy(); m_obj = out; } diff --git a/shibsp/impl/StorageServiceSessionCache.cpp b/shibsp/impl/StorageServiceSessionCache.cpp index 38d5989..c1e7256 100644 --- a/shibsp/impl/StorageServiceSessionCache.cpp +++ b/shibsp/impl/StorageServiceSessionCache.cpp @@ -106,11 +106,16 @@ namespace shibsp { const char* getAuthnContextDeclRef() const { return m_obj["authncontext_decl"].string(); } - const multimap& getAttributes() const { + const vector& getAttributes() const { if (m_attributes.empty()) unmarshallAttributes(); return m_attributes; } + const multimap& getIndexedAttributes() const { + if (m_attributes.empty()) + unmarshallAttributes(); + return m_attributeIndex; + } const vector& getAssertionIDs() const { if (m_ids.empty()) { DDF ids = m_obj["assertions"]; @@ -132,7 +137,8 @@ namespace shibsp { DDF m_obj; saml2::NameID* m_nameid; - mutable multimap m_attributes; + mutable vector m_attributes; + mutable multimap m_attributeIndex; mutable vector m_ids; mutable map m_tokens; SSCache* m_cache; @@ -158,7 +164,7 @@ namespace shibsp { const XMLCh* authncontext_class=NULL, const XMLCh* authncontext_decl=NULL, const vector* tokens=NULL, - const multimap* attributes=NULL + const vector* attributes=NULL ); Session* find(const char* key, const Application& application, const char* client_addr=NULL, time_t* timeout=NULL); void remove(const char* key, const Application& application); @@ -200,7 +206,7 @@ StoredSession::~StoredSession() { m_obj.destroy(); delete m_nameid; - for_each(m_attributes.begin(), m_attributes.end(), cleanup_pair()); + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); for_each(m_tokens.begin(), m_tokens.end(), cleanup_pair()); } @@ -212,7 +218,8 @@ void StoredSession::unmarshallAttributes() const while (!attr.isnull()) { try { attribute = Attribute::unmarshall(attr); - m_attributes.insert(make_pair(attribute->getId(), attribute)); + m_attributes.push_back(attribute); + m_attributeIndex.insert(make_pair(attribute->getId(), attribute)); if (m_cache->m_log.isDebugEnabled()) m_cache->m_log.debug("unmarshalled attribute (ID: %s) with %d value%s", attribute->getId(), attr.first().integer(), attr.first().integer()!=1 ? "s" : ""); @@ -289,8 +296,9 @@ void StoredSession::addAttributes(const vector& attributes) in >> newobj; m_ids.clear(); - for_each(m_attributes.begin(), m_attributes.end(), cleanup_const_pair()); + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); m_attributes.clear(); + m_attributeIndex.clear(); newobj["version"].integer(ver); m_obj.destroy(); m_obj = newobj; @@ -412,8 +420,9 @@ void StoredSession::addAssertion(Assertion* assertion) in >> newobj; m_ids.clear(); - for_each(m_attributes.begin(), m_attributes.end(), cleanup_const_pair()); + for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup()); m_attributes.clear(); + m_attributeIndex.clear(); newobj["version"].integer(ver); m_obj.destroy(); m_obj = newobj; @@ -534,7 +543,7 @@ string SSCache::insert( const XMLCh* authncontext_class, const XMLCh* authncontext_decl, const vector* tokens, - const multimap* attributes + const vector* attributes ) { #ifdef _DEBUG @@ -634,8 +643,8 @@ string SSCache::insert( if (attributes) { DDF attr; DDF attrlist = obj.addmember("attributes").list(); - for (multimap::const_iterator a=attributes->begin(); a!=attributes->end(); ++a) { - attr = a->second->marshall(); + for (vector::const_iterator a=attributes->begin(); a!=attributes->end(); ++a) { + attr = (*a)->marshall(); attrlist.add(attr); } } @@ -697,8 +706,8 @@ string SSCache::insert( ") for (applicationId: " << application.getId() << ") {"; - for (multimap::const_iterator a=attributes->begin(); a!=attributes->end(); ++a) - xlog->log.infoStream() << "\t" << a->second->getId() << " (" << a->second->valueCount() << " values)"; + for (vector::const_iterator a=attributes->begin(); a!=attributes->end(); ++a) + xlog->log.infoStream() << "\t" << (*a)->getId() << " (" << (*a)->valueCount() << " values)"; xlog->log.info("}"); } diff --git a/shibsp/impl/XMLAccessControl.cpp b/shibsp/impl/XMLAccessControl.cpp index 7f51df8..9f223c9 100644 --- a/shibsp/impl/XMLAccessControl.cpp +++ b/shibsp/impl/XMLAccessControl.cpp @@ -159,8 +159,8 @@ bool Rule::authorized(const SPRequest& request, const Session* session) const } // Find the attribute(s) matching the require rule. - pair::const_iterator, multimap::const_iterator> attrs = - session->getAttributes().equal_range(m_alias); + pair::const_iterator, multimap::const_iterator> attrs = + session->getIndexedAttributes().equal_range(m_alias); if (attrs.first == attrs.second) { request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session"); return false; -- 2.1.4