using namespace xmltooling::logging;
using namespace xmltooling;
using namespace xercesc;
+using namespace boost;
using namespace std;
#define WSFED_NS "http://schemas.xmlsoap.org/ws/2003/07/secext"
return m_binding.get();
}
+#ifndef SHIBSP_LITE
+ void generateMetadata(saml2md::SPSSODescriptor& role, const char* handlerURL) const {
+ doGenerateMetadata(role, handlerURL);
+ }
+#endif
+
private:
pair<bool,long> doRequest(
const Application& application,
{
// We have to know the IdP to function.
if (entityID.empty() || !checkCompatibility(request, isHandler))
- return make_pair(false,0L);
+ return make_pair(false, 0L);
string target;
pair<bool,const char*> prop;
pair<bool,const char*> acClass;
- const Handler* ACS=nullptr;
- const Application& app=request.getApplication();
+ const Handler* ACS = nullptr;
+ const Application& app = request.getApplication();
if (isHandler) {
prop.second = request.getParameter("acsIndex");
// 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(app, request, request, target, false);
+ app.limitRedirect(request, target.c_str());
acClass = getString("authnContextClassRef", request);
}
// Since we're not passing by index, we need to fully compute the return URL.
// Compute the ACS URL. We add the ACS location to the base handlerURL.
- string ACSloc=request.getHandlerURL(target.c_str());
+ string ACSloc = request.getHandlerURL(target.c_str());
prop = ACS->getString("Location");
if (prop.first)
ACSloc += prop.second;
void ADFSSessionInitiator::receive(DDF& in, ostream& out)
{
// Find application.
- const char* aid=in["application_id"].string();
- const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+ const char* aid = in["application_id"].string();
+ const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
if (!app) {
// Something's horribly wrong.
m_log.error("couldn't find application (%s) to generate ADFS request", aid ? aid : "(missing)");
DDFJanitor jout(ret);
// Wrap the outgoing object with a Response facade.
- auto_ptr<HTTPResponse> http(getResponse(ret));
+ scoped_ptr<HTTPResponse> http(getResponse(ret));
string relayState(in["RelayState"].string() ? in["RelayState"].string() : "");
// 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, nullptr, *http.get(), entityID, acsLocation, in["authnContextClassRef"].string(), relayState);
+ doRequest(*app, nullptr, *http, entityID, acsLocation, in["authnContextClassRef"].string(), relayState);
if (!ret.isstruct())
ret.structure();
ret.addmember("RelayState").unsafe_string(relayState.c_str());
{
#ifndef SHIBSP_LITE
// Use metadata to invoke the SSO service directly.
- MetadataProvider* m=app.getMetadataProvider();
+ MetadataProvider* m = app.getMetadataProvider();
Locker locker(m);
MetadataProviderCriteria mc(app, entityID, &IDPSSODescriptor::ELEMENT_QNAME, m_binding.get());
- pair<const EntityDescriptor*,const RoleDescriptor*> entity=m->getEntityDescriptor(mc);
+ pair<const EntityDescriptor*,const RoleDescriptor*> entity = m->getEntityDescriptor(mc);
if (!entity.first) {
m_log.warn("unable to locate metadata for provider (%s)", entityID);
throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID));
else if (!entity.second) {
m_log.log(getParent() ? Priority::INFO : Priority::WARN, "unable to locate ADFS-aware identity provider role for provider (%s)", entityID);
if (getParent())
- return make_pair(false,0L);
+ return make_pair(false, 0L);
throw MetadataException("Unable to locate ADFS-aware identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
}
const EndpointType* ep = EndpointManager<SingleSignOnService>(
if (!ep) {
m_log.warn("unable to locate compatible SSO service for provider (%s)", entityID);
if (getParent())
- return make_pair(false,0L);
+ return make_pair(false, 0L);
throw MetadataException("Unable to locate compatible SSO service for provider ($entityID)", namedparams(1, "entityID", entityID));
}
preserveRelayState(app, httpResponse, relayState);
- auto_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
+ scoped_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
if (ar_event.get()) {
ar_event->m_binding = WSFED_NS;
ar_event->m_protocol = WSFED_NS;
return make_pair(true, httpResponse.sendRedirect(req.c_str()));
#else
- return make_pair(false,0L);
+ return make_pair(false, 0L);
#endif
}
const saml1::NameIdentifier* saml1name=nullptr;
const saml1::AuthenticationStatement* saml1statement=nullptr;
- saml2::NameID* saml2name=nullptr;
+ const saml2::NameID* saml2name=nullptr;
const saml2::AuthnStatement* saml2statement=nullptr;
const XMLCh* authMethod=nullptr;
const XMLCh* authInstant=nullptr;
// To complete processing, we need to extract and resolve attributes and then create the session.
// Normalize a SAML 1.x NameIdentifier...
- auto_ptr<saml2::NameID> nameid(saml1name ? saml2::NameIDBuilder::buildNameID() : nullptr);
+ scoped_ptr<saml2::NameID> nameid(saml1name ? saml2::NameIDBuilder::buildNameID() : nullptr);
if (saml1name) {
nameid->setName(saml1name->getName());
nameid->setFormat(saml1name->getFormat());
// The context will handle deleting attributes and new tokens.
vector<const Assertion*> tokens(1,token);
- auto_ptr<ResolutionContext> ctx(
+ scoped_ptr<ResolutionContext> ctx(
resolveAttributes(
application,
+ &httpRequest,
policy.getIssuerMetadata(),
m_protocol.get(),
+ nullptr,
saml1name,
saml1statement,
(saml1name ? nameid.get() : saml2name),
authMethod,
nullptr,
&tokens,
- ctx.get() ? &ctx->getResolvedAttributes() : nullptr
+ ctx ? &ctx->getResolvedAttributes() : nullptr
);
- auto_ptr<LoginEvent> login_event(newLoginEvent(application, httpRequest));
- if (login_event.get()) {
+ scoped_ptr<LoginEvent> login_event(newLoginEvent(application, httpRequest));
+ if (login_event) {
login_event->m_sessionID = session_id.c_str();
login_event->m_peer = entity;
login_event->m_protocol = WSFED_NS;
login_event->m_saml1AuthnStatement = saml1statement;
login_event->m_nameID = (saml1name ? nameid.get() : saml2name);
login_event->m_saml2AuthnStatement = saml2statement;
- if (ctx.get())
+ if (ctx)
login_event->m_attributes = &ctx->getResolvedAttributes();
application.getServiceProvider().getTransactionLog()->write(*login_event);
}
try {
session = request.getSession(false, true, false); // don't cache it and ignore all checks
if (!session)
- return make_pair(false,0L);
+ return make_pair(false, 0L);
// We only handle ADFS sessions.
if (!XMLString::equals(session->getProtocol(), WSFED_NS) || !session->getEntityID()) {
session->unlock();
- return make_pair(false,0L);
+ return make_pair(false, 0L);
}
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("error accessing current session: %s", ex.what());
return make_pair(false,0L);
}
- session->unlock();
-
if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
// When out of process, we run natively.
return doRequest(request.getApplication(), request, request, session);
session->unlock();
vector<string> headers(1,"Cookie");
headers.push_back("User-Agent");
- DDF out,in = wrap(request,&headers);
+ DDF out,in = wrap(request, &headers);
DDFJanitor jin(in), jout(out);
out=request.getServiceProvider().getListenerService()->send(in);
return unwrap(request, out);
return LogoutHandler::receive(in, out);
// Find application.
- const char* aid=in["application_id"].string();
- const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+ const char* aid = in["application_id"].string();
+ const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
if (!app) {
// Something's horribly wrong.
m_log.error("couldn't find application (%s) for logout", aid ? aid : "(missing)");
}
// Unpack the request.
- auto_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(in));
// Set up a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- auto_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(ret));
Session* session = nullptr;
try {
- session = app->getServiceProvider().getSessionCache()->find(*app, *req.get(), nullptr, nullptr);
+ session = app->getServiceProvider().getSessionCache()->find(*app, *req, nullptr, nullptr);
}
- catch (exception& ex) {
+ catch (std::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, *req.get(), *resp.get(), session);
+ doRequest(*app, *req, *resp, session);
}
else {
m_log.error("no issuing entityID found in session");
session->unlock();
- app->getServiceProvider().getSessionCache()->remove(*app, *req.get(), resp.get());
+ app->getServiceProvider().getSessionCache()->remove(*app, *req, resp.get());
}
}
out << ret;
const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, Session* session
) const
{
+ Locker sessionLocker(session, false);
+
// Do back channel notification.
vector<string> sessions(1, session->getID());
if (!notifyBackChannel(application, httpRequest.getRequestURL(), sessions, false)) {
#ifndef SHIBSP_LITE
- auto_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
- if (logout_event.get()) {
+ scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
+ if (logout_event) {
logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_PARTIAL;
application.getServiceProvider().getTransactionLog()->write(*logout_event);
}
#endif
- session->unlock();
+ sessionLocker.assign();
+ session = nullptr;
application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
return sendLogoutPage(application, httpRequest, httpResponse, "partial");
}
#ifndef SHIBSP_LITE
- pair<bool,long> ret = make_pair(false,0L);
+ pair<bool,long> ret = make_pair(false, 0L);
try {
// With a session in hand, we can create a request message, if we can find a compatible endpoint.
- MetadataProvider* m=application.getMetadataProvider();
+ MetadataProvider* m = application.getMetadataProvider();
Locker metadataLocker(m);
MetadataProviderCriteria mc(application, session->getEntityID(), &IDPSSODescriptor::ELEMENT_QNAME, m_binding.get());
pair<const EntityDescriptor*,const RoleDescriptor*> entity=m->getEntityDescriptor(mc);
);
}
+ const char* returnloc = httpRequest.getParameter("return");
+ if (returnloc)
+ application.limitRedirect(httpRequest, returnloc);
+
// Log the request.
- auto_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
- if (logout_event.get()) {
+ scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
+ if (logout_event) {
logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_UNKNOWN;
application.getServiceProvider().getTransactionLog()->write(*logout_event);
}
- const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
- const char* returnloc = httpRequest.getParameter("return");
auto_ptr_char dest(ep->getLocation());
string req=string(dest.get()) + (strchr(dest.get(),'?') ? '&' : '?') + "wa=wsignout1.0";
- if (returnloc)
- req += "&wreply=" + urlenc->encode(returnloc);
+ if (returnloc) {
+ req += "&wreply=";
+ if (*returnloc == '/') {
+ string s(returnloc);
+ httpRequest.absolutize(s);
+ req += XMLToolingConfig::getConfig().getURLEncoder()->encode(s.c_str());
+ }
+ else {
+ req += XMLToolingConfig::getConfig().getURLEncoder()->encode(returnloc);
+ }
+ }
ret.second = httpResponse.sendRedirect(req.c_str());
ret.first = true;
if (session) {
- session->unlock();
+ sessionLocker.assign();
session = nullptr;
application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
}
// Less noise for IdPs that don't support logout
m_log.info("unable to issue ADFS logout request: %s", mex.what());
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("error issuing ADFS logout request: %s", ex.what());
}
- if (session)
- session->unlock();
-
return ret;
#else
throw ConfigurationException("Cannot perform logout using lite version of shibsp library.");
try {
app.getServiceProvider().getSessionCache()->remove(app, request, &request);
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("error removing session (%s): %s", session_id.c_str(), ex.what());
}
}
- if (param)
- return make_pair(true, request.sendRedirect(param));
+ if (param) {
+ if (*param == '/') {
+ string p(param);
+ request.absolutize(p);
+ return make_pair(true, request.sendRedirect(p.c_str()));
+ }
+ else {
+ app.limitRedirect(request, param);
+ return make_pair(true, request.sendRedirect(param));
+ }
+ }
return sendLogoutPage(app, request, request, "global");
}