Change API to permit session initiators to modify the entityID mid-chain.
[shibboleth/sp.git] / shibsp / handler / impl / WAYFSessionInitiator.cpp
index 148573c..19510ec 100644 (file)
 #include "handler/AbstractHandler.h"
 #include "handler/SessionInitiator.h"
 
+#include <ctime>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/URLEncoder.h>
 
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
-using namespace log4cpp;
 using namespace std;
 
 namespace shibsp {
@@ -47,7 +47,7 @@ namespace shibsp {
     {
     public:
         WAYFSessionInitiator(const DOMElement* e, const char* appId)
-                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator")), m_url(NULL) {
+                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.WAYF")), m_url(NULL) {
             pair<bool,const char*> url = getString("URL");
             if (!url.first)
                 throw ConfigurationException("WAYF SessionInitiator requires a URL property.");
@@ -55,7 +55,7 @@ namespace shibsp {
         }
         virtual ~WAYFSessionInitiator() {}
         
-        pair<bool,long> run(SPRequest& request, const char* entityID=NULL, bool isHandler=true) const;
+        pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
 
     private:
         const char* m_url;
@@ -72,12 +72,12 @@ namespace shibsp {
 
 };
 
-pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, const char* entityID, bool isHandler) const
+pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID, bool isHandler) const
 {
     // The IdP CANNOT be specified for us to run. Otherwise, we'd be redirecting to a WAYF
     // anytime the IdP's metadata was wrong.
-    if (entityID && *entityID)
-        return make_pair(false,0);
+    if (!entityID.empty())
+        return make_pair(false,0L);
 
     string target;
     const char* option;
@@ -86,13 +86,16 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, const char* entity
 
     if (isHandler) {
         option=request.getParameter("acsIndex");
-        if (option)
+        if (option) {
             ACS=app.getAssertionConsumerServiceByIndex(atoi(option));
+            if (!ACS)
+                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
+        }
 
         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.
@@ -100,8 +103,17 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, const char* entity
         target=request.getRequestURL();
     }
     
-    if (!ACS)
-        ACS = app.getDefaultAssertionConsumerService();
+    // Since we're not passing by index, we need to fully compute the return URL.
+    if (!ACS) {
+        pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+        if (index.first) {
+            ACS = app.getAssertionConsumerServiceByIndex(index.second);
+            if (!ACS)
+                request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+        }
+        if (!ACS)
+            ACS = app.getDefaultAssertionConsumerService();
+    }
 
     m_log.debug("sending request to WAYF (%s)", m_url);
 
@@ -124,7 +136,7 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, const char* entity
         target = "default";
 
     char timebuf[16];
-    sprintf(timebuf,"%u",time(NULL));
+    sprintf(timebuf,"%lu",time(NULL));
     const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
     string req=string(m_url) + (strchr(m_url,'?') ? '&' : '?') + "shire=" + urlenc->encode(ACSloc.c_str()) +
         "&time=" + timebuf + "&target=" + urlenc->encode(target.c_str()) +