Detect multiple executions of NSAPI function so spoof check doesn't run twice.
[shibboleth/cpp-sp.git] / nsapi_shib / nsapi_shib.cpp
index 6c8618e..29b80ab 100644 (file)
@@ -76,6 +76,7 @@ namespace {
     string g_ServerScheme;
     string g_unsetHeaderValue;
     bool g_checkSpoofing = true;
+    bool g_catchAll = false;
 
     static const XMLCh path[] =     UNICODE_LITERAL_4(p,a,t,h);
     static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
@@ -172,9 +173,10 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, ::Session* sn, Request*
         pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
         if (unsetValue.first)
             g_unsetHeaderValue = unsetValue.second;
-        pair<bool,bool> checkSpoofing=props->getBool("checkSpoofing");
-        if (checkSpoofing.first && !checkSpoofing.second)
-            g_checkSpoofing = false;
+        pair<bool,bool> flag=props->getBool("checkSpoofing");
+        g_checkSpoofing = !flag.first || flag.second;
+        flag=props->getBool("catchAll");
+        g_catchAll = flag.first && flag.second;
     }
     return REQ_PROCEED;
 }
@@ -184,28 +186,38 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, ::Session* sn, Request*
 
 class ShibTargetNSAPI : public AbstractSPRequest
 {
-  string m_uri;
   mutable string m_body;
-  mutable bool m_gotBody;
+  mutable bool m_gotBody,m_firsttime;
   mutable vector<string> m_certs;
   set<string> m_allhttp;
 
 public:
-  ShibTargetNSAPI(pblock* pb, ::Session* sn, Request* rq) : m_gotBody(false) {
-    m_pb = pb;
-    m_sn = sn;
-    m_rq = rq;
+  pblock* m_pb;
+  ::Session* m_sn;
+  Request* m_rq;
+
+  ShibTargetNSAPI(pblock* pb, ::Session* sn, Request* rq)
+      : AbstractSPRequest(SHIBSP_LOGCAT".NSAPI"), m_gotBody(false), m_firsttime(true), m_pb(pb), m_sn(sn), m_rq(rq) {
 
     const char* uri=pblock_findval("uri", rq->reqpb);
     const char* qstr=pblock_findval("query", rq->reqpb);
 
-    if (uri)
-        m_uri = uri;
-    if (qstr)
-        m_uri = m_uri + '?' + qstr;
-  }
-  ~ShibTargetNSAPI() {
+    if (qstr) {
+        string temp = string(uri) + '?' + qstr;
+        setRequestURI(temp.c_str());
+    }
+    else {
+        setRequestURI(uri);
+    }
+
+    // See if this is the first time we've run.
+    qstr = pblock_findval("auth-type", rq->vars);
+    if (qstr && !strcmp(qstr, "shibboleth"))
+        m_firsttime = false;
+    if (!m_firsttime)
+        log(SPDebug, "nsapi_shib function running more than once");
   }
+  ~ShibTargetNSAPI() { }
 
   const char* getScheme() const {
     return security_active ? "https" : "http";
@@ -225,9 +237,6 @@ public:
   int getPort() const {
     return server_portnum;
   }
-  const char* getRequestURI() const {
-    return m_uri.c_str();
-  }
   const char* getMethod() const {
     return pblock_findval("method", m_rq->reqpb);
   }
@@ -278,7 +287,7 @@ public:
     }
   }
   void clearHeader(const char* rawname, const char* cginame) {
-    if (g_checkSpoofing) {
+    if (m_firsttime && g_checkSpoofing) {
         if (m_allhttp.empty()) {
             // Populate the set of client-supplied headers for spoof checking.
             const pb_entry* entry;
@@ -370,10 +379,6 @@ public:
       }
       return m_certs;
   }
-
-  pblock* m_pb;
-  ::Session* m_sn;
-  Request* m_rq;
 };
 
 /********************************************************************************/
@@ -419,11 +424,12 @@ extern "C" NSAPI_PUBLIC int nsapi_shib(pblock* pb, ::Session* sn, Request* rq)
     log_error(LOG_FAILURE,FUNC,sn,rq,const_cast<char*>(e.what()));
     return WriteClientError(sn, rq, FUNC, "Shibboleth module threw an exception, see web server log for error.");
   }
-#ifndef _DEBUG
   catch (...) {
-    return WriteClientError(sn, rq, FUNC, "Shibboleth module threw an uncaught exception.");
+    log_error(LOG_FAILURE,FUNC,sn,rq,const_cast<char*>("Shibboleth module threw an unknown exception."));
+    if (g_catchAll)
+        return WriteClientError(sn, rq, FUNC, "Shibboleth module threw an unknown exception.");
+    throw;
   }
-#endif
 }
 
 
@@ -447,11 +453,11 @@ extern "C" NSAPI_PUBLIC int shib_handler(pblock* pb, ::Session* sn, Request* rq)
     log_error(LOG_FAILURE,FUNC,sn,rq,const_cast<char*>(e.what()));
     return WriteClientError(sn, rq, FUNC, "Shibboleth handler threw an exception, see web server log for error.");
   }
-#ifndef _DEBUG
   catch (...) {
-    return WriteClientError(sn, rq, FUNC, "Shibboleth handler threw an unknown exception.");
+    if (g_catchAll)
+        return WriteClientError(sn, rq, FUNC, "Shibboleth handler threw an unknown exception.");
+    throw;
   }
-#endif
 }
 
 
@@ -569,6 +575,8 @@ void SunRequestMapper::getAll(map<string,const char*>& properties) const
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
     if (s)
         s->getAll(properties);
+    if (!stn)
+        return;
     properties["authType"] = "shibboleth";
     const pb_entry* entry;
     for (int i=0; i<stn->m_pb->hsize; ++i) {