Cache invalid tokens in case they're targeted at other services.
authorScott Cantor <cantor.2@osu.edu>
Sat, 17 Mar 2007 19:03:15 +0000 (19:03 +0000)
committerScott Cantor <cantor.2@osu.edu>
Sat, 17 Mar 2007 19:03:15 +0000 (19:03 +0000)
shibsp/handler/impl/SAML1Consumer.cpp

index 7fe6831..33744a7 100644 (file)
@@ -120,6 +120,10 @@ string SAML1Consumer::implementProtocol(
     const AuthenticationStatement* ssoStatement=NULL;
     vector<const opensaml::Assertion*> tokens;
 
+    // Also track "bad" tokens that we'll cache but not use.
+    // This is necessary because there may be valid tokens not aimed at us.
+    vector<const opensaml::Assertion*> badtokens;
+
     // Profile validator.
     time_t now = time(NULL);
     BrowserSSOProfileValidator ssoValidator(application.getAudiences(), now);
@@ -131,6 +135,7 @@ string SAML1Consumer::implementProtocol(
         // Skip unsigned assertion?
         if (!(*a)->getSignature() && flag.first && flag.second) {
             m_log.warn("found unsigned assertion in SAML response, ignoring it per signedAssertions policy");
+            badtokens.push_back(*a);
             continue;
         }
 
@@ -143,8 +148,11 @@ string SAML1Consumer::implementProtocol(
             policy.evaluate(*(*a));
             
             // If no security is in place now, we kick it.
-            if (!alreadySecured && !policy.isSecure())
-                throw SecurityPolicyException("Unable to establish security of the assertion.");
+            if (!alreadySecured && !policy.isSecure()) {
+                m_log.warn("unable to establish security of assertion");
+                badtokens.push_back(*a);
+                continue;
+            }
 
             // Now do profile and core semantic validation to ensure we can use it for SSO.
             ssoValidator.validateAssertion(*(*a));
@@ -158,6 +166,7 @@ string SAML1Consumer::implementProtocol(
         }
         catch (exception& ex) {
             m_log.warn("detected a problem with assertion: %s", ex.what());
+            badtokens.push_back(*a);
         }
     }
 
@@ -193,6 +202,9 @@ string SAML1Consumer::implementProtocol(
     // Copy over any new tokens, but leave them in the context for cleanup.
     tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end());
 
+    // Now merge in bad tokens for caching.
+    tokens.insert(tokens.end(), badtokens.begin(), badtokens.end());
+
     // Now we have to extract the authentication details for session setup.
 
     // Session expiration for SAML 1.x is purely SP-driven, and the method is mapped to a ctx class.