https://issues.shibboleth.net/jira/browse/SSPCPP-396
authorScott Cantor <cantor.2@osu.edu>
Tue, 27 Mar 2012 19:18:47 +0000 (19:18 +0000)
committerScott Cantor <cantor.2@osu.edu>
Tue, 27 Mar 2012 19:18:47 +0000 (19:18 +0000)
schemas/shibboleth-2.0-native-sp-config.xsd
shibsp/Application.cpp
shibsp/ServiceProvider.cpp

index c7ec932..4db5a68 100644 (file)
     <attribute name="authType" type="conf:string"/>
     <attribute name="requireSession" type="boolean"/>
     <attribute name="requireSessionWith" type="conf:string"/>
+    <attribute name="requireLogoutWith" type="anyURI"/>
     <attribute name="exportAssertion" type="boolean"/>
     <attribute name="exportStdVars" type="boolean"/>
+    <attribute name="exportCookie" type="boolean"/>
     <attribute name="redirectToSSL" type="unsignedInt"/>
     <attribute name="entityID" type="anyURI"/>
     <attribute name="discoveryURL" type="anyURI"/>
index 2fc42f3..20021c1 100644 (file)
@@ -66,6 +66,8 @@ pair<string,const char*> Application::getCookieNameProps(const char* prefix, tim
 
     if (lifetime)
         *lifetime = 0;
+    if (!prefix)
+        prefix = "";
     const PropertySet* props=getPropertySet("Sessions");
     if (props) {
         if (lifetime) {
@@ -78,12 +80,12 @@ pair<string,const char*> Application::getCookieNameProps(const char* prefix, tim
             p.second=defProps;
         pair<bool,const char*> p2=props->getString("cookieName");
         if (p2.first)
-            return make_pair(string(prefix) + p2.second,p.second);
-        return make_pair(string(prefix) + getHash(),p.second);
+            return make_pair(string(prefix) + p2.second, p.second);
+        return make_pair(string(prefix) + getHash(), p.second);
     }
 
     // Shouldn't happen, but just in case..
-    return pair<string,const char*>(prefix,defProps);
+    return pair<string,const char*>(prefix, defProps);
 }
 
 void Application::clearHeader(SPRequest& request, const char* rawname, const char* cginame) const
index b7c1637..97d5a5e 100644 (file)
@@ -149,6 +149,7 @@ namespace shibsp {
 
     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");
@@ -268,10 +269,11 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
                 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
@@ -294,7 +296,29 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
                 throw;
         }
 
-        if (!session) {
+        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 += '?';
+                    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());
@@ -305,7 +329,7 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
                 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)
                         );
                 }
             }
@@ -329,7 +353,7 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
         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));
     }
 }
 
@@ -396,7 +420,7 @@ pair<bool,long> ServiceProvider::doAuthorization(SPRequest& request) const
         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));
     }
 }
 
@@ -466,6 +490,13 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
                 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) {
@@ -551,7 +582,7 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
         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));
     }
 }