New policy rules for handling conditions.
authorScott Cantor <cantor.2@osu.edu>
Fri, 20 Feb 2009 20:07:37 +0000 (20:07 +0000)
committerScott Cantor <cantor.2@osu.edu>
Fri, 20 Feb 2009 20:07:37 +0000 (20:07 +0000)
24 files changed:
.cproject
saml/Makefile.am
saml/binding/SecurityPolicy.h
saml/binding/SecurityPolicyRule.h
saml/binding/impl/MessageFlowRule.cpp
saml/binding/impl/SecurityPolicy.cpp
saml/profile/impl/AudienceRestrictionRule.cpp [new file with mode: 0644]
saml/profile/impl/ConditionsRule.cpp [new file with mode: 0644]
saml/profile/impl/IgnoreRule.cpp [new file with mode: 0644]
saml/saml.vcproj
saml/saml1/profile/AssertionValidator.h
saml/saml1/profile/BrowserSSOProfileValidator.h
saml/saml2/profile/AssertionValidator.h
saml/saml2/profile/BrowserSSOProfileValidator.h
saml/saml2/profile/SAML2AssertionPolicy.cpp [new file with mode: 0644]
saml/saml2/profile/SAML2AssertionPolicy.h [new file with mode: 0644]
samltest/Makefile.am
samltest/data/saml1/profile/SAML1Assertion.xml [new file with mode: 0644]
samltest/data/saml2/profile/SAML2Assertion.xml [new file with mode: 0644]
samltest/saml1/profile/.gitignore [new file with mode: 0644]
samltest/saml1/profile/SAML1PolicyTest.h [new file with mode: 0644]
samltest/saml2/profile/.gitignore [new file with mode: 0644]
samltest/saml2/profile/SAML2PolicyTest.h [new file with mode: 0644]
samltest/samltest.vcproj

index 29c81c1..4bb7304 100644 (file)
--- a/.cproject
+++ b/.cproject
 <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>\r
 \r
 \r
+\r
 <storageModule moduleId="org.eclipse.cdt.core.pathentry">\r
 <pathentry kind="mac" name="_MSC_VER" path="" value=""/>\r
 <pathentry kind="mac" name="WIN32" path="" value=""/>\r
 <pathentry kind="mac" name="SAML_API" path="" value=""/>\r
-<pathentry include="C:/xerces-c_2_8_0-x86-windows-vc_8_0/include" kind="inc" path="" system="true"/>\r
+<pathentry kind="mac" name="SAML_DLLLOCAL" path="" value=""/>\r
 <pathentry include="C:/xml-security-c-1.4.0/include" kind="inc" path="" system="true"/>\r
 <pathentry include="C:/log4shib-1.0/include" kind="inc" path="" system="true"/>\r
 <pathentry include="C:/cxxtest" kind="inc" path="" system="true"/>\r
@@ -78,7 +79,7 @@
 <pathentry kind="out" path="saml/Debug"/>\r
 <pathentry kind="out" path="samltest/Debug"/>\r
 <pathentry kind="con" path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>\r
-<pathentry excluding="util/|saml1/|signature/|saml2/|encryption/|security/|security/impl/|saml1/binding/|saml1/binding/impl/|saml2/binding/|saml2/binding/impl/|binding/|binding/impl/|zlib/|saml1/profile/|saml1/profile/impl/|saml2/profile/|saml2/profile/impl/" kind="src" path="saml"/>\r
+<pathentry excluding="util/|saml1/|signature/|saml2/|encryption/|security/|security/impl/|saml1/binding/|saml1/binding/impl/|saml2/binding/|saml2/binding/impl/|binding/|binding/impl/|zlib/|saml1/profile/|saml1/profile/impl/|saml2/profile/|saml2/profile/impl/|profile/impl/" kind="src" path="saml"/>\r
 <pathentry excluding="impl/" kind="src" path="saml/binding"/>\r
 <pathentry kind="src" path="saml/binding/impl"/>\r
 <pathentry excluding="impl/" kind="src" path="saml/saml1/core"/>\r
@@ -97,7 +98,7 @@
 <pathentry kind="src" path="saml/signature"/>\r
 <pathentry kind="src" path="saml/util"/>\r
 <pathentry kind="src" path="saml/zlib"/>\r
-<pathentry excluding="saml1/core/impl/|signature/|saml2/core/impl/|saml2/metadata/|security/|saml1/binding/|saml2/binding/|encryption/" kind="src" path="samltest"/>\r
+<pathentry excluding="saml1/core/impl/|signature/|saml2/core/impl/|saml2/metadata/|security/|saml1/binding/|saml2/binding/|encryption/|saml2/profile/|saml1/profile/" kind="src" path="samltest"/>\r
 <pathentry kind="src" path="samltest/saml1/binding"/>\r
 <pathentry kind="src" path="samltest/saml1/core/impl"/>\r
 <pathentry kind="src" path="samltest/saml2/binding"/>\r
 <pathentry kind="src" path="samltest/signature"/>\r
 <pathentry kind="src" path="samltest/encryption"/>\r
 <pathentry kind="src" path="samlsign"/>\r
+<pathentry kind="src" path="samltest/saml2/profile"/>\r
+<pathentry kind="src" path="saml/profile/impl"/>\r
+<pathentry kind="src" path="samltest/saml1/profile"/>\r
 </storageModule>\r
 </cconfiguration>\r
 </storageModule>\r
index 69e778a..eb19340 100644 (file)
@@ -96,7 +96,8 @@ saml2mdinclude_HEADERS = \
 
 saml2profinclude_HEADERS = \
        saml2/profile/AssertionValidator.h \
-       saml2/profile/BrowserSSOProfileValidator.h
+       saml2/profile/BrowserSSOProfileValidator.h \
+       saml2/profile/SAML2AssertionPolicy.h
 
 noinst_HEADERS = \
        internal.h
@@ -114,6 +115,9 @@ libsaml_la_SOURCES = \
        binding/impl/SimpleSigningRule.cpp \
        binding/impl/SOAPClient.cpp \
        binding/impl/XMLSigningRule.cpp \
+       profile/impl/AudienceRestrictionRule.cpp \
+    profile/impl/ConditionsRule.cpp \
+    profile/impl/IgnoreRule.cpp \
        saml1/core/impl/AssertionsImpl.cpp \
        saml1/core/impl/AssertionsSchemaValidators.cpp \
        saml1/core/impl/ProtocolsImpl.cpp \
@@ -164,6 +168,7 @@ libsaml_la_SOURCES = \
        saml2/binding/impl/SAML2SOAPClient.cpp \
        saml2/profile/Assertion20Validator.cpp \
        saml2/profile/BrowserSSOProfile20Validator.cpp \
+       saml2/profile/SAML2AssertionPolicy.cpp \
        encryption/EncryptedKeyResolver.cpp \
        signature/ContentReference.cpp \
        signature/SignatureProfileValidator.cpp \
