Change audience handling and validators to separate out entityID.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 17 Jan 2008 05:14:42 +0000 (05:14 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 17 Jan 2008 05:14:42 +0000 (05:14 +0000)
Make entityID overridable by relying party.

git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2691 cb58f699-b61c-0410-a6fe-9272a202ed29

17 files changed:
adfs/adfs.cpp
schemas/shibboleth-2.0-native-sp-config.xsd
shibsp/Application.h
shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp
shibsp/binding/impl/ArtifactResolver.cpp
shibsp/handler/impl/MetadataGenerator.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/Shib1SessionInitiator.cpp
shibsp/handler/impl/StatusHandler.cpp
shibsp/impl/StorageServiceSessionCache.cpp
shibsp/impl/XMLServiceProvider.cpp

index 7fee451..b2be93b 100644 (file)
@@ -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<const EntityDescriptor*>(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<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL,
+        entity,
         m_protocol.get(),
         nameid.get(),
         ssoStatement->getAuthenticationInstant() ? ssoStatement->getAuthenticationInstant()->getRawData() : NULL,
index d192e46..90ab0ee 100644 (file)
             <sequence/>\r
             <attribute name="Name" type="conf:string" use="required"/>\r
             <attributeGroup ref="conf:RelyingPartyGroup"/>\r
+            <attribute name="entityID" type="anyURI"/>\r
             <anyAttribute namespace="##other" processContents="lax"/>\r
         </complexType>\r
     </element>\r
index 1571c10..9660e7a 100644 (file)
@@ -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<const XMLCh*>& getAudiences() const=0;
+        virtual const std::vector<const XMLCh*>* getAudiences() const=0;
 #endif
 
         /**
index 46f46aa..2b36e99 100644 (file)
@@ -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<AttributeDesignator*>::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<saml1p::Response> wrapper(response);
     saml1::Assertion* newtoken = assertions.front();
 
-    pair<bool,bool> signedAssertions = application.getRelyingParty(ctx.getEntityDescriptor())->getBool("signedAssertions");
+    pair<bool,bool> 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<saml2::Subject> 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<saml2::Attribute*>::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) {
index 6888d16..332549f 100644 (file)
@@ -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<EntityDescriptor*>(ssoDescriptor.getParent()))->getXMLString("entityID").second);
             auto_ptr_XMLCh artbuf(artifact.encode().c_str());
             Artifact* a = ArtifactBuilder::buildArtifact();
             a->setArtifact(artbuf.get());
index 48a077b..bcf9e35 100644 (file)
@@ -66,13 +66,17 @@ namespace shibsp {
         void receive(DDF& in, ostream& out);
 
     private:
-        pair<bool,long> processMessage(const Application& application, const char* handlerURL, HTTPResponse& httpResponse) const;
+        pair<bool,long> processMessage(
+            const Application& application,
+            const char* handlerURL,
+            const char* entityID,
+            HTTPResponse& httpResponse
+            ) const;
 
         set<string> m_acl;
 #ifndef SHIBSP_LITE
         short m_http,m_https;
         vector<string> 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<bool,const char*> 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<bool,long> 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<bool,long> MetadataGenerator::processMessage(const Application& application, const char* handlerURL, HTTPResponse& httpResponse) const
+pair<bool,long> 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<bool,const char*> prop = getString("template");
     if (prop.first) {
@@ -212,6 +227,7 @@ pair<bool,long> MetadataGenerator::processMessage(const Application& application
         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());
         if (!entity)
             throw ConfigurationException("Template file ($1) did not contain an EntityDescriptor", params(1, prop.second));
@@ -225,7 +241,7 @@ pair<bool,long> MetadataGenerator::processMessage(const Application& application
     pair<bool,unsigned int> 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<bool,long> 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<bool,bool> flagprop = application.getRelyingParty(NULL)->getBool("signedAssertions");
+    pair<bool,bool> flagprop = relyingParty->getBool("signedAssertions");
     if (flagprop.first && flagprop.second)
         role->WantAssertionsSigned(true);
 
@@ -278,6 +294,9 @@ pair<bool,long> 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<const Credential*> creds;
         credResolver->resolve(creds,&cc);
@@ -357,7 +376,8 @@ pair<bool,long> 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);
index 74f13f8..475184c 100644 (file)
@@ -147,10 +147,6 @@ void SAML1Consumer::implementProtocol(
     // This is necessary because there may be valid tokens not aimed at us.
     vector<const opensaml::Assertion*> 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<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL;
     pair<bool,bool> 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<saml1::Assertion*>::const_iterator a = assertions.begin(); a!=assertions.end(); ++a) {
         try {
             // Skip unsigned assertion?
index df95366..ef85778 100644 (file)
@@ -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<bool,long> SAML2ArtifactResolution::processMessage(const Application& appli
     if (!req)
         throw FatalProfileException("Decoded message was not a samlp::ArtifactResolve request.");
 
+    const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast<EntityDescriptor*>(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<bool,long> 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<bool,long> SAML2ArtifactResolution::processMessage(const Application& appli
         auto_ptr<ArtifactResponse> 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<bool,long> 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<bool,long> SAML2ArtifactResolution::processMessage(const Application& appli
 
 #ifndef SHIBSP_LITE
 pair<bool,long> 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<ArtifactResponse> 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
index 735196c..af3505a 100644 (file)
@@ -132,11 +132,6 @@ void SAML2Consumer::implementProtocol(
     // And also track "owned" tokens that we decrypt here.
     vector<saml2::Assertion*> 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<bool,bool> 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<bool,unsigned int> authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair<bool,unsigned int>(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<MetadataCredentialCriteria> mcc(
                 policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : NULL
                 );
-            auto_ptr<XMLObject> wrapper((*ea)->decrypt(*cr, application.getXMLString("entityID").second, mcc.get()));
+            auto_ptr<XMLObject> wrapper((*ea)->decrypt(*cr, application.getRelyingParty(entity)->getXMLString("entityID").second, mcc.get()));
             decrypted = dynamic_cast<saml2::Assertion*>(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<XMLObject> decryptedID(encname->decrypt(*cr,application.getXMLString("entityID").second,mcc.get()));
+                    auto_ptr<XMLObject> decryptedID(encname->decrypt(*cr,application.getRelyingParty(entity)->getXMLString("entityID").second,mcc.get()));
                     ssoName = dynamic_cast<NameID*>(decryptedID.get());
                     if (ssoName) {
                         ownedName = true;
index 7dd1d78..be80cb1 100644 (file)
@@ -373,7 +373,13 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
                         policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : NULL
                         );
                     try {
-                        auto_ptr<XMLObject> decryptedID(encname->decrypt(*cr,application.getXMLString("entityID").second,mcc.get()));
+                        auto_ptr<XMLObject> decryptedID(
+                            encname->decrypt(
+                                *cr,
+                                application.getRelyingParty(policy.getIssuerMetadata() ? dynamic_cast<EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL)->getXMLString("entityID").second,
+                                mcc.get()
+                                )
+                            );
                         nameid = dynamic_cast<NameID*>(decryptedID.get());
                         if (nameid) {
                             ownedName = true;
@@ -583,7 +589,7 @@ pair<bool,long> SAML2Logout::sendResponse(
     }
     Issuer* issuer = IssuerBuilder::buildIssuer();
     logout->setIssuer(issuer);
-    issuer->setName(application.getXMLString("entityID").second);
+    issuer->setName(application.getRelyingParty(dynamic_cast<EntityDescriptor*>(role->getParent()))->getXMLString("entityID").second);
     fillStatus(*logout.get(), code, subcode, msg);
 
     auto_ptr_char dest(logout->getDestination());
index ff813d3..400989c 100644 (file)
@@ -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<EntityDescriptor*>(role.getParent()));
+
     auto_ptr<LogoutRequest> 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<EntityDescriptor*>(role.getParent()));
     pair<bool,const char*> flag = relyingParty->getString("encryption");
     if (flag.first &&
         (!strcmp(flag.second, "true") || (encoder && !strcmp(flag.second, "front")) || (!encoder && !strcmp(flag.second, "back")))) {
index 08435ed..4aba9a6 100644 (file)
@@ -285,7 +285,9 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
                 true
                 );
         }
-        
+
+        EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast<EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL;
+
         bool ownedName = false;
         NameID* nameid = mgmtRequest->getNameID();
         if (!nameid) {
@@ -301,7 +303,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
                         policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : NULL
                         );
                     try {
-                        auto_ptr<XMLObject> decryptedID(encname->decrypt(*cr,application.getXMLString("entityID").second,mcc.get()));
+                        auto_ptr<XMLObject> decryptedID(encname->decrypt(*cr,application.getRelyingParty(entity)->getXMLString("entityID").second,mcc.get()));
                         nameid = dynamic_cast<NameID*>(decryptedID.get());
                         if (nameid) {
                             ownedName = true;
@@ -332,7 +334,6 @@ pair<bool,long> 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<EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL;
         if (!session_id.empty()) {
             if (!cache->matches(application, request, entity, *nameid, NULL)) {
                 return sendResponse(
@@ -367,7 +368,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
                             policy.getIssuerMetadata() ? new MetadataCredentialCriteria(*policy.getIssuerMetadata()) : NULL
                             );
                         try {
-                            auto_ptr<XMLObject> decryptedID(encnewid->decrypt(*cr,application.getXMLString("entityID").second,mcc.get()));
+                            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;
@@ -518,7 +519,7 @@ pair<bool,long> SAML2NameIDMgmt::sendResponse(
     }
     Issuer* issuer = IssuerBuilder::buildIssuer();
     nim->setIssuer(issuer);
-    issuer->setName(application.getXMLString("entityID").second);
+    issuer->setName(application.getRelyingParty(dynamic_cast<EntityDescriptor*>(role->getParent()))->getXMLString("entityID").second);
     fillStatus(*nim.get(), code, subcode, msg);
 
     auto_ptr_char dest(nim->getDestination());
index 84dc168..e6efdd8 100644 (file)
@@ -562,7 +562,7 @@ pair<bool,long> 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();
index e2b1ea4..8d5e065 100644 (file)
@@ -258,7 +258,7 @@ pair<bool,long> 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
index 5a5a11b..5f72c43 100644 (file)
@@ -421,7 +421,18 @@ pair<bool,long> StatusHandler::processMessage(
             status = "<Partial/>";
         }
 
-        s << "<Application id='" << application.getId() << "' entityID='" << application.getString("entityID").second << "'/>";
+        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 << "<Application id='" << application.getId() << "' entityID='" << relyingParty->getString("entityID").second << "'/>";
 
         s << "<Handlers>";
         vector<const Handler*> handlers;
@@ -434,15 +445,6 @@ pair<bool,long> StatusHandler::processMessage(
         }
         s << "</Handlers>";
 
-        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);
index cb26b1f..f5c9d60 100644 (file)
@@ -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<string>::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<string>::const_iterator x = indexes->begin(); x!=indexes->end(); ++x)
                 root.addmember(x->c_str()).string(timebuf);
@@ -1150,7 +1150,7 @@ vector<string>::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();
                         }
index ee06184..5c6c4cf 100644 (file)
@@ -95,11 +95,10 @@ namespace {
         SAML2Artifact* generateSAML2Artifact(const EntityDescriptor* relyingParty) const {
             pair<bool,int> 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<const XMLCh*>& getAudiences() const {
-            return (m_audiences.empty() && m_base) ? m_base->getAudiences() : m_audiences;
+        const vector<const XMLCh*>* 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) {