From 392d1448deb48beb75f219532ac248b4776f16db Mon Sep 17 00:00:00 2001 From: cantor Date: Thu, 17 Jan 2008 05:14:42 +0000 Subject: [PATCH] Change audience handling and validators to separate out entityID. Make entityID overridable by relying party. git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2691 cb58f699-b61c-0410-a6fe-9272a202ed29 --- adfs/adfs.cpp | 6 ++- schemas/shibboleth-2.0-native-sp-config.xsd | 1 + shibsp/Application.h | 6 +-- .../resolver/impl/QueryAttributeResolver.cpp | 14 +++---- shibsp/binding/impl/ArtifactResolver.cpp | 2 +- shibsp/handler/impl/MetadataGenerator.cpp | 48 +++++++++++++++------- shibsp/handler/impl/SAML1Consumer.cpp | 8 ++-- shibsp/handler/impl/SAML2ArtifactResolution.cpp | 21 +++++++--- shibsp/handler/impl/SAML2Consumer.cpp | 18 ++++---- shibsp/handler/impl/SAML2Logout.cpp | 10 ++++- shibsp/handler/impl/SAML2LogoutInitiator.cpp | 5 ++- shibsp/handler/impl/SAML2NameIDMgmt.cpp | 11 ++--- shibsp/handler/impl/SAML2SessionInitiator.cpp | 2 +- shibsp/handler/impl/Shib1SessionInitiator.cpp | 2 +- shibsp/handler/impl/StatusHandler.cpp | 22 +++++----- shibsp/impl/StorageServiceSessionCache.cpp | 8 ++-- shibsp/impl/XMLServiceProvider.cpp | 12 ++---- 17 files changed, 118 insertions(+), 78 deletions(-) diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp index 7fee451..b2be93b 100644 --- a/adfs/adfs.cpp +++ b/adfs/adfs.cpp @@ -566,10 +566,12 @@ void ADFSConsumer::implementProtocol( if (!policy.isAuthenticated()) throw SecurityPolicyException("Unable to establish security of incoming assertion."); + const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast(policy.getIssuerMetadata()->getParent()) : NULL; + // Now do profile and core semantic validation to ensure we can use it for SSO. // Profile validator. time_t now = time(NULL); - saml1::AssertionValidator ssoValidator(application.getAudiences(), now); + saml1::AssertionValidator ssoValidator(application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now); ssoValidator.validateAssertion(*token); if (!token->getConditions() || !token->getConditions()->getNotBefore() || !token->getConditions()->getNotOnOrAfter()) throw FatalProfileException("Assertion did not contain time conditions."); @@ -642,7 +644,7 @@ void ADFSConsumer::implementProtocol( httpRequest, httpResponse, now + lifetime.second, - policy.getIssuerMetadata() ? dynamic_cast(policy.getIssuerMetadata()->getParent()) : NULL, + entity, m_protocol.get(), nameid.get(), ssoStatement->getAuthenticationInstant() ? ssoStatement->getAuthenticationInstant()->getRawData() : NULL, diff --git a/schemas/shibboleth-2.0-native-sp-config.xsd b/schemas/shibboleth-2.0-native-sp-config.xsd index d192e46..90ab0ee 100644 --- a/schemas/shibboleth-2.0-native-sp-config.xsd +++ b/schemas/shibboleth-2.0-native-sp-config.xsd @@ -641,6 +641,7 @@ + diff --git a/shibsp/Application.h b/shibsp/Application.h index 1571c10..9660e7a 100644 --- a/shibsp/Application.h +++ b/shibsp/Application.h @@ -172,11 +172,11 @@ namespace shibsp { virtual const PropertySet* getRelyingParty(const opensaml::saml2md::EntityDescriptor* provider) const=0; /** - * Returns the set of audience values associated with this Application. + * Returns any additional audience values associated with this Application. * - * @return set of audience values associated with the Application + * @return additional audience values associated with the Application, or NULL */ - virtual const std::vector& getAudiences() const=0; + virtual const std::vector* getAudiences() const=0; #endif /** diff --git a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp index 46f46aa..2b36e99 100644 --- a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp +++ b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp @@ -269,6 +269,7 @@ bool QueryResolver::SAML1Query(QueryContext& ctx) const } const Application& application = ctx.getApplication(); + const PropertySet* relyingParty = application.getRelyingParty(ctx.getEntityDescriptor()); shibsp::SecurityPolicy policy(application); MetadataCredentialCriteria mcc(*AA); shibsp::SOAPClient soaper(policy); @@ -281,7 +282,6 @@ bool QueryResolver::SAML1Query(QueryContext& ctx) const if (!XMLString::equals((*ep)->getBinding(),binding.get())) continue; auto_ptr_char loc((*ep)->getLocation()); - auto_ptr_XMLCh issuer(application.getString("entityID").second); NameIdentifier* nameid = NameIdentifierBuilder::buildNameIdentifier(); nameid->setName(ctx.getNameID()->getName()); nameid->setFormat(ctx.getNameID()->getFormat()); @@ -290,7 +290,7 @@ bool QueryResolver::SAML1Query(QueryContext& ctx) const subject->setNameIdentifier(nameid); saml1p::AttributeQuery* query = saml1p::AttributeQueryBuilder::buildAttributeQuery(); query->setSubject(subject); - query->setResource(issuer.get()); + query->setResource(relyingParty->getXMLString("entityID").second); for (vector::const_iterator ad = m_SAML1Designators.begin(); ad!=m_SAML1Designators.end(); ++ad) query->getAttributeDesignators().push_back((*ad)->cloneAttributeDesignator()); Request* request = RequestBuilder::buildRequest(); @@ -330,7 +330,7 @@ bool QueryResolver::SAML1Query(QueryContext& ctx) const auto_ptr wrapper(response); saml1::Assertion* newtoken = assertions.front(); - pair signedAssertions = application.getRelyingParty(ctx.getEntityDescriptor())->getBool("signedAssertions"); + pair signedAssertions = relyingParty->getBool("signedAssertions"); if (!newtoken->getSignature() && signedAssertions.first && signedAssertions.second) { m_log.error("assertion unsigned, rejecting it based on signedAssertions policy"); return true; @@ -350,7 +350,7 @@ bool QueryResolver::SAML1Query(QueryContext& ctx) const throw SecurityPolicyException("Security of SAML 1.x query result not established."); // Lastly, check it over. - saml1::AssertionValidator tokval(application.getAudiences(), time(NULL)); + saml1::AssertionValidator tokval(relyingParty->getXMLString("entityID").second, application.getAudiences(), time(NULL)); tokval.validateAssertion(*newtoken); } catch (exception& ex) { @@ -416,8 +416,6 @@ bool QueryResolver::SAML2Query(QueryContext& ctx) const if (!XMLString::equals((*ep)->getBinding(),binding.get())) continue; auto_ptr_char loc((*ep)->getLocation()); - auto_ptr_XMLCh issuer(application.getString("entityID").second); - auto_ptr subject(saml2::SubjectBuilder::buildSubject()); // Encrypt the NameID? @@ -440,7 +438,7 @@ bool QueryResolver::SAML2Query(QueryContext& ctx) const saml2p::AttributeQuery* query = saml2p::AttributeQueryBuilder::buildAttributeQuery(); query->setSubject(subject.release()); Issuer* iss = IssuerBuilder::buildIssuer(); - iss->setName(issuer.get()); + iss->setName(relyingParty->getXMLString("entityID").second); query->setIssuer(iss); for (vector::const_iterator ad = m_SAML2Designators.begin(); ad!=m_SAML2Designators.end(); ++ad) query->getAttributes().push_back((*ad)->cloneAttribute()); @@ -503,7 +501,7 @@ bool QueryResolver::SAML2Query(QueryContext& ctx) const throw SecurityPolicyException("Security of SAML 2.0 query result not established."); // Lastly, check it over. - saml2::AssertionValidator tokval(application.getAudiences(), time(NULL)); + saml2::AssertionValidator tokval(relyingParty->getXMLString("entityID").second, application.getAudiences(), time(NULL)); tokval.validateAssertion(*newtoken); } catch (exception& ex) { diff --git a/shibsp/binding/impl/ArtifactResolver.cpp b/shibsp/binding/impl/ArtifactResolver.cpp index 6888d16..332549f 100644 --- a/shibsp/binding/impl/ArtifactResolver.cpp +++ b/shibsp/binding/impl/ArtifactResolver.cpp @@ -121,7 +121,7 @@ ArtifactResponse* ArtifactResolver::resolve( ArtifactResolve* request = ArtifactResolveBuilder::buildArtifactResolve(); Issuer* iss = IssuerBuilder::buildIssuer(); request->setIssuer(iss); - iss->setName(sppolicy.getApplication().getXMLString("entityID").second); + iss->setName(sppolicy.getApplication().getRelyingParty(dynamic_cast(ssoDescriptor.getParent()))->getXMLString("entityID").second); auto_ptr_XMLCh artbuf(artifact.encode().c_str()); Artifact* a = ArtifactBuilder::buildArtifact(); a->setArtifact(artbuf.get()); diff --git a/shibsp/handler/impl/MetadataGenerator.cpp b/shibsp/handler/impl/MetadataGenerator.cpp index 48a077b..bcf9e35 100644 --- a/shibsp/handler/impl/MetadataGenerator.cpp +++ b/shibsp/handler/impl/MetadataGenerator.cpp @@ -66,13 +66,17 @@ namespace shibsp { void receive(DDF& in, ostream& out); private: - pair processMessage(const Application& application, const char* handlerURL, HTTPResponse& httpResponse) const; + pair processMessage( + const Application& application, + const char* handlerURL, + const char* entityID, + HTTPResponse& httpResponse + ) const; set m_acl; #ifndef SHIBSP_LITE short m_http,m_https; vector m_bases; - const char* m_mime; #endif }; @@ -90,7 +94,7 @@ namespace shibsp { MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId) : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".MetadataGenerator"), &g_Blocker) #ifndef SHIBSP_LITE - ,m_https(0), m_http(0), m_mime(NULL) + ,m_https(0), m_http(0) #endif { string address(appId); @@ -121,10 +125,6 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId) if (flag.first) m_https = flag.second ? 1 : -1; - pair mime = getString("mimeType"); - if (mime.first) - m_mime = mime.second; - e = XMLHelper::getFirstChildElement(e, EndpointBase); while (e) { if (e->hasChildNodes()) { @@ -151,13 +151,15 @@ pair MetadataGenerator::run(SPRequest& request, bool isHandler) const try { if (conf.isEnabled(SPConfig::OutOfProcess)) { // When out of process, we run natively and directly process the message. - return processMessage(request.getApplication(), request.getHandlerURL(), request); + return processMessage(request.getApplication(), request.getHandlerURL(), request.getParameter("entityID"), request); } else { // When not out of process, we remote all the message processing. DDF out,in = DDF(m_address.c_str()); in.addmember("application_id").string(request.getApplication().getId()); in.addmember("handler_url").string(request.getHandlerURL()); + if (request.getParameter("entityID")) + in.addmember("entity_id").string(request.getParameter("entityID")); DDFJanitor jin(in), jout(out); out=request.getServiceProvider().getListenerService()->send(in); @@ -194,15 +196,28 @@ void MetadataGenerator::receive(DDF& in, ostream& out) // 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, *resp.get()); + processMessage(*app, hurl, in["entity_id"].string(), *resp.get()); out << ret; } -pair MetadataGenerator::processMessage(const Application& application, const char* handlerURL, HTTPResponse& httpResponse) const +pair MetadataGenerator::processMessage( + const Application& application, const char* handlerURL, const char* entityID, HTTPResponse& httpResponse + ) const { #ifndef SHIBSP_LITE m_log.debug("processing metadata request"); + const PropertySet* relyingParty=NULL; + if (entityID) { + MetadataProvider* m=application.getMetadataProvider(); + Locker locker(m); + MetadataProvider::Criteria mc(entityID); + relyingParty = application.getRelyingParty(m->getEntityDescriptor(mc).first); + } + else { + relyingParty = application.getRelyingParty(NULL); + } + EntityDescriptor* entity; pair prop = getString("template"); if (prop.first) { @@ -212,6 +227,7 @@ pair MetadataGenerator::processMessage(const Application& application DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(dsrc); XercesJanitor docjan(doc); auto_ptr xmlobj(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true)); + docjan.release(); entity = dynamic_cast(xmlobj.get()); if (!entity) throw ConfigurationException("Template file ($1) did not contain an EntityDescriptor", params(1, prop.second)); @@ -225,7 +241,7 @@ pair MetadataGenerator::processMessage(const Application& application pair cache = getUnsignedInt("cacheDuration"); if (cache.first) entity->setValidUntil(time(NULL) + cache.second); - entity->setEntityID(application.getXMLString("entityID").second); + entity->setEntityID(relyingParty->getXMLString("entityID").second); SPSSODescriptor* role; if (entity->getSPSSODescriptors().empty()) { @@ -237,10 +253,10 @@ pair MetadataGenerator::processMessage(const Application& application } // Policy flags. - prop = application.getRelyingParty(NULL)->getString("signing"); + prop = relyingParty->getString("signing"); if (prop.first && (!strcmp(prop.second,"true") || !strcmp(prop.second,"front"))) role->AuthnRequestsSigned(true); - pair flagprop = application.getRelyingParty(NULL)->getBool("signedAssertions"); + pair flagprop = relyingParty->getBool("signedAssertions"); if (flagprop.first && flagprop.second) role->WantAssertionsSigned(true); @@ -278,6 +294,9 @@ pair MetadataGenerator::processMessage(const Application& application if (credResolver) { Locker credLocker(credResolver); CredentialCriteria cc; + prop = relyingParty->getString("keyName"); + if (prop.first) + cc.getKeyNames().insert(prop.second); cc.setUsage(Credential::SIGNING_CREDENTIAL); vector creds; credResolver->resolve(creds,&cc); @@ -357,7 +376,8 @@ pair MetadataGenerator::processMessage(const Application& application XMLHelper::serialize(entity->marshall(), s, true); } - httpResponse.setContentType(m_mime ? m_mime : "application/samlmetadata+xml"); + prop = getString("mimeType"); + httpResponse.setContentType(prop.first ? prop.second : "application/samlmetadata+xml"); return make_pair(true, httpResponse.sendResponse(s)); #else return make_pair(false,0L); diff --git a/shibsp/handler/impl/SAML1Consumer.cpp b/shibsp/handler/impl/SAML1Consumer.cpp index 74f13f8..475184c 100644 --- a/shibsp/handler/impl/SAML1Consumer.cpp +++ b/shibsp/handler/impl/SAML1Consumer.cpp @@ -147,10 +147,6 @@ void SAML1Consumer::implementProtocol( // This is necessary because there may be valid tokens not aimed at us. vector badtokens; - // Profile validator. - time_t now = time(NULL); - BrowserSSOProfileValidator ssoValidator(application.getAudiences(), now); - // With this flag on, we ignore any unsigned assertions. const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast(policy.getIssuerMetadata()->getParent()) : NULL; pair flag = application.getRelyingParty(entity)->getBool("signedAssertions"); @@ -162,6 +158,10 @@ void SAML1Consumer::implementProtocol( // Saves off error messages potentially helpful for users. string contextualError; + // Profile validator. + time_t now = time(NULL); + BrowserSSOProfileValidator ssoValidator(application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now); + for (vector::const_iterator a = assertions.begin(); a!=assertions.end(); ++a) { try { // Skip unsigned assertion? diff --git a/shibsp/handler/impl/SAML2ArtifactResolution.cpp b/shibsp/handler/impl/SAML2ArtifactResolution.cpp index df95366..ef85778 100644 --- a/shibsp/handler/impl/SAML2ArtifactResolution.cpp +++ b/shibsp/handler/impl/SAML2ArtifactResolution.cpp @@ -82,6 +82,7 @@ namespace shibsp { const Application& app, const ArtifactResolve& request, HTTPResponse& httpResponse, + const EntityDescriptor* recipient, const XMLCh* code, const XMLCh* subcode=NULL, const char* msg=NULL @@ -277,10 +278,12 @@ pair SAML2ArtifactResolution::processMessage(const Application& appli if (!req) throw FatalProfileException("Decoded message was not a samlp::ArtifactResolve request."); + const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast(policy.getIssuerMetadata()->getParent()) : NULL; + try { auto_ptr_char artifact(req->getArtifact() ? req->getArtifact()->getArtifact() : NULL); if (!artifact.get() || !*artifact.get()) - return samlError(application, *req, httpResponse, StatusCode::REQUESTER, NULL, "Request did not contain an artifact to resolve."); + return samlError(application, *req, httpResponse, entity, StatusCode::REQUESTER, NULL, "Request did not contain an artifact to resolve."); auto_ptr_char issuer(policy.getIssuer() ? policy.getIssuer()->getName() : NULL); m_log.info("resolving artifact (%s) for (%s)", artifact.get(), issuer.get() ? issuer.get() : "unknown"); @@ -291,7 +294,7 @@ pair SAML2ArtifactResolution::processMessage(const Application& appli if (!policy.isAuthenticated()) { m_log.error("request for artifact was unauthenticated, purging the artifact mapping"); - return samlError(application, *req, httpResponse, StatusCode::REQUESTER, StatusCode::AUTHN_FAILED, "Unable to authenticate request."); + return samlError(application, *req, httpResponse, entity, StatusCode::REQUESTER, StatusCode::AUTHN_FAILED, "Unable to authenticate request."); } m_log.debug("artifact resolved, preparing response"); @@ -300,7 +303,7 @@ pair SAML2ArtifactResolution::processMessage(const Application& appli auto_ptr resp(ArtifactResponseBuilder::buildArtifactResponse()); resp->setInResponseTo(req->getID()); Issuer* me = IssuerBuilder::buildIssuer(); - me->setName(application.getXMLString("entityID").second); + me->setName(application.getRelyingParty(entity)->getXMLString("entityID").second); resp->setPayload(payload.release()); long ret = sendMessage( @@ -312,7 +315,7 @@ pair SAML2ArtifactResolution::processMessage(const Application& appli catch (exception& ex) { // Trap localized errors in a SAML Response. m_log.error("error processing artifact request, returning SAML error: %s", ex.what()); - return samlError(application, *req, httpResponse, StatusCode::RESPONDER, NULL, ex.what()); + return samlError(application, *req, httpResponse, entity, StatusCode::RESPONDER, NULL, ex.what()); } #else return make_pair(false,0L); @@ -321,13 +324,19 @@ pair SAML2ArtifactResolution::processMessage(const Application& appli #ifndef SHIBSP_LITE pair SAML2ArtifactResolution::samlError( - const Application& app, const ArtifactResolve& request, HTTPResponse& httpResponse, const XMLCh* code, const XMLCh* subcode, const char* msg + const Application& app, + const ArtifactResolve& request, + HTTPResponse& httpResponse, + const EntityDescriptor* recipient, + const XMLCh* code, + const XMLCh* subcode, + const char* msg ) const { auto_ptr resp(ArtifactResponseBuilder::buildArtifactResponse()); resp->setInResponseTo(request.getID()); Issuer* me = IssuerBuilder::buildIssuer(); - me->setName(app.getXMLString("entityID").second); + me->setName(app.getRelyingParty(recipient)->getXMLString("entityID").second); fillStatus(*resp.get(), code, subcode, msg); long ret = m_encoder->encode(httpResponse, resp.get(), NULL); resp.release(); // freed by encoder diff --git a/shibsp/handler/impl/SAML2Consumer.cpp b/shibsp/handler/impl/SAML2Consumer.cpp index 735196c..af3505a 100644 --- a/shibsp/handler/impl/SAML2Consumer.cpp +++ b/shibsp/handler/impl/SAML2Consumer.cpp @@ -132,11 +132,6 @@ void SAML2Consumer::implementProtocol( // And also track "owned" tokens that we decrypt here. vector ownedtokens; - // Profile validator. - time_t now = time(NULL); - string dest = httpRequest.getRequestURL(); - BrowserSSOProfileValidator ssoValidator(application.getAudiences(), now, dest.substr(0,dest.find('?')).c_str()); - // With this flag on, we ignore any unsigned assertions. const EntityDescriptor* entity = NULL; pair flag = make_pair(false,false); @@ -145,6 +140,9 @@ void SAML2Consumer::implementProtocol( flag = application.getRelyingParty(entity)->getBool("signedAssertions"); } + time_t now = time(NULL); + string dest = httpRequest.getRequestURL(); + // authnskew allows rejection of SSO if AuthnInstant is too old. const PropertySet* sessionProps = application.getPropertySet("Sessions"); pair authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair(false,0); @@ -182,6 +180,9 @@ void SAML2Consumer::implementProtocol( } // Now do profile and core semantic validation to ensure we can use it for SSO. + BrowserSSOProfileValidator ssoValidator( + application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now, dest.substr(0,dest.find('?')).c_str() + ); ssoValidator.validateAssertion(*(*a)); // Address checking. @@ -224,7 +225,7 @@ void SAML2Consumer::implementProtocol( auto_ptr mcc( policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : NULL ); - auto_ptr wrapper((*ea)->decrypt(*cr, application.getXMLString("entityID").second, mcc.get())); + auto_ptr wrapper((*ea)->decrypt(*cr, application.getRelyingParty(entity)->getXMLString("entityID").second, mcc.get())); decrypted = dynamic_cast(wrapper.get()); if (decrypted) { wrapper.release(); @@ -263,6 +264,9 @@ void SAML2Consumer::implementProtocol( throw SecurityPolicyException("Unable to establish security of incoming assertion."); // Now do profile and core semantic validation to ensure we can use it for SSO. + BrowserSSOProfileValidator ssoValidator( + application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now, dest.substr(0,dest.find('?')).c_str() + ); ssoValidator.validateAssertion(*decrypted); // Address checking. @@ -313,7 +317,7 @@ void SAML2Consumer::implementProtocol( policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : NULL ); try { - auto_ptr decryptedID(encname->decrypt(*cr,application.getXMLString("entityID").second,mcc.get())); + auto_ptr decryptedID(encname->decrypt(*cr,application.getRelyingParty(entity)->getXMLString("entityID").second,mcc.get())); ssoName = dynamic_cast(decryptedID.get()); if (ssoName) { ownedName = true; diff --git a/shibsp/handler/impl/SAML2Logout.cpp b/shibsp/handler/impl/SAML2Logout.cpp index 7dd1d78..be80cb1 100644 --- a/shibsp/handler/impl/SAML2Logout.cpp +++ b/shibsp/handler/impl/SAML2Logout.cpp @@ -373,7 +373,13 @@ pair SAML2Logout::doRequest(const Application& application, const HTT policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : NULL ); try { - auto_ptr decryptedID(encname->decrypt(*cr,application.getXMLString("entityID").second,mcc.get())); + auto_ptr decryptedID( + encname->decrypt( + *cr, + application.getRelyingParty(policy.getIssuerMetadata() ? dynamic_cast(policy.getIssuerMetadata()->getParent()) : NULL)->getXMLString("entityID").second, + mcc.get() + ) + ); nameid = dynamic_cast(decryptedID.get()); if (nameid) { ownedName = true; @@ -583,7 +589,7 @@ pair SAML2Logout::sendResponse( } Issuer* issuer = IssuerBuilder::buildIssuer(); logout->setIssuer(issuer); - issuer->setName(application.getXMLString("entityID").second); + issuer->setName(application.getRelyingParty(dynamic_cast(role->getParent()))->getXMLString("entityID").second); fillStatus(*logout.get(), code, subcode, msg); auto_ptr_char dest(logout->getDestination()); diff --git a/shibsp/handler/impl/SAML2LogoutInitiator.cpp b/shibsp/handler/impl/SAML2LogoutInitiator.cpp index ff813d3..400989c 100644 --- a/shibsp/handler/impl/SAML2LogoutInitiator.cpp +++ b/shibsp/handler/impl/SAML2LogoutInitiator.cpp @@ -404,10 +404,12 @@ LogoutRequest* SAML2LogoutInitiator::buildRequest( const Application& application, const Session& session, const RoleDescriptor& role, const MessageEncoder* encoder ) const { + const PropertySet* relyingParty = application.getRelyingParty(dynamic_cast(role.getParent())); + auto_ptr msg(LogoutRequestBuilder::buildLogoutRequest()); Issuer* issuer = IssuerBuilder::buildIssuer(); msg->setIssuer(issuer); - issuer->setName(application.getXMLString("entityID").second); + issuer->setName(relyingParty->getXMLString("entityID").second); auto_ptr_XMLCh index(session.getSessionIndex()); if (index.get() && *index.get()) { SessionIndex* si = SessionIndexBuilder::buildSessionIndex(); @@ -416,7 +418,6 @@ LogoutRequest* SAML2LogoutInitiator::buildRequest( } const NameID* nameid = session.getNameID(); - const PropertySet* relyingParty = application.getRelyingParty(dynamic_cast(role.getParent())); pair flag = relyingParty->getString("encryption"); if (flag.first && (!strcmp(flag.second, "true") || (encoder && !strcmp(flag.second, "front")) || (!encoder && !strcmp(flag.second, "back")))) { diff --git a/shibsp/handler/impl/SAML2NameIDMgmt.cpp b/shibsp/handler/impl/SAML2NameIDMgmt.cpp index 08435ed..4aba9a6 100644 --- a/shibsp/handler/impl/SAML2NameIDMgmt.cpp +++ b/shibsp/handler/impl/SAML2NameIDMgmt.cpp @@ -285,7 +285,9 @@ pair SAML2NameIDMgmt::doRequest( true ); } - + + EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast(policy.getIssuerMetadata()->getParent()) : NULL; + bool ownedName = false; NameID* nameid = mgmtRequest->getNameID(); if (!nameid) { @@ -301,7 +303,7 @@ pair SAML2NameIDMgmt::doRequest( policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : NULL ); try { - auto_ptr decryptedID(encname->decrypt(*cr,application.getXMLString("entityID").second,mcc.get())); + auto_ptr decryptedID(encname->decrypt(*cr,application.getRelyingParty(entity)->getXMLString("entityID").second,mcc.get())); nameid = dynamic_cast(decryptedID.get()); if (nameid) { ownedName = true; @@ -332,7 +334,6 @@ pair SAML2NameIDMgmt::doRequest( // For a front-channel request, we have to match the information in the request // against the current session. - EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast(policy.getIssuerMetadata()->getParent()) : NULL; if (!session_id.empty()) { if (!cache->matches(application, request, entity, *nameid, NULL)) { return sendResponse( @@ -367,7 +368,7 @@ pair SAML2NameIDMgmt::doRequest( policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : NULL ); try { - auto_ptr decryptedID(encnewid->decrypt(*cr,application.getXMLString("entityID").second,mcc.get())); + auto_ptr decryptedID(encnewid->decrypt(*cr,application.getRelyingParty(entity)->getXMLString("entityID").second,mcc.get())); newid = dynamic_cast(decryptedID.get()); if (newid) { ownedNewID = true; @@ -518,7 +519,7 @@ pair SAML2NameIDMgmt::sendResponse( } Issuer* issuer = IssuerBuilder::buildIssuer(); nim->setIssuer(issuer); - issuer->setName(application.getXMLString("entityID").second); + issuer->setName(application.getRelyingParty(dynamic_cast(role->getParent()))->getXMLString("entityID").second); fillStatus(*nim.get(), code, subcode, msg); auto_ptr_char dest(nim->getDestination()); diff --git a/shibsp/handler/impl/SAML2SessionInitiator.cpp b/shibsp/handler/impl/SAML2SessionInitiator.cpp index 84dc168..e6efdd8 100644 --- a/shibsp/handler/impl/SAML2SessionInitiator.cpp +++ b/shibsp/handler/impl/SAML2SessionInitiator.cpp @@ -562,7 +562,7 @@ pair SAML2SessionInitiator::doRequest( if (!req->getIssuer()) { Issuer* issuer = IssuerBuilder::buildIssuer(); req->setIssuer(issuer); - issuer->setName(app.getXMLString("entityID").second); + issuer->setName(app.getRelyingParty(entity.first)->getXMLString("entityID").second); } if (!req->getNameIDPolicy()) { NameIDPolicy* namepol = NameIDPolicyBuilder::buildNameIDPolicy(); diff --git a/shibsp/handler/impl/Shib1SessionInitiator.cpp b/shibsp/handler/impl/Shib1SessionInitiator.cpp index e2b1ea4..8d5e065 100644 --- a/shibsp/handler/impl/Shib1SessionInitiator.cpp +++ b/shibsp/handler/impl/Shib1SessionInitiator.cpp @@ -258,7 +258,7 @@ pair Shib1SessionInitiator::doRequest( 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()) + - "&providerId=" + urlenc->encode(app.getString("entityID").second); + "&providerId=" + urlenc->encode(app.getRelyingParty(entity.first)->getString("entityID").second); return make_pair(true, httpResponse.sendRedirect(req.c_str())); #else diff --git a/shibsp/handler/impl/StatusHandler.cpp b/shibsp/handler/impl/StatusHandler.cpp index 5a5a11b..5f72c43 100644 --- a/shibsp/handler/impl/StatusHandler.cpp +++ b/shibsp/handler/impl/StatusHandler.cpp @@ -421,7 +421,18 @@ pair StatusHandler::processMessage( status = ""; } - s << ""; + const PropertySet* relyingParty=NULL; + param=httpRequest.getParameter("entityID"); + if (param) { + MetadataProvider* m = application.getMetadataProvider(); + Locker mlock(m); + relyingParty = application.getRelyingParty(m->getEntityDescriptor(MetadataProvider::Criteria(param)).first); + } + else { + relyingParty = application.getRelyingParty(NULL); + } + + s << ""; s << ""; vector handlers; @@ -434,15 +445,6 @@ pair StatusHandler::processMessage( } s << ""; - const PropertySet* relyingParty=NULL; - param=httpRequest.getParameter("entityID"); - if (param) { - MetadataProvider* m = application.getMetadataProvider(); - Locker mlock(m); - relyingParty = application.getRelyingParty(m->getEntityDescriptor(MetadataProvider::Criteria(param)).first); - } - if (!relyingParty) - relyingParty = application.getRelyingParty(NULL); CredentialResolver* credResolver=application.getCredentialResolver(); if (credResolver) { Locker credLocker(credResolver); diff --git a/shibsp/impl/StorageServiceSessionCache.cpp b/shibsp/impl/StorageServiceSessionCache.cpp index cb26b1f..f5c9d60 100644 --- a/shibsp/impl/StorageServiceSessionCache.cpp +++ b/shibsp/impl/StorageServiceSessionCache.cpp @@ -866,7 +866,7 @@ void SSCache::insert( istringstream pstr(pending); pstr >> pendobj; // IdP.SP.index contains logout expiration, if any. - DDF deadmenwalking = pendobj[issuer ? entity_id.get() : "_shibnull"][application.getString("entityID").second]; + DDF deadmenwalking = pendobj[issuer ? entity_id.get() : "_shibnull"][application.getRelyingParty(issuer)->getString("entityID").second]; const char* logexpstr = deadmenwalking[session_index ? index.get() : "_shibnull"].string(); if (!logexpstr && session_index) // we tried an exact session match, now try for NULL logexpstr = deadmenwalking["_shibnull"].string(); @@ -1027,7 +1027,7 @@ bool SSCache::matches( if (session) { Locker locker(session, false); if (XMLString::equals(session->getEntityID(), entityID.get()) && session->getNameID() && - stronglyMatches(issuer->getEntityID(), application.getXMLString("entityID").second, nameid, *session->getNameID())) { + stronglyMatches(issuer->getEntityID(), application.getRelyingParty(issuer)->getXMLString("entityID").second, nameid, *session->getNameID())) { return (!indexes || indexes->empty() || (session->getSessionIndex() ? (indexes->count(session->getSessionIndex())>0) : false)); } } @@ -1090,7 +1090,7 @@ vector::size_type SSCache::logout( } // Structure is keyed by the IdP and SP, with a member per session index containing the expiration. - DDF root = obj.addmember(issuer ? entityID.get() : "_shibnull").addmember(application.getString("entityID").second); + DDF root = obj.addmember(issuer ? entityID.get() : "_shibnull").addmember(application.getRelyingParty(issuer)->getString("entityID").second); if (indexes) { for (set::const_iterator x = indexes->begin(); x!=indexes->end(); ++x) root.addmember(x->c_str()).string(timebuf); @@ -1150,7 +1150,7 @@ vector::size_type SSCache::logout( // Same issuer? if (XMLString::equals(session->getEntityID(), entityID.get())) { // Same NameID? - if (stronglyMatches(issuer->getEntityID(), application.getXMLString("entityID").second, nameid, *session->getNameID())) { + if (stronglyMatches(issuer->getEntityID(), application.getRelyingParty(issuer)->getXMLString("entityID").second, nameid, *session->getNameID())) { sessionsKilled.push_back(key.string()); key.destroy(); } diff --git a/shibsp/impl/XMLServiceProvider.cpp b/shibsp/impl/XMLServiceProvider.cpp index ee06184..5c6c4cf 100644 --- a/shibsp/impl/XMLServiceProvider.cpp +++ b/shibsp/impl/XMLServiceProvider.cpp @@ -95,11 +95,10 @@ namespace { SAML2Artifact* generateSAML2Artifact(const EntityDescriptor* relyingParty) const { pair index = make_pair(false,0); const PropertySet* props = getRelyingParty(relyingParty); - if (props) - index = getInt("artifactEndpointIndex"); + index = props->getInt("artifactEndpointIndex"); if (!index.first) index = getArtifactEndpointIndex(); - return new SAML2ArtifactType0004(SAMLConfig::getConfig().hashSHA1(getString("entityID").second),index.first ? index.second : 1); + return new SAML2ArtifactType0004(SAMLConfig::getConfig().hashSHA1(props->getString("entityID").second),index.first ? index.second : 1); } MetadataProvider* getMetadataProvider(bool required=true) const { @@ -125,8 +124,8 @@ namespace { return (!m_credResolver && m_base) ? m_base->getCredentialResolver() : m_credResolver; } const PropertySet* getRelyingParty(const EntityDescriptor* provider) const; - const vector& getAudiences() const { - return (m_audiences.empty() && m_base) ? m_base->getAudiences() : m_audiences; + const vector* getAudiences() const { + return (m_audiences.empty() && m_base) ? m_base->getAudiences() : &m_audiences; } #endif string getNotificationURL(const char* resource, bool front, unsigned int index) const; @@ -732,9 +731,6 @@ XMLApplication::XMLApplication( if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes()) m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue()); - // Always include our own entityID as an audience. - m_audiences.push_back(getXMLString("entityID").second); - if (conf.isEnabled(SPConfig::Metadata)) { child = XMLHelper::getFirstChildElement(e,_MetadataProvider); if (child) { -- 2.1.4