Factor out LogoutInitiator class, simpler API to get ACS by binding.
[shibboleth/cpp-sp.git] / shibsp / handler / impl / AbstractHandler.cpp
index aa86b54..0763746 100644 (file)
@@ -67,12 +67,10 @@ using namespace xercesc;
 using namespace std;
 
 namespace shibsp {
+
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML1ConsumerFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ConsumerFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ArtifactResolutionFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory ChainingLogoutInitiatorFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory LocalLogoutInitiatorFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutInitiatorFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2NameIDMgmtFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory AssertionLookupFactory;
@@ -80,6 +78,23 @@ namespace shibsp {
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory StatusHandlerFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SessionHandlerFactory;
 
+    void SHIBSP_DLLLOCAL absolutize(const HTTPRequest& request, string& url) {
+        if (url.empty())
+            url = '/';
+        if (url[0] == '/') {
+            // Compute a URL to the root of the site.
+            int port = request.getPort();
+            const char* scheme = request.getScheme();
+            string root = string(scheme) + "://" + request.getHostname();
+            if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
+                ostringstream portstr;
+                portstr << port;
+                root += ":" + portstr.str();
+            }
+            url = root + url;
+        }
+    }
+
     void SHIBSP_DLLLOCAL generateRandomHex(std::string& buf, unsigned int len) {
         static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
         int r;
@@ -95,6 +110,8 @@ namespace shibsp {
             buf += (DIGITS[0x0F & b2]);
         }
     }
+
+
 };
 
 void SHIBSP_API shibsp::registerHandlers()
@@ -115,9 +132,6 @@ void SHIBSP_API shibsp::registerHandlers()
     conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory);
     conf.HandlerManager.registerFactory(SESSION_HANDLER, SessionHandlerFactory);
 
-    conf.LogoutInitiatorManager.registerFactory(CHAINING_LOGOUT_INITIATOR, ChainingLogoutInitiatorFactory);
-    conf.LogoutInitiatorManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);
-    conf.LogoutInitiatorManager.registerFactory(SAML2_LOGOUT_INITIATOR, SAML2LogoutInitiatorFactory);
     conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2LogoutFactory);
     conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2LogoutFactory);
     conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2LogoutFactory);
@@ -139,6 +153,11 @@ Handler::~Handler()
 {
 }
 
