/*
- * Copyright 2001-2007 Internet2
- *
+ * Copyright 2001-2009 Internet2
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
/**
* SAML2LogoutInitiator.cpp
- *
+ *
* Triggers SP-initiated logout for SAML 2.0 sessions.
*/
#ifndef SHIBSP_LITE
# include "binding/SOAPClient.h"
+# include "metadata/MetadataProviderCriteria.h"
# include <saml/SAMLConfig.h>
# include <saml/saml2/core/Protocols.h>
# include <saml/saml2/binding/SAML2SOAPClient.h>
# include <saml/saml2/metadata/EndpointManager.h>
# include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+# include <saml/signature/ContentReference.h>
+# include <xmltooling/security/Credential.h>
+# include <xmltooling/signature/Signature.h>
using namespace opensaml::saml2;
using namespace opensaml::saml2p;
using namespace opensaml::saml2md;
#pragma warning( push )
#pragma warning( disable : 4250 )
#endif
-
+
class SHIBSP_DLLLOCAL SAML2LogoutInitiator : public AbstractHandler, public LogoutHandler
{
public:
}
#endif
}
-
+
void setParent(const PropertySet* parent);
void receive(DDF& in, ostream& out);
pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
auto_ptr_char b(start);
MessageEncoder * encoder =
SAMLConfig::getConfig().MessageEncoderManager.newPlugin(b.get(),pair<const DOMElement*,const XMLCh*>(e,NULL));
- m_encoders[start] = encoder;
- m_log.debug("supporting outgoing binding (%s)", b.get());
+ if (encoder->isUserAgentPresent()) {
+ m_encoders[start] = encoder;
+ m_log.debug("supporting outgoing binding (%s)", b.get());
+ }
+ else {
+ delete encoder;
+ m_log.warn("skipping outgoing binding (%s), not a front-channel mechanism", b.get());
+ }
}
catch (exception& ex) {
m_log.error("error building MessageEncoder: %s", ex.what());
m_log.error("couldn't find application (%s) for logout", aid ? aid : "(missing)");
throw ConfigurationException("Unable to locate application for logout, deleted?");
}
-
+
// Unpack the request.
auto_ptr<HTTPRequest> req(getRequest(in));
DDF ret(NULL);
DDFJanitor jout(ret);
auto_ptr<HTTPResponse> resp(getResponse(ret));
-
+
Session* session = NULL;
try {
session = app->getServiceProvider().getSessionCache()->find(*app, *req.get(), NULL, NULL);
// With a session in hand, we can create a LogoutRequest message, if we can find a compatible endpoint.
MetadataProvider* m = application.getMetadataProvider();
Locker metadataLocker(m);
- MetadataProvider::Criteria mc(session->getEntityID(), &IDPSSODescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS);
+ MetadataProviderCriteria mc(application, session->getEntityID(), &IDPSSODescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS);
pair<const EntityDescriptor*,const RoleDescriptor*> entity = m->getEntityDescriptor(mc);
if (!entity.first) {
throw MetadataException(
}
}
- if (!logoutResponse)
- ret = sendLogoutPage(application, httpRequest, httpResponse, false, "Identity provider did not respond to logout request.");
+ if (!logoutResponse) {
+ ret = sendLogoutPage(
+ application, httpRequest, httpResponse, false,
+ endpoints.empty() ?
+ "Identity provider does not support SAML 2 Single Logout protocol." :
+ "Identity provider did not respond to logout request."
+ );
+ }
else if (!logoutResponse->getStatus() || !logoutResponse->getStatus()->getStatusCode() ||
!XMLString::equals(logoutResponse->getStatus()->getStatusCode()->getValue(), saml2p::StatusCode::SUCCESS)) {
delete logoutResponse;
if (cr)
cr->setDigestAlgorithm(sigalg.second);
}
-
+
// Sign response while marshalling.
vector<xmlsignature::Signature*> sigs(1,sig);
msg->marshall((DOMDocument*)NULL,&sigs,cred);