auto_ptr_XMLCh m_protocol;
private:
- string implementProtocol(
+ void implementProtocol(
const Application& application,
const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse,
SecurityPolicy& policy,
const PropertySet* settings,
const XMLObject& xmlObject
#endif
private:
- pair<bool,long> doRequest(
- const Application& application, const char* requestURL, const char* entityID, HTTPResponse& httpResponse
- ) const;
+ pair<bool,long> doRequest(const Application& application, const char* entityID, HTTPResponse& httpResponse) const;
string m_appId;
auto_ptr_XMLCh m_binding;
// Since we're passing the ACS by value, we need to compute the return URL,
// so we'll need the target resource for real.
- recoverRelayState(request.getApplication(), request, target, false);
+ recoverRelayState(request.getApplication(), request, request, target, false);
}
else {
// We're running as a "virtual handler" from within the filter.
return xmlObject.release();
}
-string ADFSConsumer::implementProtocol(
+void ADFSConsumer::implementProtocol(
const Application& application,
const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse,
SecurityPolicy& policy,
const PropertySet* settings,
const XMLObject& xmlObject
}
// The context will handle deleting attributes and new tokens.
- auto_ptr<ResolutionContext> ctx(
+ auto_ptr<ResolutionContext> ctx(
resolveAttributes(
application,
policy.getIssuerMetadata(),
tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end());
}
- return application.getServiceProvider().getSessionCache()->insert(
+ application.getServiceProvider().getSessionCache()->insert(
now + lifetime.second,
application,
- httpRequest.getRemoteAddr().c_str(),
+ httpRequest,
+ httpResponse,
policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL,
m_protocol.get(),
nameid.get(),
if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
// When out of process, we run natively.
- return doRequest(request.getApplication(), request.getRequestURL(), entityID.c_str(), request);
+ return doRequest(request.getApplication(), entityID.c_str(), request);
}
else {
// When not out of process, we remote the request.
DDF out,in(m_address.c_str());
DDFJanitor jin(in), jout(out);
in.addmember("application_id").string(request.getApplication().getId());
- in.addmember("url").string(request.getRequestURL());
in.addmember("entity_id").string(entityID.c_str());
out=request.getServiceProvider().getListenerService()->send(in);
return unwrap(request, out);
// Since we're remoted, the result should either be a throw, which we pass on,
// 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.
- doRequest(*app, in["url"].string(), in["entity_id"].string(), *resp.get());
+ doRequest(*app, in["entity_id"].string(), *resp.get());
out << ret;
#else
#endif
}
-pair<bool,long> ADFSLogoutInitiator::doRequest(
- const Application& application, const char* requestURL, const char* entityID, HTTPResponse& response
- ) const
+pair<bool,long> ADFSLogoutInitiator::doRequest(const Application& application, const char* entityID, HTTPResponse& response) const
{
#ifndef SHIBSP_LITE
try {
param = request.getParameter("wreply");
const Application& app = request.getApplication();
- // Get the session_id.
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
- const char* session_id = request.getCookie(shib_cookie.first.c_str());
-
if (!returning) {
// Pass control to the first front channel notification point, if any.
map<string,string> parammap;
}
// Best effort on back channel and to remove the user agent's session.
- if (session_id) {
+ string session_id = app.getServiceProvider().getSessionCache()->active(request, app);
+ if (!session_id.empty()) {
vector<string> sessions(1,session_id);
notifyBackChannel(app, request.getRequestURL(), sessions, false);
try {
- app.getServiceProvider().getSessionCache()->remove(session_id, app);
+ app.getServiceProvider().getSessionCache()->remove(request, &request, app);
}
catch (exception& ex) {
- m_log.error("error removing session (%s): %s", session_id, ex.what());
+ m_log.error("error removing session (%s): %s", session_id.c_str(), ex.what());
}
- request.setCookie(shib_cookie.first.c_str(), shib_cookie.second);
}
if (param)
else if (cache)
m_sessionTried = true;
- // Get session ID from cookie.
- const Application& app = getApplication();
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
- const char* session_id = getCookie(shib_cookie.first.c_str());
- if (!session_id || !*session_id)
- return NULL;
-
// Need address checking and timeout settings.
time_t timeout=0;
if (checkTimeout || !ignoreAddress) {
- const PropertySet* props=app.getPropertySet("Sessions");
+ const PropertySet* props=getApplication().getPropertySet("Sessions");
if (props) {
if (checkTimeout) {
pair<bool,unsigned int> p=props->getUnsignedInt("timeout");
// The cache will either silently pass a session or NULL back, or throw an exception out.
Session* session = getServiceProvider().getSessionCache()->find(
- session_id, app, ignoreAddress ? NULL : getRemoteAddr().c_str(), checkTimeout ? &timeout : NULL
+ *this, getApplication(), ignoreAddress ? NULL : getRemoteAddr().c_str(), checkTimeout ? &timeout : NULL
);
if (cache)
m_session = session;
#define __shibsp_sessioncache_h__
#include <shibsp/base.h>
-
#ifndef SHIBSP_LITE
# include <saml/saml1/core/Assertions.h>
# include <saml/saml2/metadata/Metadata.h>
#endif
#include <xmltooling/Lockable.h>
+#include <xmltooling/io/HTTPRequest.h>
+#include <xmltooling/io/HTTPResponse.h>
namespace shibsp {
#ifndef SHIBSP_LITE
/**
- * Inserts a new session into the cache.
+ * Inserts a new session into the cache and binds the session to the outgoing
+ * client response.
*
* <p>The SSO tokens and Attributes remain owned by the caller and are copied by the cache.
*
* @param expires expiration time of session
* @param application reference to Application that owns the Session
- * @param client_addr network address of client
+ * @param httpRequest request that initiated session
+ * @param httpResponse current response to client
* @param issuer issuing metadata of assertion issuer, if known
* @param protocol protocol family used to initiate the session
* @param nameid principal identifier, normalized to SAML 2, if any
* @param authncontext_decl specifics of authentication event, if known
* @param tokens assertions to cache with session, if any
* @param attributes optional array of resolved Attributes to cache with session
- * @return newly created session's key
*/
- virtual std::string insert(
+ virtual void insert(
time_t expires,
const Application& application,
- const char* client_addr=NULL,
+ const xmltooling::HTTPRequest& httpRequest,
+ xmltooling::HTTPResponse& httpResponse,
const opensaml::saml2md::EntityDescriptor* issuer=NULL,
const XMLCh* protocol=NULL,
const opensaml::saml2::NameID* nameid=NULL,
)=0;
/**
- * Determines whether a given session (based on its ID) matches a set of input
- * criteria.
+ * Determines whether the Session bound to a client request matches a set of input criteria.
*
- * @param key session key to check
+ * @param request request in which to locate Session
* @param issuer required source of session(s)
* @param nameid required name identifier
* @param indexes session indexes
* @param application reference to Application that owns the Session
- * @return true iff the session matches the input criteria
+ * @return true iff the Session exists and matches the input criteria
*/
virtual bool matches(
- const char* key,
+ const xmltooling::HTTPRequest& request,
const opensaml::saml2md::EntityDescriptor* issuer,
const opensaml::saml2::NameID& nameid,
const std::set<std::string>* indexes,
#endif
/**
- * Locates an existing session.
+ * Returns the ID of the session bound to the specified client request, if possible.
+ *
+ * @param request request from client containing session, or a reference to it
+ * @param application reference to Application that owns the Session
+ * @return ID of session, if any known, or an empty string
+ */
+ virtual std::string active(const xmltooling::HTTPRequest& request, const Application& application) const=0;
+
+ /**
+ * Locates an existing session by ID.
*
* <p>If the client address is supplied, then a check will be performed against
* the address recorded in the record.
virtual Session* find(
const char* key, const Application& application, const char* client_addr=NULL, time_t* timeout=NULL
)=0;
-
+
+ /**
+ * Locates an existing session bound to a request.
+ *
+ * <p>If the client address is supplied, then a check will be performed against
+ * the address recorded in the record.
+ *
+ * @param request request from client containing session, or a reference to it
+ * @param application reference to Application that owns the Session
+ * @param client_addr network address of client (if known)
+ * @param timeout inactivity timeout to enforce (0 for none, NULL to bypass check/update of last access)
+ * @return pointer to locked Session, or NULL
+ */
+ virtual Session* find(
+ const xmltooling::HTTPRequest& request, const Application& application, const char* client_addr=NULL, time_t* timeout=NULL
+ )=0;
+
/**
* Deletes an existing session.
*
* @param application reference to Application that owns the Session
*/
virtual void remove(const char* key, const Application& application)=0;
+
+ /**
+ * Deletes an existing session bound to a request.
+ *
+ * @param request request from client containing session, or a reference to it
+ * @param response optional response to client enabling removal of session or reference
+ * @param application reference to Application that owns the Session
+ */
+ virtual void remove(const xmltooling::HTTPRequest& request, xmltooling::HTTPResponse* response, const Application& application)=0;
};
/** SessionCache implementation backed by a StorageService. */
* @param response outgoing HTTP response
* @param relayState RelayState token to supply with message
*/
- virtual void preserveRelayState(const Application& application, xmltooling::HTTPResponse& response, std::string& relayState) const;
+ virtual void preserveRelayState(
+ const Application& application, xmltooling::HTTPResponse& response, std::string& relayState
+ ) const;
/**
* Implements various mechanisms to recover RelayState,
*
* @param application the associated Application
* @param request incoming HTTP request
+ * @param response outgoing HTTP response
* @param relayState RelayState token supplied with message
* @param clear true iff the token state should be cleared
*/
virtual void recoverRelayState(
- const Application& application, xmltooling::HTTPRequest& request, std::string& relayState, bool clear=true
+ const Application& application,
+ const xmltooling::HTTPRequest& request,
+ xmltooling::HTTPResponse& response,
+ std::string& relayState,
+ bool clear=true
) const;
/** Logging object. */
* @param httpRequest client request that initiated session
* @param issuedTo address for which security assertion was issued
*/
- void checkAddress(
- const Application& application, const xmltooling::HTTPRequest& httpRequest, const char* issuedTo
- ) const;
+ void checkAddress(const Application& application, const xmltooling::HTTPRequest& httpRequest, const char* issuedTo) const;
#ifndef SHIBSP_LITE
void generateMetadata(opensaml::saml2md::SPSSODescriptor& role, const char* handlerURL) const;
* Implement protocol-specific handling of the incoming decoded message.
*
* <p>The result of implementing the protocol should be an exception or
- * the key to a newly created session.
+ * modifications to the request/response objects to reflect processing
+ * of the message.
*
* @param application reference to application receiving message
* @param httpRequest client request that included message
+ * @param httpResponse response to client
* @param policy the SecurityPolicy in effect, after having evaluated the message
* @param settings policy configuration settings in effect
* @param xmlObject a protocol-specific message object
- * @return the key to the newly created session
*/
- virtual std::string implementProtocol(
+ virtual void implementProtocol(
const Application& application,
const xmltooling::HTTPRequest& httpRequest,
+ xmltooling::HTTPResponse& httpResponse,
opensaml::SecurityPolicy& policy,
const PropertySet* settings,
const xmltooling::XMLObject& xmlObject
#endif
private:
- std::string processMessage(
- const Application& application,
- xmltooling::HTTPRequest& httpRequest,
- std::string& entityID,
- std::string& relayState
+ std::pair<bool,long> processMessage(
+ const Application& application, const xmltooling::HTTPRequest& httpRequest, xmltooling::HTTPResponse& httpResponse
) const;
-
+
std::pair<bool,long> sendRedirect(
- SPRequest& request, const char* key, const char* entityID, const char* relayState
+ const Application& application,
+ const xmltooling::HTTPRequest& request,
+ xmltooling::HTTPResponse& response,
+ const char* entityID,
+ const char* relayState
+ ) const;
+
+ void maintainHistory(
+ const Application& application, const xmltooling::HTTPRequest& request, xmltooling::HTTPResponse& response, const char* entityID
) const;
-
- void maintainHistory(SPRequest& request, const char* entityID, const char* cookieProps) const;
#ifndef SHIBSP_LITE
opensaml::MessageDecoder* m_decoder;
throw ConfigurationException("Unsupported relayState mechanism ($1).", params(1,mech.second));
}
-void AbstractHandler::recoverRelayState(const Application& application, HTTPRequest& httpRequest, string& relayState, bool clear) const
+void AbstractHandler::recoverRelayState(
+ const Application& application, const HTTPRequest& request, HTTPResponse& response, string& relayState, bool clear
+ ) const
{
SPConfig& conf = SPConfig::getConfig();
}
}
- if (conf.isEnabled(SPConfig::InProcess)) {
- if (relayState == "cookie") {
- // Pull the value from the "relay state" cookie.
- pair<string,const char*> relay_cookie = application.getCookieNameProps("_shibstate_");
- // In process, we should be able to cast down to a full SPRequest.
- SPRequest& request = dynamic_cast<SPRequest&>(httpRequest);
- const char* state = request.getCookie(relay_cookie.first.c_str());
- if (state && *state) {
- // URL-decode the value.
- char* rscopy=strdup(state);
- XMLToolingConfig::getConfig().getURLEncoder()->decode(rscopy);
- relayState = rscopy;
- free(rscopy);
-
- if (clear)
- request.setCookie(relay_cookie.first.c_str(),relay_cookie.second);
- return;
- }
-
- relayState.erase();
- }
-
- // Check for "default" value.
- if (relayState.empty() || relayState == "default") {
- pair<bool,const char*> homeURL=application.getString("homeURL");
- relayState=homeURL.first ? homeURL.second : "/";
+ if (relayState == "cookie") {
+ // Pull the value from the "relay state" cookie.
+ pair<string,const char*> relay_cookie = application.getCookieNameProps("_shibstate_");
+ const char* state = request.getCookie(relay_cookie.first.c_str());
+ if (state && *state) {
+ // URL-decode the value.
+ char* rscopy=strdup(state);
+ XMLToolingConfig::getConfig().getURLEncoder()->decode(rscopy);
+ relayState = rscopy;
+ free(rscopy);
+
+ if (clear)
+ response.setCookie(relay_cookie.first.c_str(),relay_cookie.second);
return;
}
+
+ relayState.erase();
+ }
+
+ // Check for "default" value.
+ if (relayState.empty() || relayState == "default") {
+ pair<bool,const char*> homeURL=application.getString("homeURL");
+ relayState=homeURL.first ? homeURL.second : "/";
+ return;
}
if (relayState == "default")
string relayState;
SPConfig& conf = SPConfig::getConfig();
- try {
- if (conf.isEnabled(SPConfig::OutOfProcess)) {
- // When out of process, we run natively and directly process the message.
- // RelayState will be fully handled during message processing.
- string entityID;
- string key = processMessage(request.getApplication(), request, entityID, relayState);
- return sendRedirect(request, key.c_str(), entityID.c_str(), relayState.c_str());
- }
- else {
- // When not out of process, we remote all the message processing.
- DDF out,in = wrap(request);
- DDFJanitor jin(in), jout(out);
-
- try {
- out=request.getServiceProvider().getListenerService()->send(in);
- }
- catch (XMLToolingException& ex) {
- // Try for RelayState recovery.
- if (ex.getProperty("RelayState"))
- relayState = ex.getProperty("RelayState");
- try {
- recoverRelayState(request.getApplication(), request, relayState);
- }
- catch (exception& ex2) {
- m_log.error("trapped an error during RelayState recovery while handling an error: %s", ex2.what());
- }
- throw;
- }
-
- // We invoke RelayState recovery one last time on this side of the boundary.
- if (out["RelayState"].isstring())
- relayState = out["RelayState"].string();
- recoverRelayState(request.getApplication(), request, relayState);
-
- // If it worked, we have a session key.
- if (!out["key"].isstring())
- throw FatalProfileException("Remote processing of SSO profile did not return a usable session key.");
-
- // Take care of cookie business and wrap it up.
- return sendRedirect(request, out["key"].string(), out["entity_id"].string(), relayState.c_str());
- }
+ if (conf.isEnabled(SPConfig::OutOfProcess)) {
+ // When out of process, we run natively and directly process the message.
+ return processMessage(request.getApplication(), request, request);
}
- catch (XMLToolingException& ex) {
- // Try and preserve RelayState.
- if (!relayState.empty())
- ex.addProperty("RelayState", relayState.c_str());
- throw;
+ else {
+ // When not out of process, we remote all the message processing.
+ vector<string> headers(1, "Cookie");
+ DDF out,in = wrap(request, &headers);
+ DDFJanitor jin(in), jout(out);
+ out=request.getServiceProvider().getListenerService()->send(in);
+ return unwrap(request, out);
}
}
}
// Unpack the request.
- auto_ptr<HTTPRequest> http(getRequest(in));
-
- // Do the work.
- string relayState, entityID;
- try {
- string key = processMessage(*app, *http.get(), entityID, relayState);
-
- // Repack for return to caller.
- DDF ret=DDF(NULL).structure();
- DDFJanitor jret(ret);
- ret.addmember("key").string(key.c_str());
- if (!entityID.empty())
- ret.addmember("entity_id").string(entityID.c_str());
- if (!relayState.empty())
- ret.addmember("RelayState").string(relayState.c_str());
- out << ret;
- }
- catch (XMLToolingException& ex) {
- // Try and preserve RelayState if we can.
- if (!relayState.empty())
- ex.addProperty("RelayState", relayState.c_str());
- throw;
- }
+ auto_ptr<HTTPRequest> req(getRequest(in));
+
+ // Wrap a response shim.
+ DDF ret(NULL);
+ DDFJanitor jout(ret);
+ auto_ptr<HTTPResponse> resp(getResponse(ret));
+
+ // 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, *req.get(), *resp.get());
+ out << ret;
}
-string AssertionConsumerService::processMessage(
- const Application& application, HTTPRequest& httpRequest, string& entityID, string& relayState
+pair<bool,long> AssertionConsumerService::processMessage(
+ const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse
) const
{
#ifndef SHIBSP_LITE
// Create the policy.
shibsp::SecurityPolicy policy(application, &m_role, validate.first && validate.second);
- // Decode the message and process it in a protocol-specific way.
- auto_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, policy));
- if (!msg.get())
- throw BindingException("Failed to decode an SSO protocol response.");
- recoverRelayState(application, httpRequest, relayState);
- string key = implementProtocol(application, httpRequest, policy, settings, *msg.get());
-
- auto_ptr_char issuer(policy.getIssuer() ? policy.getIssuer()->getName() : NULL);
- if (issuer.get())
- entityID = issuer.get();
-
- return key;
+ string relayState;
+
+ try {
+ // Decode the message and process it in a protocol-specific way.
+ auto_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, policy));
+ if (!msg.get())
+ throw BindingException("Failed to decode an SSO protocol response.");
+ recoverRelayState(application, httpRequest, httpResponse, relayState);
+ implementProtocol(application, httpRequest, httpResponse, policy, settings, *msg.get());
+
+ auto_ptr_char issuer(policy.getIssuer() ? policy.getIssuer()->getName() : NULL);
+
+ // History cookie.
+ if (issuer.get() && *issuer.get())
+ maintainHistory(application, httpRequest, httpResponse, issuer.get());
+
+ // Now redirect to the state value. By now, it should be set to *something* usable.
+ return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
+ }
+ catch (XMLToolingException& ex) {
+ if (!relayState.empty())
+ ex.addProperty("RelayState", relayState.c_str());
+ throw;
+ }
#else
throw ConfigurationException("Cannot process message using lite version of shibsp library.");
#endif
}
-pair<bool,long> AssertionConsumerService::sendRedirect(
- SPRequest& request, const char* key, const char* entityID, const char* relayState
- ) const
-{
- // We've got a good session, so set the session cookie.
- pair<string,const char*> shib_cookie=request.getApplication().getCookieNameProps("_shibsession_");
- string k(key);
- k += shib_cookie.second;
- request.setCookie(shib_cookie.first.c_str(), k.c_str());
-
- // History cookie.
- maintainHistory(request, entityID, shib_cookie.second);
-
- // Now redirect to the state value. By now, it should be set to *something* usable.
- return make_pair(true, request.sendRedirect(relayState));
-}
-
-void AssertionConsumerService::checkAddress(
- const Application& application, const HTTPRequest& httpRequest, const char* issuedTo
- ) const
+void AssertionConsumerService::checkAddress(const Application& application, const HTTPRequest& httpRequest, const char* issuedTo) const
{
const PropertySet* props=application.getPropertySet("Sessions");
pair<bool,bool> checkAddress = props ? props->getBool("checkAddress") : make_pair(false,true);
#endif
-void AssertionConsumerService::maintainHistory(SPRequest& request, const char* entityID, const char* cookieProps) const
+void AssertionConsumerService::maintainHistory(
+ const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* entityID
+ ) const
{
- if (!entityID)
- return;
-
- const PropertySet* sessionProps=request.getApplication().getPropertySet("Sessions");
+ static const char* defProps="; path=/";
+
+ const PropertySet* sessionProps=application.getPropertySet("Sessions");
pair<bool,bool> idpHistory=sessionProps->getBool("idpHistory");
+
if (!idpHistory.first || idpHistory.second) {
+ pair<bool,const char*> cookieProps=sessionProps->getString("cookieProps");
+ if (!cookieProps.first)
+ cookieProps.second=defProps;
+
// Set an IdP history cookie locally (essentially just a CDC).
CommonDomainCookie cdc(request.getCookie(CommonDomainCookie::CDCName));
// Either leave in memory or set an expiration.
pair<bool,unsigned int> days=sessionProps->getUnsignedInt("idpHistoryDays");
if (!days.first || days.second==0) {
- string c = string(cdc.set(entityID)) + cookieProps;
- request.setCookie(CommonDomainCookie::CDCName, c.c_str());
+ string c = string(cdc.set(entityID)) + cookieProps.second;
+ response.setCookie(CommonDomainCookie::CDCName, c.c_str());
}
else {
time_t now=time(NULL) + (days.second * 24 * 60 * 60);
#endif
char timebuf[64];
strftime(timebuf,64,"%a, %d %b %Y %H:%M:%S GMT",ptime);
- string c = string(cdc.set(entityID)) + cookieProps + "; expires=" + timebuf;
- request.setCookie(CommonDomainCookie::CDCName, c.c_str());
+ string c = string(cdc.set(entityID)) + cookieProps.second + "; expires=" + timebuf;
+ response.setCookie(CommonDomainCookie::CDCName, c.c_str());
}
}
}
}
else {
// When not out of process, we remote all the message processing.
- DDF out,in = wrap(request, NULL, true);
+ DDF out,in = wrap(request);
DDFJanitor jin(in), jout(out);
out=request.getServiceProvider().getListenerService()->send(in);
m_log.debug("processing assertion lookup request (session: %s, assertion: %s)", key, ID);
// The cache will either silently pass a session or NULL back, or throw an exception out.
- Session* session = application.getServiceProvider().getSessionCache()->find(key, application);
+ Session* session = application.getServiceProvider().getSessionCache()->find(httpRequest, application);
if (!session) {
m_log.error("valid session (%s) not found for assertion lookup", key);
throw FatalProfileException("Session key not found.");
if (ret.first)
return ret;
- // Get session ID from cookie.
- pair<string,const char*> shib_cookie = request.getApplication().getCookieNameProps("_shibsession_");
- const char* session_id = request.getCookie(shib_cookie.first.c_str());
- if (session_id) {
+ const Application& app = request.getApplication();
+ string session_id = app.getServiceProvider().getSessionCache()->active(request, app);
+ if (!session_id.empty()) {
// Do back channel notification.
vector<string> sessions(1, session_id);
- if (!notifyBackChannel(request.getApplication(), request.getRequestURL(), sessions, true)) {
- request.getApplication().getServiceProvider().getSessionCache()->remove(session_id, request.getApplication());
- return sendLogoutPage(request.getApplication(), request, true, "Partial logout failure.");
+ if (!notifyBackChannel(app, request.getRequestURL(), sessions, true)) {
+ app.getServiceProvider().getSessionCache()->remove(request, &request, app);
+ return sendLogoutPage(app, request, true, "Partial logout failure.");
}
- request.getServiceProvider().getSessionCache()->remove(session_id, request.getApplication());
-
- // Clear the cookie.
- pair<string,const char*> shib_cookie=request.getApplication().getCookieNameProps("_shibsession_");
- request.setCookie(shib_cookie.first.c_str(), shib_cookie.second);
+ request.getServiceProvider().getSessionCache()->remove(request, &request, app);
}
- return sendLogoutPage(request.getApplication(), request, true, "Logout was successful.");
+ return sendLogoutPage(app, request, true, "Logout was successful.");
}
}
private:
- string implementProtocol(
+ void implementProtocol(
const Application& application,
const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse,
SecurityPolicy& policy,
const PropertySet* settings,
const XMLObject& xmlObject
#ifndef SHIBSP_LITE
-string SAML1Consumer::implementProtocol(
+void SAML1Consumer::implementProtocol(
const Application& application,
const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse,
SecurityPolicy& policy,
const PropertySet* settings,
const XMLObject& xmlObject
// Now merge in bad tokens for caching.
tokens.insert(tokens.end(), badtokens.begin(), badtokens.end());
- return application.getServiceProvider().getSessionCache()->insert(
+ application.getServiceProvider().getSessionCache()->insert(
now + lifetime.second,
application,
- httpRequest.getRemoteAddr().c_str(),
+ httpRequest,
+ httpResponse,
policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL,
(!response->getMinorVersion().first || response->getMinorVersion().second==1) ?
samlconstants::SAML11_PROTOCOL_ENUM : samlconstants::SAML10_PROTOCOL_ENUM,
}
private:
- string implementProtocol(
+ void implementProtocol(
const Application& application,
const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse,
SecurityPolicy& policy,
const PropertySet* settings,
const XMLObject& xmlObject
#ifndef SHIBSP_LITE
-string SAML2Consumer::implementProtocol(
+void SAML2Consumer::implementProtocol(
const Application& application,
const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse,
SecurityPolicy& policy,
const PropertySet* settings,
const XMLObject& xmlObject
// Now merge in bad tokens for caching.
tokens.insert(tokens.end(), badtokens.begin(), badtokens.end());
- string key = application.getServiceProvider().getSessionCache()->insert(
+ application.getServiceProvider().getSessionCache()->insert(
sessionExp,
application,
- httpRequest.getRemoteAddr().c_str(),
+ httpRequest,
+ httpResponse,
policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL,
samlconstants::SAML20P_NS,
ssoName,
if (ownedName)
delete ssoName;
for_each(ownedtokens.begin(), ownedtokens.end(), xmltooling::cleanup<saml2::Assertion>());
- return key;
}
catch (exception&) {
if (ownedName)
#endif
private:
- pair<bool,long> doRequest(
- const Application& application, const char* session_id, const HTTPRequest& httpRequest, HTTPResponse& httpResponse
- ) const;
+ pair<bool,long> doRequest(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
#ifndef SHIBSP_LITE
- bool stronglyMatches(const XMLCh* idp, const XMLCh* sp, const saml2::NameID& n1, const saml2::NameID& n2) const;
-
pair<bool,long> sendResponse(
const XMLCh* requestID,
const XMLCh* code,
if (ret.first)
return ret;
- // Get the session_id in case this is a front-channel LogoutRequest.
- pair<string,const char*> shib_cookie = request.getApplication().getCookieNameProps("_shibsession_");
- const char* session_id = request.getCookie(shib_cookie.first.c_str());
-
SPConfig& conf = SPConfig::getConfig();
if (conf.isEnabled(SPConfig::OutOfProcess)) {
// When out of process, we run natively and directly process the message.
- return doRequest(request.getApplication(), session_id, request, request);
+ return doRequest(request.getApplication(), request, request);
}
else {
// When not out of process, we remote all the message processing.
- DDF out,in = wrap(request, NULL, true);
+ vector<string> headers(1,"Cookie");
+ DDF out,in = wrap(request, &headers, true);
DDFJanitor jin(in), jout(out);
- if (session_id)
- in.addmember("session_id").string(session_id);
out=request.getServiceProvider().getListenerService()->send(in);
return unwrap(request, out);
}
}
// Unpack the request.
+ auto_ptr<HTTPRequest> req(getRequest(in));
+
+ // Wrap a response shim.
DDF ret(NULL);
DDFJanitor jout(ret);
- auto_ptr<HTTPRequest> req(getRequest(in));
auto_ptr<HTTPResponse> resp(getResponse(ret));
// Since we're remoted, the result should either be a throw, which we pass on,
// 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.
- doRequest(*app, in["session_id"].string(), *req.get(), *resp.get());
+ doRequest(*app, *req.get(), *resp.get());
out << ret;
}
-pair<bool,long> SAML2Logout::doRequest(
- const Application& application, const char* session_id, const HTTPRequest& request, HTTPResponse& response
- ) const
+pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTTPRequest& request, HTTPResponse& response) const
{
#ifndef SHIBSP_LITE
+ // First capture the active session ID.
SessionCache* cache = application.getServiceProvider().getSessionCache();
- if (!strcmp(request.getMethod(),"GET") && request.getParameter("notifying")) {
+ string session_id = cache->active(request, application);
+ if (!strcmp(request.getMethod(),"GET") && request.getParameter("notifying")) {
// This is returning from a front-channel notification, so we have to do the back-channel and then
// respond. To do that, we need state from the original request.
if (!request.getParameter("entityID")) {
- if (session_id) {
- cache->remove(session_id, application);
- // Clear the cookie.
- pair<string,const char*> shib_cookie=application.getCookieNameProps("_shibsession_");
- response.setCookie(shib_cookie.first.c_str(), shib_cookie.second);
- }
+ cache->remove(request, &response, application);
throw FatalProfileException("Application notification loop did not return entityID for LogoutResponse.");
}
// Best effort on back channel and to remove the user agent's session.
bool worked1 = false,worked2 = false;
- if (session_id) {
+ if (!session_id.empty()) {
vector<string> sessions(1,session_id);
worked1 = notifyBackChannel(application, request.getRequestURL(), sessions, false);
try {
- cache->remove(session_id, application);
+ cache->remove(request, &response, application);
worked2 = true;
}
catch (exception& ex) {
m_log.error("error removing session (%s): %s", session_id, ex.what());
}
-
- // Clear the cookie.
- pair<string,const char*> shib_cookie=application.getCookieNameProps("_shibsession_");
- response.setCookie(shib_cookie.first.c_str(), shib_cookie.second);
}
else {
worked1 = worked2 = true;
// Message from IdP to logout one or more sessions.
// If this is front-channel, we have to have a session_id to use already.
- if (m_decoder->isUserAgentPresent() && !session_id) {
+ if (m_decoder->isUserAgentPresent() && session_id.empty()) {
m_log.error("no active session");
return sendResponse(
logoutRequest->getID(),
// For a front-channel LogoutRequest, we have to match the information in the request
// against the current session.
- if (session_id) {
- if (!cache->matches(session_id, entity, *nameid, &indexes, application)) {
+ if (!session_id.empty()) {
+ if (!cache->matches(request, entity, *nameid, &indexes, application)) {
return sendResponse(
logoutRequest->getID(),
- StatusCode::REQUESTER, StatusCode::REQUEST_DENIED, "Active sessions did not match logout request.",
+ StatusCode::REQUESTER, StatusCode::REQUEST_DENIED, "Active session did not match logout request.",
relayState.c_str(),
policy.getIssuerMetadata(),
application,
// Now we actually terminate everything except for the active session,
// if this is front-channel, for notification purposes.
for (vector<string>::const_iterator sit = sessions.begin(); sit != sessions.end(); ++sit)
- if (session_id && strcmp(sit->c_str(), session_id))
- cache->remove(sit->c_str(), application);
+ if (*sit != session_id)
+ cache->remove(sit->c_str(), application); // using the ID-based removal operation
}
catch (exception& ex) {
m_log.error("error while logging out matching sessions: %s", ex.what());
// For back-channel requests, or if no front-channel notification is needed...
bool worked1 = false,worked2 = false;
worked1 = notifyBackChannel(application, request.getRequestURL(), sessions, false);
- if (session_id) {
+ if (!session_id.empty()) {
// One last session to yoink...
try {
- cache->remove(session_id, application);
+ cache->remove(request, &response, application);
worked2 = true;
}
catch (exception& ex) {
- m_log.error("error removing active session (%s): %s", session_id, ex.what());
+ m_log.error("error removing active session (%s): %s", session_id.c_str(), ex.what());
}
-
- // Clear the cookie.
- pair<string,const char*> shib_cookie=application.getCookieNameProps("_shibsession_");
- response.setCookie(shib_cookie.first.c_str(), shib_cookie.second);
}
return sendResponse(
#ifndef SHIBSP_LITE
-bool SAML2Logout::stronglyMatches(const XMLCh* idp, const XMLCh* sp, const saml2::NameID& n1, const saml2::NameID& n2) const
-{
- if (!XMLString::equals(n1.getName(), n2.getName()))
- return false;
-
- const XMLCh* s1 = n1.getFormat();
- const XMLCh* s2 = n2.getFormat();
- if (!s1 || !*s1)
- s1 = saml2::NameID::UNSPECIFIED;
- if (!s2 || !*s2)
- s2 = saml2::NameID::UNSPECIFIED;
- if (!XMLString::equals(s1,s2))
- return false;
-
- s1 = n1.getNameQualifier();
- s2 = n2.getNameQualifier();
- if (!s1 || !*s1)
- s1 = idp;
- if (!s2 || !*s2)
- s2 = idp;
- if (!XMLString::equals(s1,s2))
- return false;
-
- s1 = n1.getSPNameQualifier();
- s2 = n2.getSPNameQualifier();
- if (!s1 || !*s1)
- s1 = sp;
- if (!s2 || !*s2)
- s2 = sp;
- if (!XMLString::equals(s1,s2))
- return false;
-
- return true;
-}
-
pair<bool,long> SAML2Logout::sendResponse(
const XMLCh* requestID,
const XMLCh* code,
#endif
private:
- pair<bool,long> doRequest(const Application& application, const char* requestURL, Session* session, HTTPResponse& httpResponse) const;
+ pair<bool,long> doRequest(
+ const Application& application, const HTTPRequest& request, HTTPResponse& httpResponse, Session* session
+ ) const;
string m_appId;
#ifndef SHIBSP_LITE
if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
// When out of process, we run natively.
- return doRequest(request.getApplication(), request.getRequestURL(), session, request);
+ return doRequest(request.getApplication(), request, request, session);
}
else {
// When not out of process, we remote the request.
- Locker locker(session, false);
- DDF out,in(m_address.c_str());
+ session->unlock();
+ vector<string> headers(1,"Cookie");
+ DDF out,in = wrap(request,&headers);
DDFJanitor jin(in), jout(out);
- in.addmember("application_id").string(request.getApplication().getId());
- in.addmember("session_id").string(session->getID());
- in.addmember("url").string(request.getRequestURL());
out=request.getServiceProvider().getListenerService()->send(in);
return unwrap(request, out);
}
throw ConfigurationException("Unable to locate application for logout, deleted?");
}
+ // Unpack the request.
+ auto_ptr<HTTPRequest> req(getRequest(in));
+
// Set up a response shim.
DDF ret(NULL);
DDFJanitor jout(ret);
Session* session = NULL;
try {
- session = app->getServiceProvider().getSessionCache()->find(in["session_id"].string(), *app, NULL, NULL);
+ session = app->getServiceProvider().getSessionCache()->find(*req.get(), *app, NULL, NULL);
}
catch (exception& ex) {
m_log.error("error accessing current session: %s", ex.what());
// Since we're remoted, the result should either be a throw, which we pass on,
// 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.
- doRequest(*app, in["url"].string(), session, *resp.get());
+ doRequest(*app, *req.get(), *resp.get(), session);
}
else {
m_log.error("no NameID or issuing entityID found in session");
session->unlock();
- app->getServiceProvider().getSessionCache()->remove(in["session_id"].string(), *app);
-
- // Clear the cookie.
- pair<string,const char*> shib_cookie=app->getCookieNameProps("_shibsession_");
- resp->setCookie(shib_cookie.first.c_str(), shib_cookie.second);
+ app->getServiceProvider().getSessionCache()->remove(*req.get(), resp.get(), *app);
}
}
out << ret;
}
pair<bool,long> SAML2LogoutInitiator::doRequest(
- const Application& application, const char* requestURL, Session* session, HTTPResponse& response
+ const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, Session* session
) const
{
- // Clear the cookie.
- pair<string,const char*> shib_cookie=application.getCookieNameProps("_shibsession_");
- response.setCookie(shib_cookie.first.c_str(), shib_cookie.second);
-
// Do back channel notification.
vector<string> sessions(1, session->getID());
- if (!notifyBackChannel(application, requestURL, sessions, false)) {
+ if (!notifyBackChannel(application, httpRequest.getRequestURL(), sessions, false)) {
session->unlock();
- application.getServiceProvider().getSessionCache()->remove(sessions.front().c_str(), application);
- return sendLogoutPage(application, response, true, "Partial logout failure.");
+ application.getServiceProvider().getSessionCache()->remove(httpRequest, &httpResponse, application);
+ return sendLogoutPage(application, httpResponse, true, "Partial logout failure.");
}
#ifndef SHIBSP_LITE
}
if (!logoutResponse)
- ret = sendLogoutPage(application, response, false, "Identity provider did not respond to logout request.");
+ ret = sendLogoutPage(application, httpResponse, false, "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;
- ret = sendLogoutPage(application, response, false, "Identity provider returned a SAML error in response to logout request.");
+ ret = sendLogoutPage(application, httpResponse, false, "Identity provider returned a SAML error in response to logout request.");
}
else {
delete logoutResponse;
- ret = sendLogoutPage(application, response, false, "Logout completed successfully.");
+ ret = sendLogoutPage(application, httpResponse, false, "Logout completed successfully.");
}
if (session) {
- string session_id = session->getID();
session->unlock();
session = NULL;
- application.getServiceProvider().getSessionCache()->remove(session_id.c_str(), application);
+ application.getServiceProvider().getSessionCache()->remove(httpRequest, &httpResponse, application);
}
return ret;
}
msg->setDestination(ep->getLocation());
auto_ptr_char dest(ep->getLocation());
- ret.second = sendMessage(*encoder, msg.get(), NULL, dest.get(), role, application, response);
+ ret.second = sendMessage(*encoder, msg.get(), NULL, dest.get(), role, application, httpResponse);
ret.first = true;
msg.release(); // freed by encoder
}
}
if (session) {
- string session_id = session->getID();
session->unlock();
session = NULL;
- application.getServiceProvider().getSessionCache()->remove(session_id.c_str(), application);
+ application.getServiceProvider().getSessionCache()->remove(httpRequest, &httpResponse, application);
}
return ret;
#else
- string session_id = session->getID();
session->unlock();
- application.getServiceProvider().getSessionCache()->remove(session_id.c_str(), application);
+ application.getServiceProvider().getSessionCache()->remove(httpRequest, &httpResponse, application);
throw ConfigurationException("Cannot perform logout using lite version of shibsp library.");
#endif
}
#endif
private:
- pair<bool,long> doRequest(
- const Application& application, const char* session_id, const HTTPRequest& httpRequest, HTTPResponse& httpResponse
- ) const;
+ pair<bool,long> doRequest(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
#ifndef SHIBSP_LITE
- bool stronglyMatches(const XMLCh* idp, const XMLCh* sp, const saml2::NameID& n1, const saml2::NameID& n2) const;
bool notifyBackChannel(const Application& application, const char* requestURL, const NameID& nameid, const NewID* newid) const;
pair<bool,long> sendResponse(
pair<bool,long> SAML2NameIDMgmt::run(SPRequest& request, bool isHandler) const
{
- // Get the session_id in case this is a front-channel request.
- pair<string,const char*> shib_cookie = request.getApplication().getCookieNameProps("_shibsession_");
- const char* session_id = request.getCookie(shib_cookie.first.c_str());
-
SPConfig& conf = SPConfig::getConfig();
if (conf.isEnabled(SPConfig::OutOfProcess)) {
// When out of process, we run natively and directly process the message.
- return doRequest(request.getApplication(), session_id, request, request);
+ return doRequest(request.getApplication(), request, request);
}
else {
// When not out of process, we remote all the message processing.
- DDF out,in = wrap(request, NULL, true);
+ vector<string> headers(1,"Cookie");
+ DDF out,in = wrap(request, &headers, true);
DDFJanitor jin(in), jout(out);
- if (session_id)
- in.addmember("session_id").string(session_id);
out=request.getServiceProvider().getListenerService()->send(in);
return unwrap(request, out);
}
}
// Unpack the request.
+ auto_ptr<HTTPRequest> req(getRequest(in));
+
+ // Wrap a response shim.
DDF ret(NULL);
DDFJanitor jout(ret);
- auto_ptr<HTTPRequest> req(getRequest(in));
auto_ptr<HTTPResponse> resp(getResponse(ret));
// Since we're remoted, the result should either be a throw, which we pass on,
// 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.
- doRequest(*app, in["session_id"].string(), *req.get(), *resp.get());
+ doRequest(*app, *req.get(), *resp.get());
out << ret;
}
pair<bool,long> SAML2NameIDMgmt::doRequest(
- const Application& application, const char* session_id, const HTTPRequest& request, HTTPResponse& response
+ const Application& application, const HTTPRequest& request, HTTPResponse& response
) const
{
#ifndef SHIBSP_LITE
throw SecurityPolicyException("Security of ManageNameIDRequest not established.");
// Message from IdP to change or terminate a NameID.
-
+
// If this is front-channel, we have to have a session_id to use already.
- if (m_decoder->isUserAgentPresent() && !session_id) {
+ string session_id = cache->active(request, application);
+ if (m_decoder->isUserAgentPresent() && session_id.empty()) {
m_log.error("no active session");
return sendResponse(
mgmtRequest->getID(),
true
);
}
-
+
bool ownedName = false;
NameID* nameid = mgmtRequest->getNameID();
if (!nameid) {
// 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) {
- if (!cache->matches(session_id, entity, *nameid, NULL, application)) {
+ if (!session_id.empty()) {
+ if (!cache->matches(request, entity, *nameid, NULL, application)) {
return sendResponse(
mgmtRequest->getID(),
StatusCode::REQUESTER, StatusCode::REQUEST_DENIED, "Active session did not match NameID mgmt request.",
#ifndef SHIBSP_LITE
-bool SAML2NameIDMgmt::stronglyMatches(const XMLCh* idp, const XMLCh* sp, const saml2::NameID& n1, const saml2::NameID& n2) const
-{
- if (!XMLString::equals(n1.getName(), n2.getName()))
- return false;
-
- const XMLCh* s1 = n1.getFormat();
- const XMLCh* s2 = n2.getFormat();
- if (!s1 || !*s1)
- s1 = saml2::NameID::UNSPECIFIED;
- if (!s2 || !*s2)
- s2 = saml2::NameID::UNSPECIFIED;
- if (!XMLString::equals(s1,s2))
- return false;
-
- s1 = n1.getNameQualifier();
- s2 = n2.getNameQualifier();
- if (!s1 || !*s1)
- s1 = idp;
- if (!s2 || !*s2)
- s2 = idp;
- if (!XMLString::equals(s1,s2))
- return false;
-
- s1 = n1.getSPNameQualifier();
- s2 = n2.getSPNameQualifier();
- if (!s1 || !*s1)
- s1 = sp;
- if (!s2 || !*s2)
- s2 = sp;
- if (!XMLString::equals(s1,s2))
- return false;
-
- return true;
-}
-
pair<bool,long> SAML2NameIDMgmt::sendResponse(
const XMLCh* requestID,
const XMLCh* code,
if (acsByIndex.first && !acsByIndex.second) {
// Since we're passing the ACS by value, we need to compute the return URL,
// so we'll need the target resource for real.
- recoverRelayState(request.getApplication(), request, target, false);
+ recoverRelayState(request.getApplication(), request, request, target, false);
}
option = request.getParameter("isPassive");
option = request.getParameter("target");
if (option)
target = option;
- recoverRelayState(request.getApplication(), request, target, false);
+ recoverRelayState(request.getApplication(), request, request, target, false);
option = request.getParameter("isPassive");
if (option)
// Since we're passing the ACS by value, we need to compute the return URL,
// so we'll need the target resource for real.
- recoverRelayState(request.getApplication(), request, target, false);
+ recoverRelayState(request.getApplication(), request, request, target, false);
}
else {
// We're running as a "virtual handler" from within the filter.
option = request.getParameter("target");
if (option)
target = option;
- recoverRelayState(request.getApplication(), request, target, false);
+ recoverRelayState(request.getApplication(), request, request, target, false);
}
else {
// We're running as a "virtual handler" from within the filter.
#ifndef SHIBSP_LITE
void receive(DDF& in, ostream& out);
- string insert(
+ void insert(
time_t expires,
const Application& application,
- const char* client_addr=NULL,
+ const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse,
const saml2md::EntityDescriptor* issuer=NULL,
const XMLCh* protocol=NULL,
const saml2::NameID* nameid=NULL,
vector<string>& sessions
);
bool matches(
- const char* key,
+ const xmltooling::HTTPRequest& request,
const saml2md::EntityDescriptor* issuer,
const saml2::NameID& nameid,
const set<string>* indexes,
void remove(const char* key, const Application& application);
void test();
+ string active(const xmltooling::HTTPRequest& request, const Application& application) const {
+ pair<string,const char*> shib_cookie = application.getCookieNameProps("_shibsession_");
+ const char* session_id = request.getCookie(shib_cookie.first.c_str());
+ return (session_id ? session_id : "");
+ }
+
+ Session* find(const HTTPRequest& request, const Application& application, const char* client_addr=NULL, time_t* timeout=NULL) {
+ string id = active(request, application);
+ if (!id.empty())
+ return find(id.c_str(), application, client_addr, timeout);
+ return NULL;
+ }
+
+ void remove(const HTTPRequest& request, HTTPResponse* response, const Application& application) {
+ pair<string,const char*> shib_cookie = application.getCookieNameProps("_shibsession_");
+ const char* session_id = request.getCookie(shib_cookie.first.c_str());
+ if (session_id && *session_id) {
+ if (response)
+ response->setCookie(shib_cookie.first.c_str(), shib_cookie.second);
+ remove(session_id, application);
+ }
+ }
+
void cleanup();
Category& m_log;
}
}
-string SSCache::insert(
+void SSCache::insert(
time_t expires,
const Application& application,
- const char* client_addr,
+ const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse,
const saml2md::EntityDescriptor* issuer,
const XMLCh* protocol,
const saml2::NameID* nameid,
strftime(timebuf,32,"%Y-%m-%dT%H:%M:%SZ",ptime);
obj.addmember("expires").string(timebuf);
- if (client_addr)
- obj.addmember("client_addr").string(client_addr);
+ obj.addmember("client_addr").string(httpRequest.getRemoteAddr().c_str());
if (issuer)
obj.addmember("entity_id").string(entity_id.get());
if (protocol) {
}
const char* pid = obj["entity_id"].string();
- m_log.info("new session created: SessionID (%s) IdP (%s) Address (%s)", key.get(), pid ? pid : "none", client_addr);
+ m_log.info("new session created: SessionID (%s) IdP (%s) Address (%s)", key.get(), pid ? pid : "none", httpRequest.getRemoteAddr().c_str());
// Transaction Logging
TransactionLog* xlog = application.getServiceProvider().getTransactionLog();
") for principal from (IdP: " <<
(pid ? pid : "none") <<
") at (ClientAddress: " <<
- (client_addr ? client_addr : "none") <<
+ httpRequest.getRemoteAddr() <<
") with (NameIdentifier: " <<
(nameid ? name.get() : "none") <<
")";
xlog->log.info("}");
}
- return key.get();
+ pair<string,const char*> shib_cookie = application.getCookieNameProps("_shibsession_");
+ string k(key.get());\r
+ k += shib_cookie.second;
+ httpResponse.setCookie(shib_cookie.first.c_str(), k.c_str());
}
bool SSCache::matches(
- const char* key,
+ const xmltooling::HTTPRequest& request,
const saml2md::EntityDescriptor* issuer,
const saml2::NameID& nameid,
const set<string>* indexes,
{
auto_ptr_char entityID(issuer ? issuer->getEntityID() : NULL);
try {
- Session* session = find(key, application);
+ Session* session = find(request, application);
if (session) {
Locker locker(session, false);
if (XMLString::equals(session->getEntityID(), entityID.get()) && session->getNameID() &&
}
}
catch (exception& ex) {
- m_log.error("error while matching session (%s): %s", key, ex.what());
+ m_log.error("error while matching session: %s", ex.what());
}
return false;
}
}
private:
- string implementProtocol(
+ void implementProtocol(
const Application& application,
const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse,
SecurityPolicy& policy,
const PropertySet* settings,
const XMLObject& xmlObject