From: cantor Date: Thu, 8 Nov 2007 06:45:22 +0000 (+0000) Subject: Collapse entity/role lookup in metadata API. X-Git-Tag: 2.4~677 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fsp.git;a=commitdiff_plain;h=5c1c763c8ed7ab2b8a4dc4fe7f9a0946295a5da3 Collapse entity/role lookup in metadata API. git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2591 cb58f699-b61c-0410-a6fe-9272a202ed29 --- diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp index 9b4d452..3c0fdff 100644 --- a/adfs/adfs.cpp +++ b/adfs/adfs.cpp @@ -437,18 +437,19 @@ pair ADFSSessionInitiator::doRequest( // Use metadata to invoke the SSO service directly. MetadataProvider* m=app.getMetadataProvider(); Locker locker(m); - const EntityDescriptor* entity=m->getEntityDescriptor(entityID); - if (!entity) { + MetadataProvider::Criteria mc(entityID, &IDPSSODescriptor::ELEMENT_QNAME, m_binding.get()); + pair entity=m->getEntityDescriptor(mc); + if (!entity.first) { m_log.error("unable to locate metadata for provider (%s)", entityID); - throw MetadataException("Unable to locate metadata for identity provider ($entityID)", - namedparams(1, "entityID", entityID)); + throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID)); } - const IDPSSODescriptor* role=find_if(entity->getIDPSSODescriptors(), isValidForProtocol(m_binding.get())); - if (!role) { + else if (!entity.second) { m_log.error("unable to locate ADFS-aware identity provider role for provider (%s)", entityID); return make_pair(false,0); } - const EndpointType* ep=EndpointManager(role->getSingleSignOnServices()).getByBinding(m_binding.get()); + const EndpointType* ep = EndpointManager( + dynamic_cast(entity.second)->getSingleSignOnServices() + ).getByBinding(m_binding.get()); if (!ep) { m_log.error("unable to locate compatible SSO service for provider (%s)", entityID); return make_pair(false,0); @@ -727,23 +728,18 @@ pair ADFSLogoutInitiator::doRequest( throw ConfigurationException("Missing entityID parameter."); // With a session in hand, we can create a request message, if we can find a compatible endpoint. - Locker metadataLocker(application.getMetadataProvider()); - const EntityDescriptor* entity = application.getMetadataProvider()->getEntityDescriptor(entityID); - if (!entity) { - throw MetadataException( - "Unable to locate metadata for identity provider ($entityID)", - namedparams(1, "entityID", entityID) - ); - } - const IDPSSODescriptor* role = find_if(entity->getIDPSSODescriptors(), isValidForProtocol(m_binding.get())); - if (!role) { - throw MetadataException( - "Unable to locate ADFS IdP role for identity provider ($entityID).", - namedparams(1, "entityID", entityID) - ); - } - - const EndpointType* ep = EndpointManager(role->getSingleLogoutServices()).getByBinding(m_binding.get()); + MetadataProvider* m=application.getMetadataProvider(); + Locker locker(m); + MetadataProvider::Criteria mc(entityID, &IDPSSODescriptor::ELEMENT_QNAME, m_binding.get()); + pair entity=m->getEntityDescriptor(mc); + if (!entity.first) + throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID)); + else if (!entity.second) + throw MetadataException("Unable to locate ADFS IdP role for identity provider ($entityID).", namedparams(1, "entityID", entityID)); + + const EndpointType* ep = EndpointManager( + dynamic_cast(entity.second)->getSingleLogoutServices() + ).getByBinding(m_binding.get()); if (!ep) { throw MetadataException( "Unable to locate ADFS single logout service for identity provider ($entityID).", diff --git a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp index bf8df1b..e6ccb70 100644 --- a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp +++ b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp @@ -121,10 +121,10 @@ namespace shibsp { if (m_entity) return m_entity; if (m_session && m_session->getEntityID()) { - m_metadata = m_app.getMetadataProvider(); + m_metadata = m_app.getMetadataProvider(false); if (m_metadata) { m_metadata->lock(); - return m_entity = m_metadata->getEntityDescriptor(m_session->getEntityID()); + return m_entity = m_metadata->getEntityDescriptor(MetadataProvider::Criteria(m_session->getEntityID())).first; } } return NULL; diff --git a/shibsp/handler/impl/AssertionConsumerService.cpp b/shibsp/handler/impl/AssertionConsumerService.cpp index 169636d..57dacb3 100644 --- a/shibsp/handler/impl/AssertionConsumerService.cpp +++ b/shibsp/handler/impl/AssertionConsumerService.cpp @@ -40,10 +40,11 @@ # include # include using namespace samlconstants; +using opensaml::saml2md::MetadataProvider; +using opensaml::saml2md::RoleDescriptor; using opensaml::saml2md::EntityDescriptor; using opensaml::saml2md::IDPSSODescriptor; using opensaml::saml2md::SPSSODescriptor; -using opensaml::saml2md::isValidForProtocol; #else # include "lite/CommonDomainCookie.h" #endif @@ -425,19 +426,18 @@ void AssertionConsumerService::extractMessageDetails(const Assertion& assertion, if (policy.getIssuer() && !policy.getIssuerMetadata() && policy.getMetadataProvider()) { m_log.debug("searching metadata for assertion issuer..."); - const EntityDescriptor* entity = policy.getMetadataProvider()->getEntityDescriptor(policy.getIssuer()->getName()); - if (entity) { - m_log.debug("matched assertion issuer against metadata, searching for applicable role..."); - const IDPSSODescriptor* idp=find_if(entity->getIDPSSODescriptors(), isValidForProtocol(protocol)); - if (idp) - policy.setIssuerMetadata(idp); - else if (m_log.isWarnEnabled()) - m_log.warn("unable to find compatible IdP role in metadata"); - } - else if (m_log.isWarnEnabled()) { + MetadataProvider::Criteria mc(policy.getIssuer()->getName(), &IDPSSODescriptor::ELEMENT_QNAME, protocol); + pair entity = policy.getMetadataProvider()->getEntityDescriptor(mc); + if (!entity.first) { auto_ptr_char iname(policy.getIssuer()->getName()); m_log.warn("no metadata found, can't establish identity of issuer (%s)", iname.get()); } + else if (!entity.second) { + m_log.warn("unable to find compatible IdP role in metadata"); + } + else { + policy.setIssuerMetadata(entity.second); + } } } diff --git a/shibsp/handler/impl/SAML2Logout.cpp b/shibsp/handler/impl/SAML2Logout.cpp index 9f4108a..23b5421 100644 --- a/shibsp/handler/impl/SAML2Logout.cpp +++ b/shibsp/handler/impl/SAML2Logout.cpp @@ -293,15 +293,16 @@ pair SAML2Logout::doRequest( } // We need metadata to issue a response. - Locker metadataLocker(application.getMetadataProvider()); - const EntityDescriptor* entity = application.getMetadataProvider()->getEntityDescriptor(request.getParameter("entityID")); - if (!entity) { + MetadataProvider* m = application.getMetadataProvider(); + Locker metadataLocker(m); + MetadataProvider::Criteria mc(request.getParameter("entityID"), &IDPSSODescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS); + pair entity = m->getEntityDescriptor(mc); + if (!entity.first) { throw MetadataException( "Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", request.getParameter("entityID")) ); } - const IDPSSODescriptor* idp = find_if(entity->getIDPSSODescriptors(), isValidForProtocol(samlconstants::SAML20P_NS)); - if (!idp) { + else if (!entity.second) { throw MetadataException( "Unable to locate SAML 2.0 IdP role for identity provider ($entityID).", namedparams(1, "entityID", request.getParameter("entityID")) @@ -312,7 +313,7 @@ pair SAML2Logout::doRequest( if (worked1 && worked2) { // Successful LogoutResponse. Has to be front-channel or we couldn't be here. return sendResponse( - reqid.get(), StatusCode::SUCCESS, NULL, NULL, request.getParameter("RelayState"), idp, application, response, true + reqid.get(), StatusCode::SUCCESS, NULL, NULL, request.getParameter("RelayState"), entity.second, application, response, true ); } @@ -320,7 +321,7 @@ pair SAML2Logout::doRequest( reqid.get(), StatusCode::RESPONDER, NULL, "Unable to fully destroy principal's session.", request.getParameter("RelayState"), - idp, + entity.second, application, response, true diff --git a/shibsp/handler/impl/SAML2LogoutInitiator.cpp b/shibsp/handler/impl/SAML2LogoutInitiator.cpp index eddd725..06edde9 100644 --- a/shibsp/handler/impl/SAML2LogoutInitiator.cpp +++ b/shibsp/handler/impl/SAML2LogoutInitiator.cpp @@ -83,7 +83,7 @@ namespace shibsp { string m_appId; #ifndef SHIBSP_LITE LogoutRequest* buildRequest( - const Application& application, const Session& session, const IDPSSODescriptor& role, const MessageEncoder* encoder=NULL + const Application& application, const Session& session, const RoleDescriptor& role, const MessageEncoder* encoder=NULL ) const; XMLCh* m_outgoing; @@ -287,22 +287,22 @@ pair SAML2LogoutInitiator::doRequest( pair ret = make_pair(false,0); try { // With a session in hand, we can create a LogoutRequest message, if we can find a compatible endpoint. - Locker metadataLocker(application.getMetadataProvider()); - const EntityDescriptor* entity = application.getMetadataProvider()->getEntityDescriptor(session->getEntityID()); - if (!entity) { + MetadataProvider* m = application.getMetadataProvider(); + Locker metadataLocker(m); + MetadataProvider::Criteria mc(session->getEntityID(), &IDPSSODescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS); + pair entity = m->getEntityDescriptor(mc); + if (!entity.first) { throw MetadataException( - "Unable to locate metadata for identity provider ($entityID)", - namedparams(1, "entityID", session->getEntityID()) + "Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", session->getEntityID()) ); } - const IDPSSODescriptor* role = find_if(entity->getIDPSSODescriptors(), isValidForProtocol(samlconstants::SAML20P_NS)); - if (!role) { + else if (!entity.second) { throw MetadataException( - "Unable to locate SAML 2.0 IdP role for identity provider ($entityID).", - namedparams(1, "entityID", session->getEntityID()) + "Unable to locate SAML 2.0 IdP role for identity provider ($entityID).", namedparams(1, "entityID", session->getEntityID()) ); } + const IDPSSODescriptor* role = dynamic_cast(entity.second); const EndpointType* ep=NULL; const MessageEncoder* encoder=NULL; vector::const_iterator b; @@ -396,7 +396,7 @@ pair SAML2LogoutInitiator::doRequest( #ifndef SHIBSP_LITE LogoutRequest* SAML2LogoutInitiator::buildRequest( - const Application& application, const Session& session, const IDPSSODescriptor& role, const MessageEncoder* encoder + const Application& application, const Session& session, const RoleDescriptor& role, const MessageEncoder* encoder ) const { auto_ptr msg(LogoutRequestBuilder::buildLogoutRequest()); diff --git a/shibsp/handler/impl/SAML2SessionInitiator.cpp b/shibsp/handler/impl/SAML2SessionInitiator.cpp index 1e1e0e2..2832221 100644 --- a/shibsp/handler/impl/SAML2SessionInitiator.cpp +++ b/shibsp/handler/impl/SAML2SessionInitiator.cpp @@ -403,19 +403,19 @@ pair SAML2SessionInitiator::doRequest( // Use metadata to locate the IdP's SSO service. MetadataProvider* m=app.getMetadataProvider(); Locker locker(m); - const EntityDescriptor* entity=m->getEntityDescriptor(entityID); - if (!entity) { + MetadataProvider::Criteria mc(entityID, &IDPSSODescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS); + pair entity=m->getEntityDescriptor(mc); + if (!entity.first) { m_log.error("unable to locate metadata for provider (%s)", entityID); - throw MetadataException("Unable to locate metadata for identity provider ($entityID)", - namedparams(1, "entityID", entityID)); + throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID)); } - const IDPSSODescriptor* role=find_if(entity->getIDPSSODescriptors(), isValidForProtocol(samlconstants::SAML20P_NS)); - if (!role) { + else if (!entity.second) { m_log.error("unable to locate SAML 2.0 identity provider role for provider (%s)", entityID); return make_pair(false,0); } // Loop over the supportable outgoing bindings. + const IDPSSODescriptor* role = dynamic_cast(entity.second); const EndpointType* ep=NULL; const MessageEncoder* encoder=NULL; vector::const_iterator b; @@ -486,9 +486,7 @@ pair SAML2SessionInitiator::doRequest( auto_ptr_char dest(ep->getLocation()); - long ret = sendMessage( - *encoder, req.get(), relayState.c_str(), dest.get(), role, app, httpResponse, role->WantAuthnRequestsSigned() - ); + long ret = sendMessage(*encoder, req.get(), relayState.c_str(), dest.get(), role, app, httpResponse, role->WantAuthnRequestsSigned()); req.release(); // freed by encoder return make_pair(true,ret); #else diff --git a/shibsp/handler/impl/Shib1SessionInitiator.cpp b/shibsp/handler/impl/Shib1SessionInitiator.cpp index a7155b8..f370e77 100644 --- a/shibsp/handler/impl/Shib1SessionInitiator.cpp +++ b/shibsp/handler/impl/Shib1SessionInitiator.cpp @@ -224,20 +224,19 @@ pair Shib1SessionInitiator::doRequest( // Use metadata to invoke the SSO service directly. MetadataProvider* m=app.getMetadataProvider(); Locker locker(m); - const EntityDescriptor* entity=m->getEntityDescriptor(entityID); - if (!entity) { + MetadataProvider::Criteria mc(entityID, &IDPSSODescriptor::ELEMENT_QNAME, shibspconstants::SHIB1_PROTOCOL_ENUM); + pair entity = m->getEntityDescriptor(mc); + if (!entity.first) { m_log.error("unable to locate metadata for provider (%s)", entityID); - throw MetadataException("Unable to locate metadata for identity provider ($entityID)", - namedparams(1, "entityID", entityID)); + throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID)); } - const IDPSSODescriptor* role=find_if(entity->getIDPSSODescriptors(), isValidForProtocol(shibspconstants::SHIB1_PROTOCOL_ENUM)); - if (!role) { + else if (!entity.second) { m_log.error("unable to locate Shibboleth-aware identity provider role for provider (%s)", entityID); return make_pair(false,0); } - const EndpointType* ep=EndpointManager(role->getSingleSignOnServices()).getByBinding( - shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI - ); + const EndpointType* ep=EndpointManager( + dynamic_cast(entity.second)->getSingleSignOnServices() + ).getByBinding(shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI); if (!ep) { m_log.error("unable to locate compatible SSO service for provider (%s)", entityID); return make_pair(false,0); diff --git a/shibsp/handler/impl/StatusHandler.cpp b/shibsp/handler/impl/StatusHandler.cpp index 0b8215a..8862f58 100644 --- a/shibsp/handler/impl/StatusHandler.cpp +++ b/shibsp/handler/impl/StatusHandler.cpp @@ -399,8 +399,9 @@ pair StatusHandler::processMessage( const PropertySet* relyingParty=NULL; param=httpRequest.getParameter("entityID"); if (param) { - Locker mlock(application.getMetadataProvider()); - relyingParty = application.getRelyingParty(application.getMetadataProvider()->getEntityDescriptor(param)); + MetadataProvider* m = application.getMetadataProvider(); + Locker mlock(m); + relyingParty = application.getRelyingParty(m->getEntityDescriptor(MetadataProvider::Criteria(param)).first); } if (!relyingParty) relyingParty = application.getRelyingParty(NULL); diff --git a/shibsp/impl/StorageServiceSessionCache.cpp b/shibsp/impl/StorageServiceSessionCache.cpp index 8a7c0d1..5aa9a7e 100644 --- a/shibsp/impl/StorageServiceSessionCache.cpp +++ b/shibsp/impl/StorageServiceSessionCache.cpp @@ -769,13 +769,16 @@ Session* SSCache::find(const char* key, const Application& application, const ch "Your IP address ($1) does not match the address recorded at the time the session was established.", params(1,client_addr) ); - string eid(obj["entity_id"].string()); - obj.destroy(); - if (eid.empty()) + const char* eid = obj["entity_id"].string(); + if (!eid) { + obj.destroy(); throw ex; + } + string eid2(eid); + obj.destroy(); MetadataProvider* m=application.getMetadataProvider(); Locker locker(m); - annotateException(&ex,m->getEntityDescriptor(eid.c_str(),false)); // throws it + annotateException(&ex,m->getEntityDescriptor(MetadataProvider::Criteria(eid2.c_str(),NULL,NULL,false)).first); // throws it } } @@ -786,13 +789,16 @@ Session* SSCache::find(const char* key, const Application& application, const ch m_log.info("session timed out (ID: %s)", key); remove(key, application); RetryableProfileException ex("Your session has expired, and you must re-authenticate."); - string eid(obj["entity_id"].string()); - obj.destroy(); - if (eid.empty()) + const char* eid = obj["entity_id"].string(); + if (!eid) { + obj.destroy(); throw ex; + } + string eid2(eid); + obj.destroy(); MetadataProvider* m=application.getMetadataProvider(); Locker locker(m); - annotateException(&ex,m->getEntityDescriptor(eid.c_str(),false)); // throws it + annotateException(&ex,m->getEntityDescriptor(MetadataProvider::Criteria(eid2.c_str(),NULL,NULL,false)).first); // throws it } auto_ptr_XMLCh exp(obj["expires"].string()); @@ -803,13 +809,16 @@ Session* SSCache::find(const char* key, const Application& application, const ch m_log.info("session expired (ID: %s)", key); remove(key, application); RetryableProfileException ex("Your session has expired, and you must re-authenticate."); - string eid(obj["entity_id"].string()); - obj.destroy(); - if (eid.empty()) + const char* eid = obj["entity_id"].string(); + if (!eid) { + obj.destroy(); throw ex; + } + string eid2(eid); + obj.destroy(); MetadataProvider* m=application.getMetadataProvider(); Locker locker(m); - annotateException(&ex,m->getEntityDescriptor(eid.c_str(),false)); // throws it + annotateException(&ex,m->getEntityDescriptor(MetadataProvider::Criteria(eid2.c_str(),NULL,NULL,false)).first); // throws it } } diff --git a/util/mdquery.cpp b/util/mdquery.cpp index b11aa1d..00e1e49 100644 --- a/util/mdquery.cpp +++ b/util/mdquery.cpp @@ -153,26 +153,25 @@ int main(int argc,char* argv[]) } app->getMetadataProvider()->lock(); - const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(entityID, strict); - if (entity) { - if (rname) { - const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS; - auto_ptr_XMLCh n(rname); - QName q(ns, n.get()); - const RoleDescriptor* role = entity->getRoleDescriptor(q, protocol); - if (role) { - XMLHelper::serialize(role->marshall(), cout, true); - } - else { - log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID); - } - } - else { - XMLHelper::serialize(entity->marshall(), cout, true); - } + MetadataProvider::Criteria mc(entityID, NULL, NULL, strict); + if (rname) { + const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS; + auto_ptr_XMLCh n(rname); + QName q(ns, n.get()); + mc.role = &q; + mc.protocol = protocol; + const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second; + if (role) + XMLHelper::serialize(role->marshall(), cout, true); + else + log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID); } else { - log.error("no metadata found for (%s)", entityID); + const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first; + if (entity) + XMLHelper::serialize(entity->marshall(), cout, true); + else + log.error("no metadata found for (%s)", entityID); } app->getMetadataProvider()->unlock(); diff --git a/util/resolvertest.cpp b/util/resolvertest.cpp index 7430372..d818e80 100644 --- a/util/resolvertest.cpp +++ b/util/resolvertest.cpp @@ -215,8 +215,9 @@ int main(int argc,char* argv[]) MetadataProvider* m=app->getMetadataProvider(); xmltooling::Locker mlocker(m); - const EntityDescriptor* site=m->getEntityDescriptor(issuer.get()); - if (!site) + MetadataProvider::Criteria mc(i_param, &IDPSSODescriptor::ELEMENT_QNAME, protocol); + pair site=m->getEntityDescriptor(mc); + if (!site.first) throw MetadataException("Unable to locate metadata for IdP ($1).", params(1,i_param)); // Build NameID(s). @@ -233,9 +234,7 @@ int main(int argc,char* argv[]) ResolverTest rt(NULL, a_param); try { - ctx = rt.resolveAttributes( - *app, find_if(site->getIDPSSODescriptors(), isValidForProtocol(protocol)), protocol, v1name, v2name.get(), NULL, NULL, NULL - ); + ctx = rt.resolveAttributes(*app, site.second, protocol, v1name, v2name.get(), NULL, NULL, NULL); } catch (...) { delete v1name; @@ -287,8 +286,9 @@ int main(int argc,char* argv[]) MetadataProvider* m=app->getMetadataProvider(); xmltooling::Locker mlocker(m); - const EntityDescriptor* site=m->getEntityDescriptor(issuer); - if (!site) { + MetadataProvider::Criteria mc(issuer, &IDPSSODescriptor::ELEMENT_QNAME, protocol); + pair site=m->getEntityDescriptor(mc); + if (!site.first) { auto_ptr_char temp(issuer); throw MetadataException("Unable to locate metadata for IdP ($1).", params(1,temp.get())); } @@ -296,9 +296,7 @@ int main(int argc,char* argv[]) vector tokens(1, dynamic_cast(token.get())); ResolverTest rt(NULL, a_param); try { - ctx = rt.resolveAttributes( - *app, find_if(site->getIDPSSODescriptors(), isValidForProtocol(protocol)), protocol, v1name, v2name, NULL, NULL, &tokens - ); + ctx = rt.resolveAttributes(*app, site.second, protocol, v1name, v2name, NULL, NULL, &tokens); } catch (...) { if (v1name)