index 72d2464..b655d01 100644 (file)
@@ -70,11 +70,7 @@ namespace opensaml {
             const xmltooling::QName* role=NULL,
             const xmltooling::TrustEngine* trustEngine=NULL,
             bool validate=true
-            ) : m_metadataCriteria(NULL), m_messageID(NULL), m_issueInstant(0), m_issuer(NULL), m_issuerRole(NULL), m_authenticated(false),
-                m_matchingPolicy(NULL), m_metadata(metadataProvider), m_role(NULL), m_trust(trustEngine), m_validate(validate), m_entityOnly(true) {
-            if (role)
-                m_role = new xmltooling::QName(*role);
-        }
+            );
 
         virtual ~SecurityPolicy();
 
@@ -135,6 +131,26 @@ namespace opensaml {
         }
 
         /**
+         * Returns the entityID of the receiving entity.
+         *
+         * @return entityID of the peer processing the message
+         */
+        const XMLCh* getRecipient() {
+            return m_recipient;
+        }
+
+        /**
+         * Gets the effective time of message processing.
+         *
+         * @return  the time at which the message is being processed
+         */
+        time_t getTime() {
+            if (m_ts == 0)
+                return m_ts = time(NULL);
+            return m_ts;
+        }
+
+        /**
          * Gets a mutable array of installed policy rules.
          *
          * <p>If adding rules, their lifetime must be at least as long as the policy object.
@@ -205,6 +221,27 @@ namespace opensaml {
         }
 
         /**
+         * Sets entityID of receiving entity.
+         *
+         * @param recipient the entityID of the peer processing the message
+         */
+        void setRecipient(const XMLCh* recipient) {
+            m_recipient = recipient;
+        }
+
+        /**
+         * Sets effective time of message processing.
+         *
+         * <p>Assumed to be the time of policy instantiation, can be adjusted to pre- or post-date
+         * message processing.
+         *
+         * @param ts    the time at which the message is being processed
+         */
+        void setTime(time_t ts) {
+            m_ts = ts;
+        }
+
+        /**
          * Evaluates the policy against the given request and message,
          * possibly populating message information in the policy object.
          *
@@ -410,6 +447,10 @@ namespace opensaml {
         const xmltooling::TrustEngine* m_trust;
         bool m_validate;
         bool m_entityOnly;
+
+        // contextual information
+        const XMLCh* m_recipient;
+        time_t m_ts;
     };
 
 };
index ae17ba4..003e7ec 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright 2001-2009 Internet2
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file saml/binding/SecurityPolicyRule.h
- * 
+ *
  * Policy rules that secure and authenticate bindings.
  */
 
 #include <saml/binding/SecurityPolicy.h>
 
 namespace opensaml {
-    
+
     /**
      * A rule that a protocol request and message must meet in order to be valid and secure.
-     * 
+     *
      * <p>Rules must be stateless and thread-safe across evaluations. Evaluation should not
      * result in an exception if the request/message properties do not apply to the rule
-     * (e.g. particular security mechanisms that are not present). 
+     * (e.g. particular security mechanisms that are not present).
      */
     class SAML_API SecurityPolicyRule
     {
@@ -51,14 +51,14 @@ namespace opensaml {
 
         /**
          * Evaluates the rule against the given request and message.
-         * 
+         *
          * <p>An exception will be raised if the message is invalid according to
          * a policy rule.
          *
          * <p>The return value is used to indicate whether a message was ignored or
          * successfully processed. A false value signals that the rule wasn't successful
          * but was also not unsuccessful, because the rule was inapplicable to the message.
-         * 
+         *
          * @param message   the incoming message
          * @param request   the protocol request
          * @param policy    SecurityPolicy to provide various components and track message data
@@ -77,49 +77,64 @@ namespace opensaml {
     void SAML_API registerSecurityPolicyRules();
 
     /**
+     * SecurityPolicyRule for evaluation of SAML AudienceRestriction Conditions.
+     */
+    #define AUDIENCE_POLICY_RULE        "Audience"
+
+    /**
      * SecurityPolicyRule for TLS client certificate authentication.
-     * 
+     *
      * Evaluates client certificates against the issuer's metadata.
      */
     #define CLIENTCERTAUTH_POLICY_RULE  "ClientCertAuth"
 
     /**
+     * SecurityPolicyRule for evaluation of SAML Conditions.
+     */
+    #define CONDITIONS_POLICY_RULE      "Conditions"
+
+    /**
+     * SecurityPolicyRule for ignoring a SAML Condition.
+     */
+    #define IGNORE_POLICY_RULE          "Ignore"
+
+    /**
      * SecurityPolicyRule for replay detection and freshness checking.
-     * 
+     *
      * <p>A ReplayCache instance must be available from the runtime, unless
      * a "checkReplay" XML attribute is set to "0" or "false" when instantiating
      * the policy rule.
-     * 
+     *
      * <p>Messages must have been issued in the past, but no more than 60 seconds ago,
      * or up to a number of seconds set by an "expires" XML attribute when
      * instantiating the policy rule.
      */
-    #define MESSAGEFLOW_POLICY_RULE  "MessageFlow"
+    #define MESSAGEFLOW_POLICY_RULE     "MessageFlow"
 
     /**
      * SecurityPolicyRule for disabling security.
-     * 
+     *
      * Allows the message issuer to be authenticated regardless of the message or
      * transport. Used mainly for debugging or in situations that I wouldn't care to
      * comment on.
      */
-    #define NULLSECURITY_POLICY_RULE  "NullSecurity"
+    #define NULLSECURITY_POLICY_RULE    "NullSecurity"
 
     /**
      * SecurityPolicyRule for protocol message "blob" signing.
-     * 
+     *
      * Allows the message issuer to be authenticated using a non-XML digital signature
      * over the message body. The transport layer is not considered.
      */
-    #define SIMPLESIGNING_POLICY_RULE  "SimpleSigning"
+    #define SIMPLESIGNING_POLICY_RULE   "SimpleSigning"
 
     /**
      * SecurityPolicyRule for protocol message XML signing.
-     * 
+     *
      * Allows the message issuer to be authenticated using an XML digital signature
      * over the message. The transport layer is not considered.
      */
-    #define XMLSIGNING_POLICY_RULE  "XMLSigning"
+    #define XMLSIGNING_POLICY_RULE      "XMLSigning"
 };
 
 #endif /* __saml_secrule_h__ */
index f371f1f..4ef7632 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright 2001-2009 Internet2
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * MessageFlowRule.cpp
- * 
+ *
  * SAML replay and freshness checking SecurityPolicyRule
  */
 
@@ -39,12 +39,12 @@ namespace opensaml {
     public:
         MessageFlowRule(const DOMElement* e);
         virtual ~MessageFlowRule() {}
-        
+
         const char* getType() const {
             return MESSAGEFLOW_POLICY_RULE;
         }
         bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
-    
+
     private:
         bool m_checkReplay;
         time_t m_expires;
@@ -77,7 +77,7 @@ bool MessageFlowRule::evaluate(const XMLObject& message, const GenericRequest* r
     Category& log=Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.MessageFlow");
     log.debug("evaluating message flow policy (replay checking %s, expiration %lu)", m_checkReplay ? "on" : "off", m_expires);
 
-    time_t now = time(NULL);
+    time_t now = policy.getTime();
     time_t skew = XMLToolingConfig::getConfig().clock_skew_secs;
     time_t issueInstant = policy.getIssueInstant();
     if (issueInstant == 0) {
@@ -95,7 +95,7 @@ bool MessageFlowRule::evaluate(const XMLObject& message, const GenericRequest* r
             throw SecurityPolicyException("Message expired, was issued too long ago.");
         }
     }
-    
+
     // Check replay.
     if (m_checkReplay) {
         const XMLCh* id = policy.getMessageID();
index af93a86..d78e1df 100644 (file)
@@ -32,7 +32,10 @@ using namespace xmltooling;
 using namespace std;
 
 namespace opensaml {
+    SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory AudienceRestrictionRuleFactory;
     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory ClientCertAuthRuleFactory;
+    SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory ConditionsRuleFactory;
+    SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory IgnoreRuleFactory;
     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory MessageFlowRuleFactory;
     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory NullSecurityRuleFactory;
     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory SimpleSigningRuleFactory;
@@ -42,7 +45,10 @@ namespace opensaml {
 void SAML_API opensaml::registerSecurityPolicyRules()
 {
     SAMLConfig& conf=SAMLConfig::getConfig();
+    conf.SecurityPolicyRuleManager.registerFactory(AUDIENCE_POLICY_RULE, AudienceRestrictionRuleFactory);
     conf.SecurityPolicyRuleManager.registerFactory(CLIENTCERTAUTH_POLICY_RULE, ClientCertAuthRuleFactory);
+    conf.SecurityPolicyRuleManager.registerFactory(CONDITIONS_POLICY_RULE, ConditionsRuleFactory);
+    conf.SecurityPolicyRuleManager.registerFactory(IGNORE_POLICY_RULE, IgnoreRuleFactory);
     conf.SecurityPolicyRuleManager.registerFactory(MESSAGEFLOW_POLICY_RULE, MessageFlowRuleFactory);
     conf.SecurityPolicyRuleManager.registerFactory(NULLSECURITY_POLICY_RULE, NullSecurityRuleFactory);
     conf.SecurityPolicyRuleManager.registerFactory(SIMPLESIGNING_POLICY_RULE, SimpleSigningRuleFactory);
@@ -51,6 +57,30 @@ void SAML_API opensaml::registerSecurityPolicyRules()
 
 SecurityPolicy::IssuerMatchingPolicy SecurityPolicy::m_defaultMatching;
 
+SecurityPolicy::SecurityPolicy(
+    const saml2md::MetadataProvider* metadataProvider,
+    const xmltooling::QName* role,
+    const xmltooling::TrustEngine* trustEngine,
+    bool validate
+    ) : m_metadataCriteria(NULL),
+        m_messageID(NULL),
+        m_issueInstant(0),
+        m_issuer(NULL),
+        m_issuerRole(NULL),
+        m_authenticated(false),
+        m_matchingPolicy(NULL),
+        m_metadata(metadataProvider),
+        m_role(NULL),
+        m_trust(trustEngine),
+        m_validate(validate),
+        m_entityOnly(true),
+        m_recipient(NULL),
+        m_ts(0)
+{
+    if (role)
+        m_role = new xmltooling::QName(*role);
+}
+
 SecurityPolicy::~SecurityPolicy()
 {
     XMLString::release(&m_messageID);
diff --git a/saml/profile/impl/AudienceRestrictionRule.cpp b/saml/profile/impl/AudienceRestrictionRule.cpp
new file mode 100644 (file)
index 0000000..e4b03e4
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * AudienceRestrictionRule.cpp
+ *
+ * SAML AudienceRestriction SecurityPolicyRule
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "binding/SecurityPolicyRule.h"
+#include "saml1/core/Assertions.h"
+#include "saml2/core/Assertions.h"
+
+#include <xmltooling/logging.h>
+
+using namespace opensaml;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace std;
+
+namespace opensaml {
+    class SAML_DLLLOCAL AudienceRestrictionRule : public SecurityPolicyRule
+    {
+    public:
+        AudienceRestrictionRule(const DOMElement* e);
+
+        virtual ~AudienceRestrictionRule() {
+        }
+        const char* getType() const {
+            return AUDIENCE_POLICY_RULE;
+        }
+        bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
+
+    private:
+        vector<const XMLCh*> m_audiences;
+    };
+
+    SecurityPolicyRule* SAML_DLLLOCAL AudienceRestrictionRuleFactory(const DOMElement* const & e)
+    {
+        return new AudienceRestrictionRule(e);
+    }
+};
+
+AudienceRestrictionRule::AudienceRestrictionRule(const DOMElement* e)
+{
+    e = e ? XMLHelper::getFirstChildElement(e, saml2::Audience::LOCAL_NAME) : NULL;
+    while (e) {
+        if (e->hasChildNodes())
+            m_audiences.push_back(e->getFirstChild()->getNodeValue());
+        e = XMLHelper::getNextSiblingElement(e, saml2::Audience::LOCAL_NAME);
+    }
+}
+
+bool AudienceRestrictionRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
+{
+    const saml2::AudienceRestriction* ac2=dynamic_cast<const saml2::AudienceRestriction*>(&message);
+    if (ac2) {
+        const vector<saml2::Audience*>& auds2 = ac2->getAudiences();
+        for (vector<saml2::Audience*>::const_iterator a1 = auds2.begin(); a1!=auds2.end(); ++a1) {
+            if (XMLString::equals(policy.getRecipient(), (*a1)->getAudienceURI())) {
+                return true;
+            }
+            for (vector<const XMLCh*>::const_iterator a2 = m_audiences.begin(); a2!=m_audiences.end(); ++a2) {
+                if (XMLString::equals((*a1)->getAudienceURI(), *a2))
+                    return true;
+            }
+        }
+
+        ostringstream os;
+        os << *ac2;
+        Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.AudienceRestriction").error(
+            "unacceptable AudienceRestriction in assertion (%s)", os.str().c_str()
+            );
+        throw SecurityPolicyException("Assertion contains an unacceptable AudienceRestriction.");
+    }
+
+    const saml1::AudienceRestrictionCondition* ac1=dynamic_cast<const saml1::AudienceRestrictionCondition*>(&message);
+    if (ac1) {
+        const vector<saml1::Audience*>& auds1 = ac1->getAudiences();
+        for (vector<saml1::Audience*>::const_iterator a1 = auds1.begin(); a1!=auds1.end(); ++a1) {
+            if (XMLString::equals(policy.getRecipient(), (*a1)->getAudienceURI())) {
+                return true;
+            }
+            for (vector<const XMLCh*>::const_iterator a2 = m_audiences.begin(); a2!=m_audiences.end(); ++a2) {
+                if (XMLString::equals((*a1)->getAudienceURI(), *a2))
+                    return true;
+            }
+        }
+
+        ostringstream os;
+        os << *ac1;
+        Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.AudienceRestriction").error(
+            "unacceptable AudienceRestrictionCondition in assertion (%s)", os.str().c_str()
+            );
+        throw SecurityPolicyException("Assertion contains an unacceptable AudienceRestrictionCondition.");
+    }
+
+    return false;
+}
diff --git a/saml/profile/impl/ConditionsRule.cpp b/saml/profile/impl/ConditionsRule.cpp
new file mode 100644 (file)
index 0000000..933c61e
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * ConditionsRule.cpp
+ *
+ * SAML Conditions SecurityPolicyRule
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "binding/SecurityPolicyRule.h"
+#include "saml1/core/Assertions.h"
+#include "saml2/core/Assertions.h"
+
+#include <xmltooling/logging.h>
+
+using namespace opensaml;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace std;
+
+namespace opensaml {
+    class SAML_DLLLOCAL ConditionsRule : public SecurityPolicyRule
+    {
+    public:
+        ConditionsRule(const DOMElement* e);
+
+        virtual ~ConditionsRule() {
+            for_each(m_rules.begin(), m_rules.end(), xmltooling::cleanup<SecurityPolicyRule>());
+            if (m_doc)
+                m_doc->release();
+        }
+        const char* getType() const {
+            return CONDITIONS_POLICY_RULE;
+        }
+        bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
+
+    private:
+        DOMDocument* m_doc;
+        vector<SecurityPolicyRule*> m_rules;
+    };
+
+    SecurityPolicyRule* SAML_DLLLOCAL ConditionsRuleFactory(const DOMElement* const & e)
+    {
+        return new ConditionsRule(e);
+    }
+
+    static const XMLCh Rule[] =     UNICODE_LITERAL_4(R,u,l,e);
+    static const XMLCh type[] =     UNICODE_LITERAL_4(t,y,p,e);
+
+    const char config[] =
+        "<Rule type=\"Conditions\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\">"\r
+            "<Rule type=\"Audience\"/>"\r
+            "<Rule type=\"Ignore\">saml:DoNotCacheCondition</Rule>"\r
+            "<Rule type=\"Ignore\">saml2:OneTimeUse</Rule>"\r
+            "<Rule type=\"Ignore\">saml2:ProxyRestriction</Rule>"\r
+        "</Rule>";\r
+};
+
+ConditionsRule::ConditionsRule(const DOMElement* e) : m_doc(NULL)
+{
+    Category& log=Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.Conditions");
+
+    if (!e || !e->hasChildNodes()) {
+        // Default the configuration.
+        istringstream in(config);
+        m_doc = XMLToolingConfig::getConfig().getParser().parse(in);
+        e = m_doc->getDocumentElement();
+    }
+
+    e = XMLHelper::getFirstChildElement(e, Rule);
+    while (e) {
+        auto_ptr_char temp(e->getAttributeNS(NULL, type));
+        if (temp.get() && *temp.get()) {
+            try {
+                log.info("building SecurityPolicyRule of type %s", temp.get());
+                m_rules.push_back(SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(temp.get(),e));
+            }
+            catch (exception& ex) {
+                log.crit("error building SecurityPolicyRule: %s", ex.what());
+            }
+        }
+        e = XMLHelper::getNextSiblingElement(e, Rule);
+    }
+}
+
+bool ConditionsRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
+{
+    const saml2::Assertion* a2=dynamic_cast<const saml2::Assertion*>(&message);
+    if (a2) {
+        const saml2::Conditions* conds = a2->getConditions();
+        if (!conds)
+            return true;
+
+        // First verify the time conditions, using the specified timestamp.
+        time_t now = policy.getTime();
+        unsigned int skew = XMLToolingConfig::getConfig().clock_skew_secs;
+        time_t t = conds->getNotBeforeEpoch();
+        if (now + skew < t)
+            throw SecurityPolicyException("Assertion is not yet valid.");
+        t = conds->getNotOnOrAfterEpoch();
+        if (t <= now - skew)
+            throw SecurityPolicyException("Assertion is no longer valid.");
+
+        // Now we process conditions, starting with the known types and then extensions.
+
+        bool valid;
+
+        const vector<saml2::AudienceRestriction*>& acvec = conds->getAudienceRestrictions();
+        for (vector<saml2::AudienceRestriction*>::const_iterator ac = acvec.begin(); ac!=acvec.end(); ++ac) {
+            valid = false;
+            for (vector<SecurityPolicyRule*>::const_iterator r = m_rules.begin(); r != m_rules.end(); ++r) {
+                if ((*r)->evaluate(*(*ac), request, policy))
+                    valid = true;
+            }
+            if (!valid)
+                throw SecurityPolicyException("AudienceRestriction was not understood by policy.");
+        }
+
+        const vector<saml2::OneTimeUse*>& otvec = conds->getOneTimeUses();
+        for (vector<saml2::OneTimeUse*>::const_iterator ot = otvec.begin(); ot!=otvec.end(); ++ot) {
+            valid = false;
+            for (vector<SecurityPolicyRule*>::const_iterator r = m_rules.begin(); r != m_rules.end(); ++r) {
+                if ((*r)->evaluate(*(*ot), request, policy))
+                    valid = true;
+            }
+            if (!valid)
+                throw SecurityPolicyException("OneTimeUse was not understood by policy.");
+        }
+
+        const vector<saml2::ProxyRestriction*> pvec = conds->getProxyRestrictions();
+        for (vector<saml2::ProxyRestriction*>::const_iterator p = pvec.begin(); p!=pvec.end(); ++p) {
+            valid = false;
+            for (vector<SecurityPolicyRule*>::const_iterator r = m_rules.begin(); r != m_rules.end(); ++r) {
+                if ((*r)->evaluate(*(*p), request, policy))
+                    valid = true;
+            }
+            if (!valid)
+                throw SecurityPolicyException("ProxyRestriction was not understood by policy.");
+        }
+
+        const vector<saml2::Condition*>& convec = conds->getConditions();
+        for (vector<saml2::Condition*>::const_iterator c = convec.begin(); c!=convec.end(); ++c) {
+            valid = false;
+            for (vector<SecurityPolicyRule*>::const_iterator r = m_rules.begin(); r != m_rules.end(); ++r) {
+                if ((*r)->evaluate(*(*c), request, policy))
+                    valid = true;
+            }
+            if (!valid)
+                throw SecurityPolicyException("Condition ($1) was not understood by policy.", params(1,(*c)->getElementQName().toString().c_str()));
+        }
+
+        return true;
+    }
+
+    const saml1::Assertion* a1=dynamic_cast<const saml1::Assertion*>(&message);
+    if (a1) {
+        const saml1::Conditions* conds = a1->getConditions();
+        if (!conds)
+            return true;
+
+        // First verify the time conditions, using the specified timestamp.
+        time_t now = policy.getTime();
+        unsigned int skew = XMLToolingConfig::getConfig().clock_skew_secs;
+        time_t t = conds->getNotBeforeEpoch();
+        if (now + skew < t)
+            throw SecurityPolicyException("Assertion is not yet valid.");
+        t = conds->getNotOnOrAfterEpoch();
+        if (t <= now - skew)
+            throw SecurityPolicyException("Assertion is no longer valid.");
+
+        // Now we process conditions, starting with the known types and then extensions.
+
+        bool valid;
+
+        const vector<saml1::AudienceRestrictionCondition*>& acvec = conds->getAudienceRestrictionConditions();
+        for (vector<saml1::AudienceRestrictionCondition*>::const_iterator ac = acvec.begin(); ac!=acvec.end(); ++ac) {
+            valid = false;
+            for (vector<SecurityPolicyRule*>::const_iterator r = m_rules.begin(); r != m_rules.end(); ++r) {
+                if ((*r)->evaluate(*(*ac), request, policy))
+                    valid = true;
+            }
+            if (!valid)
+                throw SecurityPolicyException("AudienceRestrictionCondition was not understood by policy.");
+        }
+
+        const vector<saml1::DoNotCacheCondition*>& dncvec = conds->getDoNotCacheConditions();
+        for (vector<saml1::DoNotCacheCondition*>::const_iterator dnc = dncvec.begin(); dnc!=dncvec.end(); ++dnc) {
+            valid = false;
+            for (vector<SecurityPolicyRule*>::const_iterator r = m_rules.begin(); r != m_rules.end(); ++r) {
+                if ((*r)->evaluate(*(*dnc), request, policy))
+                    valid = true;
+            }
+            if (!valid)
+                throw SecurityPolicyException("DoNotCacheCondition was not understood by policy.");
+        }
+
+        const vector<saml1::Condition*>& convec = conds->getConditions();
+        for (vector<saml1::Condition*>::const_iterator c = convec.begin(); c!=convec.end(); ++c) {
+            valid = false;
+            for (vector<SecurityPolicyRule*>::const_iterator r = m_rules.begin(); r != m_rules.end(); ++r) {
+                if ((*r)->evaluate(*(*c), request, policy))
+                    valid = true;
+            }
+            if (!valid)
+                throw SecurityPolicyException("Condition ($1) was not understood by policy.", params(1,(*c)->getElementQName().toString().c_str()));
+        }
+
+        return true;
+    }
+
+    return false;
+}
diff --git a/saml/profile/impl/IgnoreRule.cpp b/saml/profile/impl/IgnoreRule.cpp
new file mode 100644 (file)
index 0000000..f602424
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * IgnoreRule.cpp
+ *
+ * SecurityPolicyRule that ignores a message while indicating "success".
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "binding/SecurityPolicyRule.h"
+
+#include <xmltooling/logging.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace opensaml;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace std;
+
+
+namespace opensaml {
+    class SAML_DLLLOCAL IgnoreRule : public SecurityPolicyRule
+    {
+    public:
+        IgnoreRule(const DOMElement* e)
+            : m_log(Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.Ignore")), m_qname(XMLHelper::getNodeValueAsQName(e)) {
+            if (!m_qname)
+                throw SecurityPolicyException("No schema type or element name supplied to Ignore rule.");
+        }
+        virtual ~IgnoreRule() {
+            delete m_qname;
+        }
+
+        const char* getType() const {
+            return IGNORE_POLICY_RULE;
+        }
+        bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const {
+            if (message.getSchemaType()) {
+                if (*m_qname != *(message.getSchemaType()))
+                    return false;
+                m_log.info("ignoring condition with type (%s)", message.getSchemaType()->toString().c_str());
+            }
+            else {
+                if (*m_qname != message.getElementQName())
+                    return false;
+                m_log.info("ignoring condition (%s)", message.getElementQName().toString().c_str());
+            }
+            return true;
+        }
+
+    private:
+        Category& m_log;
+        xmltooling::QName* m_qname;
+    };
+
+    SecurityPolicyRule* SAML_DLLLOCAL IgnoreRuleFactory(const DOMElement* const & e)
+    {
+        return new IgnoreRule(e);
+    }
+};
index e2c0728..ab67f1f 100644 (file)
                                                        />\r
                                                </FileConfiguration>\r
                                        </File>\r
+                                       <File\r
+                                               RelativePath=".\saml2\profile\SAML2AssertionPolicy.cpp"\r
+                                               >\r
+                                       </File>\r
                                </Filter>\r
                        </Filter>\r
                        <Filter\r
                                        >\r
                                </File>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="profile"\r
+                               >\r
+                               <Filter\r
+                                       Name="impl"\r
+                                       >\r
+                                       <File\r
+                                               RelativePath=".\profile\impl\AudienceRestrictionRule.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath=".\profile\impl\ConditionsRule.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath=".\profile\impl\IgnoreRule.cpp"\r
+                                               >\r
+                                       </File>\r
+                               </Filter>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                                                RelativePath=".\saml2\profile\BrowserSSOProfileValidator.h"\r
                                                >\r
                                        </File>\r
+                                       <File\r
+                                               RelativePath=".\saml2\profile\SAML2AssertionPolicy.h"\r
+                                               >\r
+                                       </File>\r
                                </Filter>\r
                        </Filter>\r
                        <Filter\r
index 7e4eefc..aa26c79 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright 2001-2007 Internet2
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file saml/saml1/profile/AssertionValidator.h
- * 
+ *
  * SAML 1.x basic assertion validator
  */
 
 
 namespace opensaml {
     namespace saml1 {
-        
+
         class SAML_API Assertion;
         class SAML_API Condition;
-        
+
         /**
+         * @deprecated
          * SAML 1.x basic assertion validator provides time and audience condition checking.
          */
         class SAML_API AssertionValidator : public virtual xmltooling::Validator
@@ -40,7 +41,7 @@ namespace opensaml {
         public:
             /**
              * Constructor
-             * 
+             *
              * @param recipient name of assertion recipient (implicit audience)
              * @param audiences additional audience values
              * @param ts        timestamp to evaluate assertion conditions, or 0 to bypass check
@@ -50,12 +51,12 @@ namespace opensaml {
             }
 
             virtual ~AssertionValidator() {}
-    
+
             void validate(const xmltooling::XMLObject* xmlObject) const;
 
             /**
              * Type-safe validation method.
-             * 
+             *
              * @param assertion assertion to validate
              */
             virtual void validateAssertion(const Assertion& assertion) const;
@@ -66,7 +67,7 @@ namespace opensaml {
              * <p>The base class version only understands AudienceRestrictionConditions.
              * All other condition types will be rejected and require subclassing to
              * prevent validation failure.
-             * 
+             *
              * @param condition condition to validate
              */
             virtual void validateCondition(const Condition* condition) const;
@@ -74,14 +75,14 @@ namespace opensaml {
         protected:
             /** Name of recipient (implicit audience). */
             const XMLCh* m_recipient;
-            
+
             /** Additional audience values. */
             const std::vector<const XMLCh*>* m_audiences;
 
             /** Timestamp to evaluate assertion conditions. */
             time_t m_ts;
         };
-        
+
     };
 };
 
index 65d304b..0580d14 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright 2001-2007 Internet2
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -16,8 +16,8 @@
 
 /**
  * @file saml/saml1/profile/BrowserSSOProfileValidator.h
- * 
- * SAML 1.x Browser SSO Profile Assertion Validator 
+ *
+ * SAML 1.x Browser SSO Profile Assertion Validator
  */
 
 #ifndef __saml1_ssoval_h__
@@ -27,8 +27,9 @@
 
 namespace opensaml {
     namespace saml1 {
-        
+
         /**
+         * @deprecated
          * SAML 1.x Browser SSO Profile Assertion Validator
          *
          * <p>In addition to standard core requirements for validity, SSO assertions
@@ -40,7 +41,7 @@ namespace opensaml {
         public:
             /**
              * Constructor
-             * 
+             *
              * @recipient       name of assertion recipient (implicit audience)
              * @param audiences additional audience values
              * @param ts        timestamp to evaluate assertion conditions, or 0 to bypass check
@@ -49,10 +50,10 @@ namespace opensaml {
                 : AssertionValidator(recipient, audiences, ts) {
             }
             virtual ~BrowserSSOProfileValidator() {}
-    
+
             void validateAssertion(const Assertion& assertion) const;
         };
-        
+
     };
 };
 
index 240fd9d..8a05e29 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright 2001-2007 Internet2
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file saml/saml2/profile/AssertionValidator.h
- * 
+ *
  * SAML 2.0 basic assertion validator
  */
 
 
 namespace opensaml {
     namespace saml2 {
-        
+
         class SAML_API Assertion;
         class SAML_API Condition;
-        
+
         /**
+         * @deprecated
          * SAML 2.0 basic assertion validator provides time and audience condition checking.
          */
         class SAML_API AssertionValidator : public virtual xmltooling::Validator
@@ -40,7 +41,7 @@ namespace opensaml {
         public:
             /**
              * Constructor
-             * 
+             *
              * @param recipient name of assertion recipient (implicit audience)
              * @param audiences additional audience values
              * @param ts        timestamp to evaluate assertion conditions, or 0 to bypass check
@@ -50,12 +51,12 @@ namespace opensaml {
             }
 
             virtual ~AssertionValidator() {}
-    
+
             void validate(const xmltooling::XMLObject* xmlObject) const;
 
             /**
              * Type-safe validation method.
-             * 
+             *
              * @param assertion assertion to validate
              */
             virtual void validateAssertion(const Assertion& assertion) const;
@@ -66,7 +67,7 @@ namespace opensaml {
              * <p>The base class version only understands AudienceRestriction conditions.
              * All other condition types will be rejected and require subclassing to
              * prevent validation failure.
-             * 
+             *
              * @param condition condition to validate
              */
             virtual void validateCondition(const Condition* condition) const;
@@ -81,7 +82,7 @@ namespace opensaml {
             /** Timestamp to evaluate assertion conditions. */
             time_t m_ts;
         };
-        
+
     };
 };
 
index 97318bd..460c99d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright 2001-2007 Internet2
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -16,8 +16,8 @@
 
 /**
  * @file saml/saml2/profile/BrowserSSOProfileValidator.h
- * 
- * SAML 2.0 Browser SSO Profile Assertion Validator 
+ *
+ * SAML 2.0 Browser SSO Profile Assertion Validator
  */
 
 #ifndef __saml2_ssoval_h__
 #include <saml/saml2/profile/AssertionValidator.h>
 
 namespace opensaml {
-    
+
     namespace saml2 {
-        
+
         /**
+         * @deprecated
          * SAML 2.0 Browser SSO Profile Assertion Validator
          *
          * <p>In addition to standard core requirements for validity, SSO assertions
@@ -41,7 +42,7 @@ namespace opensaml {
         public:
             /**
              * Constructor
-             * 
+             *
              * @param recipient     name of assertion recipient (implicit audience)
              * @param audiences     additional audience values
              * @param ts            timestamp to evaluate assertion conditions, or 0 to bypass check
@@ -57,7 +58,7 @@ namespace opensaml {
                 ) : AssertionValidator(recipient, audiences, ts), m_destination(destination), m_requestID(requestID) {
             }
             virtual ~BrowserSSOProfileValidator() {}
-    
+
             void validateAssertion(const Assertion& assertion) const;
 
             /**
@@ -68,7 +69,7 @@ namespace opensaml {
             const char* getAddress() const {
                 return m_address.c_str();
             }
-        
+
         protected:
             /** Server location to which assertion was delivered. */
             xmltooling::auto_ptr_XMLCh m_destination;
@@ -80,7 +81,7 @@ namespace opensaml {
             /** Address in confirmed bearer SubjectConfirmationData. */
             mutable std::string m_address;
         };
-        
+
     };
 };
 
diff --git a/saml/saml2/profile/SAML2AssertionPolicy.cpp b/saml/saml2/profile/SAML2AssertionPolicy.cpp
new file mode 100644 (file)
index 0000000..08e9768
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * SAML2AssertionPolicy.cpp
+ *
+ * Policy subclass to track SAML 2.0 Assertion SubjectConfirmation.
+ */
+
+#include "internal.h"
+#include "saml2/profile/SAML2AssertionPolicy.h"
+
+using namespace opensaml::saml2;
+using namespace opensaml;
+
+void SAML2AssertionPolicy::reset(bool messageOnly)
+{
+    SecurityPolicy::reset(messageOnly);
+    SAML2AssertionPolicy::_reset(messageOnly);
+}
diff --git a/saml/saml2/profile/SAML2AssertionPolicy.h b/saml/saml2/profile/SAML2AssertionPolicy.h
new file mode 100644 (file)
index 0000000..271d7e9
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file saml/saml2/profile/SAML2AssertionPolicy.h
+ *
+ * Policy subclass to track SAML 2.0 Assertion SubjectConfirmation.
+ */
+
+#ifndef __saml_saml2asspol_h__
+#define __saml_saml2asspol_h__
+
+#include <saml/binding/SecurityPolicy.h>
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4250 4251 )
+#endif
+
+namespace opensaml {
+
+    namespace saml2 {
+        class SAML_API SubjectConfirmation;
+    };
+
+    /**
+     * Policy subclass to track SAML 2.0 Assertion SubjectConfirmation.
+     */
+    class SAML_API SAML2AssertionPolicy : virtual public SecurityPolicy
+    {
+    public:
+        /**
+         * Constructor for policy.
+         *
+         * @param metadataProvider  locked MetadataProvider instance
+         * @param role              identifies the role (generally IdP or SP) of the policy peer
+         * @param trustEngine       TrustEngine to authenticate policy peer
+         * @param validate          true iff XML parsing should be done with validation
+         */
+        SAML2AssertionPolicy(
+            const saml2md::MetadataProvider* metadataProvider=NULL,
+            const xmltooling::QName* role=NULL,
+            const xmltooling::TrustEngine* trustEngine=NULL,
+            bool validate=true
+            ) : SecurityPolicy(metadataProvider, role, trustEngine, validate) {
+        }
+
+        virtual ~SAML2AssertionPolicy() {}
+
+        virtual void reset(bool messageOnly=false);
+        void _reset(bool messageOnly=false) {
+            m_confirmation = false;
+        }
+
+        /**
+         * Returns the subject confirmation that was successfully accepted by the policy.
+         *
+         * @return a successfully evaluated SubjectConfirmation
+         */
+        const saml2::SubjectConfirmation* getSubjectConfirmation() const {
+            return m_confirmation;
+        }
+
+        /**
+         * Sets the SubjectConfirmation that was successfully accepted by the policy.
+         *
+         * <p>The lifetime of the SubjectConfirmation object <strong>MUST</strong> be longer
+         * than the lifetime of the policy object.
+         *
+         * @param confirmation the successfully evaluated SubjectConfirmation
+         */
+        void setSubjectConfirmation(const saml2::SubjectConfirmation* confirmation) {
+            m_confirmation = confirmation;
+        }
+
+    private:
+        const saml2::SubjectConfirmation* m_confirmation;
+    };
+
+};
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+#endif /* __saml_saml2asspol_h__ */
index 3f9400d..25d89d5 100644 (file)
@@ -33,6 +33,7 @@ samltest_h = \
     saml1/core/impl/AuthenticationStatementTest.h \
     saml1/binding/SAML1ArtifactTest.h \
     saml1/binding/SAML1POSTTest.h \
+    saml1/profile/SAML1PolicyTest.h \ 
     saml2/core/impl/Action20Test.h \
     saml2/core/impl/Advice20Test.h \
     saml2/core/impl/Artifact20Test.h \
@@ -93,7 +94,8 @@ samltest_h = \
     saml2/binding/SAML2ArtifactTest.h \
     saml2/binding/SAML2POSTTest.h \
     saml2/binding/SAML2RedirectTest.h \
-    saml2/metadata/XMLMetadataProviderTest.h
+    saml2/metadata/XMLMetadataProviderTest.h \
+    saml2/profile/SAML2PolicyTest.h
 
 noinst_HEADERS = \
        binding.h \
diff --git a/samltest/data/saml1/profile/SAML1Assertion.xml b/samltest/data/saml1/profile/SAML1Assertion.xml
new file mode 100644 (file)
index 0000000..01d7d96
--- /dev/null
@@ -0,0 +1,12 @@
+<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="aident"
+IssueInstant="1970-01-02T01:01:02.100Z" Issuer="https://idp.example.org/" MajorVersion="1" MinorVersion="1">
+    <saml:Conditions NotBefore="2008-01-02T01:01:02.100Z" NotOnOrAfter="2030-01-02T01:01:02.100Z">
+        <saml:AudienceRestrictionCondition>
+            <saml:Audience>https://sp.example.org</saml:Audience>
+        </saml:AudienceRestrictionCondition>
+        <saml:DoNotCacheCondition/>
+    </saml:Conditions>
+    <saml:AuthenticationStatement AuthenticationInstant="1970-01-02T01:01:02.100Z" AuthenticationMethod="method">
+        <saml:Subject><saml:NameIdentifier>John Doe</saml:NameIdentifier></saml:Subject>
+    </saml:AuthenticationStatement>
+</saml:Assertion>
diff --git a/samltest/data/saml2/profile/SAML2Assertion.xml b/samltest/data/saml2/profile/SAML2Assertion.xml
new file mode 100644 (file)
index 0000000..758e79e
--- /dev/null
@@ -0,0 +1,13 @@
+<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="aident" IssueInstant="1970-01-02T01:01:02.100Z" Version="2.0">
+    <saml:Issuer>https://idp.example.org/</saml:Issuer>
+    <saml:Subject><saml:NameID>John Doe</saml:NameID></saml:Subject>
+    <saml:Conditions NotBefore="2008-01-02T01:01:02.100Z" NotOnOrAfter="2030-01-02T01:01:02.100Z">
+        <saml:AudienceRestriction>
+            <saml:Audience>https://sp.example.org</saml:Audience>
+        </saml:AudienceRestriction>
+        <saml:OneTimeUse/>
+    </saml:Conditions>
+    <saml:AuthnStatement AuthnInstant="1970-01-02T01:01:02.100Z">
+        <saml:AuthnContext><saml:AuthnContextClassRef>foo</saml:AuthnContextClassRef></saml:AuthnContext>
+    </saml:AuthnStatement>
+</saml:Assertion>
diff --git a/samltest/saml1/profile/.gitignore b/samltest/saml1/profile/.gitignore
new file mode 100644 (file)
index 0000000..e16b497
--- /dev/null
@@ -0,0 +1 @@
+/*.cpp
diff --git a/samltest/saml1/profile/SAML1PolicyTest.h b/samltest/saml1/profile/SAML1PolicyTest.h
new file mode 100644 (file)
index 0000000..82660b1
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  Copyright 2001-2007 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "internal.h"
+
+#include <saml/SAMLConfig.h>
+#include <saml/binding/SecurityPolicyRule.h>
+#include <saml/saml1/core/Assertions.h>
+
+using namespace opensaml;
+
+class SAML1PolicyTest : public CxxTest::TestSuite {
+    SecurityPolicy* m_policy;
+    SecurityPolicyRule* m_rule;
+public:
+    void setUp() {
+        m_policy = NULL;
+        m_rule = NULL;
+        m_rule = SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, NULL);
+        m_policy = new SecurityPolicy();
+        m_policy->getRules().push_back(m_rule);
+    }
+
+    void tearDown() {
+        delete m_rule;
+        delete m_policy;
+    }
+
+    void testSAML1Policy() {
+        try {
+            // Read assertion to use from file.
+            string path = data_path + "saml1/profile/SAML1Assertion.xml";
+            ifstream in(path.c_str());
+            DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
+            XercesJanitor<DOMDocument> janitor(doc);
+            auto_ptr<saml1::Assertion> assertion(
+                dynamic_cast<saml1::Assertion*>(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(),true))
+                );
+            janitor.release();
+
+            TSM_ASSERT_THROWS("Policy should have tripped on AudienceRestriction", m_policy->evaluate(*assertion.get()), SecurityPolicyException);
+
+            auto_ptr_XMLCh recipient("https://sp.example.org");
+            m_policy->setRecipient(recipient.get());
+            m_policy->evaluate(*assertion.get());
+        }
+        catch (exception& ex) {
+            TS_TRACE(ex.what());
+            throw;
+        }
+    }
+};
diff --git a/samltest/saml2/profile/.gitignore b/samltest/saml2/profile/.gitignore
new file mode 100644 (file)
index 0000000..e16b497
--- /dev/null
@@ -0,0 +1 @@
+/*.cpp
diff --git a/samltest/saml2/profile/SAML2PolicyTest.h b/samltest/saml2/profile/SAML2PolicyTest.h
new file mode 100644 (file)
index 0000000..f4cc1d8
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  Copyright 2001-2007 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "internal.h"
+
+#include <saml/SAMLConfig.h>
+#include <saml/binding/SecurityPolicyRule.h>
+#include <saml/saml2/core/Assertions.h>
+
+using namespace opensaml;
+
+class SAML2PolicyTest : public CxxTest::TestSuite {
+    SecurityPolicy* m_policy;
+    SecurityPolicyRule* m_rule;
+public:
+    void setUp() {
+        m_policy = NULL;
+        m_rule = NULL;
+        m_rule = SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, NULL);
+        m_policy = new SecurityPolicy();
+        m_policy->getRules().push_back(m_rule);
+    }
+
+    void tearDown() {
+        delete m_rule;
+        delete m_policy;
+    }
+
+    void testSAML2Policy() {
+        try {
+            // Read assertion to use from file.
+            string path = data_path + "saml2/profile/SAML2Assertion.xml";
+            ifstream in(path.c_str());
+            DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
+            XercesJanitor<DOMDocument> janitor(doc);
+            auto_ptr<saml2::Assertion> assertion(
+                dynamic_cast<saml2::Assertion*>(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(),true))
+                );
+            janitor.release();
+
+            TSM_ASSERT_THROWS("Policy should have tripped on AudienceRestriction", m_policy->evaluate(*assertion.get()), SecurityPolicyException);
+
+            auto_ptr_XMLCh recipient("https://sp.example.org");
+            m_policy->setRecipient(recipient.get());
+            m_policy->evaluate(*assertion.get());
+        }
+        catch (exception& ex) {
+            TS_TRACE(ex.what());
+            throw;
+        }
+    }
+};
index f0061fb..89006d8 100644 (file)
                                                >\r
                                        </File>\r
                                </Filter>\r
+                               <Filter\r
+                                       Name="profile"\r
+                                       >\r
+                                       <File\r
+                                               RelativePath=".\saml1\profile\SAML1PolicyTest.cpp"\r
+                                               >\r
+                                       </File>\r
+                               </Filter>\r
                        </Filter>\r
                        <Filter\r
                                Name="signature"\r
                                                >\r
                                        </File>\r
                                </Filter>\r
+                               <Filter\r
+                                       Name="profile"\r
+                                       >\r
+                                       <File\r
+                                               RelativePath=".\saml2\profile\SAML2PolicyTest.cpp"\r
+                                               >\r
+                                       </File>\r
+                               </Filter>\r
                        </Filter>\r
                        <Filter\r
                                Name="security"\r
                                                </FileConfiguration>\r
                                        </File>\r
                                </Filter>\r
+                               <Filter\r
+                                       Name="profile"\r
+                                       >\r
+                                       <File\r
+                                               RelativePath=".\saml1\profile\SAML1PolicyTest.h"\r
+                                               >\r
+                                               <FileConfiguration\r
+                                                       Name="Debug|Win32"\r
+                                                       >\r
+                                                       <Tool\r
+                                                               Name="VCCustomBuildTool"\r
+                                                               CommandLine="perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                                               Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                                       />\r
+                                               </FileConfiguration>\r
+                                               <FileConfiguration\r
+                                                       Name="Debug|x64"\r
+                                                       >\r
+                                                       <Tool\r
+                                                               Name="VCCustomBuildTool"\r
+                                                               CommandLine="perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                                               Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                                       />\r
+                                               </FileConfiguration>\r
+                                               <FileConfiguration\r
+                                                       Name="Release|Win32"\r
+                                                       >\r
+                                                       <Tool\r
+                                                               Name="VCCustomBuildTool"\r
+                                                               CommandLine="perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                                               Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                                       />\r
+                                               </FileConfiguration>\r
+                                               <FileConfiguration\r
+                                                       Name="Release|x64"\r
+                                                       >\r
+                                                       <Tool\r
+                                                               Name="VCCustomBuildTool"\r
+                                                               CommandLine="perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                                               Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                                       />\r
+                                               </FileConfiguration>\r
+                                       </File>\r
+                               </Filter>\r
                        </Filter>\r
                        <Filter\r
                                Name="signature"\r
                                                </FileConfiguration>\r
                                        </File>\r
                                </Filter>\r
+                               <Filter\r
+                                       Name="profile"\r
+                                       >\r
+                                       <File\r
+                                               RelativePath=".\saml2\profile\SAML2PolicyTest.h"\r
+                                               >\r
+                                               <FileConfiguration\r
+                                                       Name="Debug|Win32"\r
+                                                       >\r
+                                                       <Tool\r
+                                                               Name="VCCustomBuildTool"\r
+                                                               CommandLine="perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
+                                                               Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                                       />\r
+                                               </FileConfiguration>\r
+                                               <FileConfiguration\r
+                                                       Name="Debug|x64"\r
+                                                       >\r
+                                                       <Tool\r
+                                                               Name="VCCustomBuildTool"\r
+                                                               CommandLine="perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
+                                                               Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                                       />\r
+                                               </FileConfiguration>\r
+                                               <FileConfiguration\r
+                                                       Name="Release|Win32"\r
+                                                       >\r
+                                                       <Tool\r
+                                                               Name="VCCustomBuildTool"\r
+                                                               CommandLine="perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
+                                                               Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                                       />\r
+                                               </FileConfiguration>\r
+                                               <FileConfiguration\r
+                                                       Name="Release|x64"\r
+                                                       >\r
+                                                       <Tool\r
+                                                               Name="VCCustomBuildTool"\r
+                                                               CommandLine="perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
+                                                               Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                                       />\r
+                                               </FileConfiguration>\r
+                                       </File>\r
+                               </Filter>\r
                        </Filter>\r
                        <Filter\r
                                Name="security"\r