+const XMLCh* Handler::getProtocolFamily() const
+{
+    return nullptr;
+}
+
 void Handler::log(SPRequest::SPLogLevel level, const string& msg) const
 {
     Category::getInstance(SHIBSP_LOGCAT".Handler").log(
@@ -185,7 +204,7 @@ void Handler::preserveRelayState(const Application& application, HTTPResponse& r
                     if (storage) {
                         string rsKey;
                         generateRandomHex(rsKey,5);
-                        if (!storage->createString("RelayState", rsKey.c_str(), relayState.c_str(), time(NULL) + 600))
+                        if (!storage->createString("RelayState", rsKey.c_str(), relayState.c_str(), time(nullptr) + 600))
                             throw IOException("Attempted to insert duplicate storage key.");
                         relayState = string(mech.second-3) + ':' + rsKey;
                     }
@@ -234,9 +253,10 @@ void Handler::recoverRelayState(
                     StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());
                     if (storage) {
                         ssid = key;
-                        if (storage->readString("RelayState",ssid.c_str(),&relayState)>0) {
+                        if (storage->readString("RelayState",ssid.c_str(),&relayState) > 0) {
                             if (clear)
                                 storage->deleteString("RelayState",ssid.c_str());
+                            absolutize(request, relayState);
                             return;
                         }
                         else
@@ -263,6 +283,7 @@ void Handler::recoverRelayState(
                     }
                     else {
                         relayState = out.string();
+                        absolutize(request, relayState);
                         return;
                     }
                 }
@@ -290,6 +311,7 @@ void Handler::recoverRelayState(
                     exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
                     response.setCookie(relay_cookie.first.c_str(), exp.c_str());
                 }
+                absolutize(request, relayState);
                 return;
             }
         }
@@ -301,26 +323,18 @@ void Handler::recoverRelayState(
     if (relayState.empty() || relayState == "default" || relayState == "cookie") {
         pair<bool,const char*> homeURL=application.getString("homeURL");
         if (homeURL.first)
-            relayState=homeURL.second;
-        else {
-            // Compute a URL to the root of the site.
-            int port = request.getPort();
-            const char* scheme = request.getScheme();
-            relayState = string(scheme) + "://" + request.getHostname();
-            if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
-                ostringstream portstr;
-                portstr << port;
-                relayState += ":" + portstr.str();
-            }
-            relayState += '/';
-        }
+            relayState = homeURL.second;
+        else
+            relayState = '/';
     }
+
+    absolutize(request, relayState);
 }
 
 AbstractHandler::AbstractHandler(
     const DOMElement* e, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
     ) : m_log(log), m_configNS(shibspconstants::SHIB2SPCONFIG_NS) {
-    load(e,NULL,filter,remapper);
+    load(e,nullptr,filter,remapper);
 }
 
 AbstractHandler::~AbstractHandler()
@@ -352,7 +366,7 @@ void AbstractHandler::checkError(const XMLObject* response, const saml2md::RoleD
         const saml2p::Status* status = r2->getStatus();
         if (status) {
             const saml2p::StatusCode* sc = status->getStatusCode();
-            const XMLCh* code = sc ? sc->getValue() : NULL;
+            const XMLCh* code = sc ? sc->getValue() : nullptr;
             if (code && !XMLString::equals(code,saml2p::StatusCode::SUCCESS)) {
                 FatalProfileException ex("SAML response contained an error.");
                 annotateException(&ex, role, status);   // throws it
@@ -365,7 +379,7 @@ void AbstractHandler::checkError(const XMLObject* response, const saml2md::RoleD
         const saml1p::Status* status = r1->getStatus();
         if (status) {
             const saml1p::StatusCode* sc = status->getStatusCode();
-            const xmltooling::QName* code = sc ? sc->getValue() : NULL;
+            const xmltooling::QName* code = sc ? sc->getValue() : nullptr;
             if (code && *code != saml1p::StatusCode::SUCCESS) {
                 FatalProfileException ex("SAML response contained an error.");
                 ex.addProperty("statusCode", code->toString().c_str());
@@ -417,7 +431,7 @@ long AbstractHandler::sendMessage(
     bool signIfPossible
     ) const
 {
-    const EntityDescriptor* entity = role ? dynamic_cast<const EntityDescriptor*>(role->getParent()) : NULL;
+    const EntityDescriptor* entity = role ? dynamic_cast<const EntityDescriptor*>(role->getParent()) : nullptr;
     const PropertySet* relyingParty = application.getRelyingParty(entity);
     pair<bool,const char*> flag = signIfPossible ? make_pair(true,(const char*)"true") : relyingParty->getString("signing");
     if (role && flag.first &&
@@ -427,7 +441,7 @@ long AbstractHandler::sendMessage(
         CredentialResolver* credResolver=application.getCredentialResolver();
         if (credResolver) {
             Locker credLocker(credResolver);
-            const Credential* cred = NULL;
+            const Credential* cred = nullptr;
             pair<bool,const char*> keyName = relyingParty->getString("keyName");
             pair<bool,const XMLCh*> sigalg = relyingParty->getXMLString("signingAlg");
             if (role) {
@@ -518,7 +532,7 @@ void AbstractHandler::preservePostData(
                 rsKey = SAMLArtifact::toHex(rsKey);
                 ostringstream out;
                 out << postData;
-                if (!storage->createString("PostData", rsKey.c_str(), out.str().c_str(), time(NULL) + 600))
+                if (!storage->createString("PostData", rsKey.c_str(), out.str().c_str(), time(nullptr) + 600))
                     throw IOException("Attempted to insert duplicate storage key.");
                 postkey = string(mech.second-3) + ':' + rsKey;
             }
@@ -678,7 +692,7 @@ DDF AbstractHandler::getPostData(const Application& application, const HTTPReque
             plimit.second = 1024 * 1024;
         if (plimit.second == 0 || request.getContentLength() <= plimit.second) {
             CGIParser cgi(request);
-            pair<CGIParser::walker,CGIParser::walker> params = cgi.getParameters(NULL);
+            pair<CGIParser::walker,CGIParser::walker> params = cgi.getParameters(nullptr);
             if (params.first == params.second)
                 return DDF("parameters").list();
             DDF child;
@@ -740,7 +754,7 @@ pair<bool,const char*> AbstractHandler::getString(const char* name, const SPRequ
         return getString(name);
     }
 
-    return pair<bool,const char*>(false,NULL);
+    return pair<bool,const char*>(false,nullptr);
 }
 
 pair<bool,unsigned int> AbstractHandler::getUnsignedInt(const char* name, const SPRequest& request, unsigned int type) const
@@ -748,7 +762,7 @@ pair<bool,unsigned int> AbstractHandler::getUnsignedInt(const char* name, const
     if (type & HANDLER_PROPERTY_REQUEST) {
         const char* param = request.getParameter(name);
         if (param && *param)
-            return pair<bool,unsigned int>(true, strtol(param,NULL,10));
+            return pair<bool,unsigned int>(true, strtol(param,nullptr,10));
     }
     
     if (type & HANDLER_PROPERTY_MAP) {