redirectErrors = props->getString("redirectErrors");
if (redirectErrors.first) {
string loc(redirectErrors.second);
+ request.absolutize(loc);
loc = loc + '?' + tp.toQueryString();
return request.sendRedirect(loc.c_str());
}
void SHIBSP_DLLLOCAL clearHeaders(SPRequest& request) {
const Application& app = request.getApplication();
+ app.clearHeader(request, "Shib-Cookie-Name", "HTTP_SHIB_COOKIE_NAME");
app.clearHeader(request, "Shib-Session-ID", "HTTP_SHIB_SESSION_ID");
app.clearHeader(request, "Shib-Session-Index", "HTTP_SHIB_SESSION_INDEX");
app.clearHeader(request, "Shib-Identity-Provider", "HTTP_SHIB_IDENTITY_PROVIDER");
if (i != m_listenerMap.end())
ret = i->second;
m_listenerMap[address] = listener;
- Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").info("registered remoted message endpoint (%s)",address);
+ Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider").info("registered remoted message endpoint (%s)",address);
return ret;
}
m_listenerMap[address] = restore;
else
m_listenerMap.erase(address);
- Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").info("unregistered remoted message endpoint (%s)",address);
+ Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider").info("unregistered remoted message endpoint (%s)",address);
return true;
}
return false;
#ifdef _DEBUG
xmltooling::NDC ndc("doAuthentication");
#endif
- Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
+ Category& log = Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider");
const Application* app = nullptr;
string targetURL = request.getRequestURL();
return make_pair(true, request.returnOK());
}
- // Three settings dictate how to proceed.
+ // These settings dictate how to proceed.
pair<bool,const char*> authType = settings.first->getString("authType");
pair<bool,bool> requireSession = settings.first->getBool("requireSession");
pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");
+ pair<bool,const char*> requireLogoutWith = settings.first->getString("requireLogoutWith");
// If no session is required AND the AuthType (an Apache-derived concept) isn't recognized,
// then we ignore this request and consider it unprotected. Apache might lie to us if
Session* session = nullptr;
try {
- session = request.getSession();
+ session = request.getSession(true, false, false); // don't cache it
}
catch (exception& e) {
log.warn("error during session lookup: %s", e.what());
throw;
}
- if (!session) {
+ Locker slocker(session, false); // pop existing lock on exit
+ if (session) {
+ // Check for logout interception.
+ if (requireLogoutWith.first) {
+ // Check for a completion parameter on the query string.
+ const char* qstr = request.getQueryString();
+ if (!qstr || !strstr(qstr, "shiblogoutdone=1")) {
+ // First leg of circuit, so we redirect to the logout endpoint specified with this URL as a return location.
+ string selfurl = request.getRequestURL();
+ if (qstr)
+ selfurl += '&';
+ else
+ selfurl += '?';
+ selfurl += "shiblogoutdone=1";
+ string loc = requireLogoutWith.second;
+ request.absolutize(loc);
+ if (loc.find('?') != string::npos)
+ loc += '&';
+ else
+ loc += '?';
+ loc += "return=" + XMLToolingConfig::getConfig().getURLEncoder()->encode(selfurl.c_str());
+ return make_pair(true, request.sendRedirect(loc.c_str()));
+ }
+ }
+ }
+ else {
// No session. Maybe that's acceptable?
if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first)
return make_pair(true, request.returnOK());
initiator=app->getSessionInitiatorById(requireSessionWith.second);
if (!initiator) {
throw ConfigurationException(
- "No session initiator found with id ($1), check requireSessionWith command.", params(1,requireSessionWith.second)
+ "No session initiator found with id ($1), check requireSessionWith command.", params(1, requireSessionWith.second)
);
}
}
throw ConfigurationException("No default session initiator found, check configuration.");
}
- return initiator->run(request, false);
+ // Dispatch to SessionInitiator. This MUST handle the request, or we want to fail here.
+ // Used to fall through into doExport, but this is a cleaner exit path.
+ pair<bool,long> ret = initiator->run(request, false);
+ if (ret.first)
+ return ret;
+ throw ConfigurationException("Session initiator did not handle request for a new session, check configuration.");
}
request.setAuthType(authType.second);
request.log(SPRequest::SPError, e.what());
TemplateParameters tp(&e);
tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,sendError(log, request, app, "session", tp));
+ return make_pair(true, sendError(log, request, app, "session", tp));
}
}
#ifdef _DEBUG
xmltooling::NDC ndc("doAuthorization");
#endif
- Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
+ Category& log = Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider");
const Application* app = nullptr;
- const Session* session = nullptr;
+ Session* session = nullptr;
+ Locker slocker;
string targetURL = request.getRequestURL();
try {
// Do we have an access control plugin?
if (settings.second) {
try {
- session = request.getSession(false);
+ session = request.getSession(false, false, false); // ignore timeout and do not cache
+ if (session)
+ slocker.assign(session, false); // assign to lock popper
}
catch (exception& e) {
log.warn("unable to obtain session to pass to access control provider: %s", e.what());
request.log(SPRequest::SPError, e.what());
TemplateParameters tp(&e, nullptr, session);
tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,sendError(log, request, app, "access", tp));
+ return make_pair(true, sendError(log, request, app, "access", tp));
}
}
#ifdef _DEBUG
xmltooling::NDC ndc("doExport");
#endif
- Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
+ Category& log = Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider");
const Application* app = nullptr;
- const Session* session = nullptr;
+ Session* session = nullptr;
+ Locker slocker;
string targetURL = request.getRequestURL();
try {
app = &(request.getApplication());
try {
- session = request.getSession(false);
+ session = request.getSession(false, false, false); // ignore timeout and do not cache
+ if (session)
+ slocker.assign(session, false); // assign to lock popper
}
catch (exception& e) {
log.warn("unable to obtain session to export to request: %s", e.what());
app->setHeader(request, "Shib-Session-Index", hval);
}
+ // Check for export of algorithmically-derived portion of cookie names.
+ stdvars = settings.first->getBool("exportCookie");
+ if (stdvars.first && stdvars.second) {
+ pair<string,const char*> cookieprops = app->getCookieNameProps(nullptr);
+ app->setHeader(request, "Shib-Cookie-Name", cookieprops.first.c_str());
+ }
+
// Maybe export the assertion keys.
pair<bool,bool> exp = settings.first->getBool("exportAssertion");
if (exp.first && exp.second) {
request.log(SPRequest::SPError, e.what());
TemplateParameters tp(&e, nullptr, session);
tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,sendError(log, request, app, "session", tp));
+ return make_pair(true, sendError(log, request, app, "session", tp));
}
}
#ifdef _DEBUG
xmltooling::NDC ndc("doHandler");
#endif
- Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
+ Category& log = Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider");
const Application* app = nullptr;
string targetURL = request.getRequestURL();
}
catch (exception& e) {
request.log(SPRequest::SPError, e.what());
- const Session* session = nullptr;
+ Session* session = nullptr;
try {
- session = request.getSession(false, true);
+ session = request.getSession(false, true, false); // do not cache
}
catch (exception&) {
}
+ Locker slocker(session, false); // pop existing lock on exit
TemplateParameters tp(&e, nullptr, session);
tp.m_map["requestURL"] = targetURL.substr(0, targetURL.find('?'));
tp.m_request = &request;