SAML Signature subclasses and test.
authorScott Cantor <cantor.2@osu.edu>
Sun, 14 May 2006 03:35:30 +0000 (03:35 +0000)
committerScott Cantor <cantor.2@osu.edu>
Sun, 14 May 2006 03:35:30 +0000 (03:35 +0000)
15 files changed:
.cdtproject
saml/Makefile.am
saml/saml.vcproj
saml/saml1/core/impl/AssertionsSchemaValidators.cpp
saml/signature/SigningContext.cpp [new file with mode: 0644]
saml/signature/SigningContext.h [new file with mode: 0644]
saml/signature/VerifyingContext.cpp [new file with mode: 0644]
saml/signature/VerifyingContext.h [new file with mode: 0644]
samltest/Makefile.am
samltest/saml1/core/impl/AudienceRestrictionConditionTest.h [new file with mode: 0644]
samltest/saml1/core/impl/AudienceTest.h [new file with mode: 0644]
samltest/saml1/core/impl/AuthenticationStatementTest.h [new file with mode: 0644]
samltest/samltest.vcproj
samltest/signature/.gitignore [new file with mode: 0644]
samltest/signature/SAML1AssertionTest.h [new file with mode: 0644]

index 419cc0d..c59f390 100644 (file)
@@ -58,7 +58,7 @@
 <pathentry include="C:/xml-security-c-1.2.0/include" kind="inc" path="" system="true"/>\r
 <pathentry include="C:/log4cpp-0.3.5rc1/include" kind="inc" path="" system="true"/>\r
 <pathentry include="C:/cxxtest" kind="inc" path="" system="true"/>\r
-<pathentry excluding="util/|saml1/|saml1/core/|saml2/|saml2/core/|saml2/metadata/|saml1/core/impl/" kind="src" path="saml"/>\r
+<pathentry excluding="util/|saml1/|saml1/core/|saml2/|saml2/core/|saml2/metadata/|saml1/core/impl/|signature/" kind="src" path="saml"/>\r
 <pathentry kind="out" path=""/>\r
 <pathentry kind="con" path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>\r
 <pathentry kind="src" path="saml/util"/>\r
 <pathentry kind="src" path="saml/saml2/core"/>\r
 <pathentry kind="src" path="saml/saml2/metadata"/>\r
 <pathentry kind="src" path="saml/saml1/core/impl"/>\r
-<pathentry excluding="saml1/core/impl/" kind="src" path="samltest"/>\r
+<pathentry excluding="saml1/core/impl/|signature/" kind="src" path="samltest"/>\r
 <pathentry kind="src" path="samltest/saml1/core/impl"/>\r
+<pathentry kind="src" path="saml/signature"/>\r
+<pathentry kind="src" path="samltest/signature"/>\r
 </item>\r
 </data>\r
 </cdtproject>\r
index 139d5fb..460c788 100644 (file)
@@ -14,6 +14,10 @@ libsamlinclude_HEADERS = \
     version.h \
     SAMLConfig.h
 
+siginclude_HEADERS = \
+    signature/SigningContext.h \
+    signature/VerifyingContext.h
+
 utilinclude_HEADERS = \
     util/SAMLConstants.h
 
@@ -27,6 +31,8 @@ libsaml_la_SOURCES = \
     SAMLConfig.cpp \
     saml1/core/impl/AssertionsImpl.cpp \
     saml1/core/impl/AssertionsSchemaValidators.cpp \
+    signature/SigningContext.cpp \
+    signature/VerifyingContext.cpp \
     util/SAMLConstants.cpp
 
 # this is different from the project version
index d9fe07c..a6e42e7 100644 (file)
                                        </Filter>\r
                                </Filter>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="signature"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\signature\SigningContext.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\signature\VerifyingContext.cpp"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                                        </File>\r
                                </Filter>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="signature"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\signature\SigningContext.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\signature\VerifyingContext.h"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
index 2980972..815d725 100644 (file)
@@ -113,6 +113,8 @@ namespace opensaml {
                 ptr->getSubjectStatements().empty() &&
                 ptr->getStatements().empty())
                 throw ValidationException("Assertion must have at least one statement.");
+            if (ptr->getMinorVersion()==0 && ptr->getConditions() && !ptr->getConditions()->getDoNotCacheConditions().empty())
+                throw ValidationException("SAML 1.0 assertions cannot contain DoNotCacheCondition elements.");
         END_XMLOBJECTVALIDATOR;
 
         class SAML_DLLLOCAL checkWildcardNS {
diff --git a/saml/signature/SigningContext.cpp b/saml/signature/SigningContext.cpp
new file mode 100644 (file)
index 0000000..445147e
--- /dev/null
@@ -0,0 +1,61 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * SigningContext.cpp\r
+ * \r
+ * SAML-specific signature construction \r
+ */\r
\r
+#include "internal.h"\r
+#include "signature/SigningContext.h"\r
+\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+#include <xsec/dsig/DSIGReference.hpp>\r
+#include <xsec/dsig/DSIGTransformC14n.hpp>\r
+\r
+using namespace opensaml;\r
+using namespace std;\r
+\r
+class _addprefix : public binary_function<DSIGTransformC14n*,string,void> {\r
+public:\r
+    void operator()(DSIGTransformC14n* t, const string& s) const {\r
+        if (s.empty())\r
+            t->addInclusiveNamespace("#default");\r
+        else \r
+            t->addInclusiveNamespace(s.c_str());\r
+    }\r
+};\r
+\r
+void SigningContext::createSignature(DSIGSignature* sig) const\r
+{\r
+    DSIGReference* ref=NULL;\r
+    XMLCh* buf=new XMLCh[XMLString::stringLen(m_id) + 2];\r
+    buf[0]=chPound;\r
+    buf[1]=chNull;\r
+    XMLString::catString(buf,m_id);\r
+    try {\r
+        ref=sig->createReference(buf);\r
+        delete[] buf;\r
+    }\r
+    catch(...) {\r
+        delete[] buf;\r
+        throw;\r
+    }\r
+    ref->appendEnvelopedSignatureTransform();\r
+    DSIGTransformC14n* c14n=ref->appendCanonicalizationTransform(CANON_C14NE_NOC);\r
+    for_each(m_prefixes.begin(), m_prefixes.end(), bind1st(_addprefix(),c14n));\r
+}\r
diff --git a/saml/signature/SigningContext.h b/saml/signature/SigningContext.h
new file mode 100644 (file)
index 0000000..bdd1cbe
--- /dev/null
@@ -0,0 +1,137 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file SigningContext.h\r
+ * \r
+ * SAML-specific signature construction \r
+ */\r
+\r
+#ifndef __saml_signctx_h__\r
+#define __saml_signctx_h__\r
+\r
+#include <saml/base.h>\r
+#include <xmltooling/signature/SigningContext.h>\r
+\r
+namespace opensaml {\r
+\r
+    /**\r
+     * Singleton object that manages library startup/shutdown.configuration.\r
+     */\r
+    class SAML_API SigningContext : public virtual xmlsignature::SigningContext\r
+    {\r
+    public:\r
+        /**\r
+         * Constructor.\r
+         * \r
+         * @param id    identifier of object being signed\r
+         * @param key   signing key to use, will be freed by context\r
+         * @param certs a certificate chain to embed, or NULL\r
+         */\r
+        SigningContext(const XMLCh* id, XSECCryptoKey* key, const std::vector<XSECCryptoX509*>* certs=NULL)\r
+            : m_id(id), m_key(key), m_certs(certs), m_keyInfo(NULL) {\r
+        }\r
+        \r
+        /**\r
+         * Constructor.\r
+         * \r
+         * @param id        identifier of object being signed\r
+         * @param key       signing key to use, will be freed by context\r
+         * @param keyInfo   a complete KeyInfo object to attach, will be freed by context\r
+         */\r
+        SigningContext(const XMLCh* id, XSECCryptoKey* key, xmlsignature::KeyInfo* keyInfo)\r
+            : m_id(id), m_key(key), m_certs(NULL), m_keyInfo(keyInfo) {\r
+        }\r
+    \r
+        virtual ~SigningContext() {\r
+            delete m_key;\r
+            delete m_keyInfo;\r
+        }\r
+\r
+        /**\r
+         * Given a "blank" native signature, asks the context to define the\r
+         * appropriate signature transforms, references, etc.\r
+         * This method MAY attach ds:KeyInfo information, or a set of X.509\r
+         * certificates can be returned from the SigningContext::getX509Certificates()\r
+         * method instead.\r
+         * \r
+         * @param sig   native signature interface\r
+         */\r
+        virtual void createSignature(DSIGSignature* sig) const;\r
+        \r
+        /**\r
+         * Gets a reference to a collection of certificates to append to\r
+         * the ds:KeyInfo element in a ds:X509Data chain.\r
+         * The certificate corresponding to the signing key SHOULD be\r
+         * first, followed by any additional intermediates to append. \r
+         * \r
+         * @return  an immutable collection of certificates to embed\r
+         */\r
+        virtual const std::vector<XSECCryptoX509*>* getX509Certificates() const {\r
+            return m_certs;\r
+        }\r
+\r
+        /**\r
+         * Gets a KeyInfo structure to embed.\r
+         * Ownership of the object MUST be transferred to the caller.\r
+         * This method will only be called if no certificates are returned from\r
+         * the getX509Certificates() method.\r
+         * \r
+         * @return  pointer to a KeyInfo structure, will be freed by caller\r
+         */\r
+        virtual xmlsignature::KeyInfo* getKeyInfo() const {\r
+            xmlsignature::KeyInfo* ret=m_keyInfo;\r
+            m_keyInfo=NULL;\r
+            return ret;\r
+        }\r
+        \r
+        /**\r
+         * Gets the signing key to use.\r
+         * Must be compatible with the intended signature algorithm. Ownership of the key\r
+         * MUST be transferred to the caller.\r
+         * \r
+         * @return  pointer to a signing key, will be freed by caller\r
+         */\r
+        virtual XSECCryptoKey* getSigningKey() const {\r
+            XSECCryptoKey* ret=m_key;\r
+            m_key=NULL;\r
+            return ret;\r
+        }\r
+        \r
+        void addInclusivePrefix(const char* prefix) {\r
+            m_prefixes.push_back(prefix);\r
+        }\r
+\r
+    protected:\r
+        /** Identifier of object to sign. */\r
+        const XMLCh* m_id;\r
+\r
+        /** Signing key. */\r
+        mutable XSECCryptoKey* m_key;\r
+        \r
+        /** Optional pointer to certificate chain to embed. */\r
+        const std::vector<XSECCryptoX509*>* m_certs;\r
+\r
+        /** Optional pointer to KeyInfo to embed. */\r
+        mutable xmlsignature::KeyInfo* m_keyInfo;\r
+        \r
+        /** Inclusive prefixes. */\r
+        std::vector<std::string> m_prefixes;\r
+    };\r
+\r
+};\r
+\r
+#endif /* __saml_signctx_h__ */\r
diff --git a/saml/signature/VerifyingContext.cpp b/saml/signature/VerifyingContext.cpp
new file mode 100644 (file)
index 0000000..def1f98
--- /dev/null
@@ -0,0 +1,62 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * VerifyingContext.cpp\r
+ * \r
+ * SAML-specific signature verification \r
+ */\r
\r
+#include "internal.h"\r
+#include "signature/VerifyingContext.h"\r
+\r
+#include <xmltooling/signature/Signature.h>\r
+\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+#include <xsec/dsig/DSIGReference.hpp>\r
+#include <xsec/dsig/DSIGTransformC14n.hpp>\r
+#include <xsec/dsig/DSIGTransformList.hpp>\r
+\r
+using namespace opensaml;\r
+using namespace std;\r
+\r
+void VerifyingContext::verifySignature(DSIGSignature* sig) const\r
+{\r
+    bool valid=false;\r
+\r
+    DSIGReferenceList* refs=sig->getReferenceList();\r
+    if (refs && refs->getSize()==1) {\r
+        DSIGReference* ref=refs->item(0);\r
+        if (ref) {\r
+            const XMLCh* URI=ref->getURI();\r
+            if (URI==NULL || *URI==0 || (*URI==chPound && !XMLString::compareString(URI+1,m_id))) {\r
+                DSIGTransformList* tlist=ref->getTransforms();\r
+                for (unsigned int i=0; tlist && i<tlist->getSize(); i++) {\r
+                    if (tlist->item(i)->getTransformType()==TRANSFORM_ENVELOPED_SIGNATURE)\r
+                        valid=true;\r
+                    else if (tlist->item(i)->getTransformType()!=TRANSFORM_EXC_C14N &&\r
+                             tlist->item(i)->getTransformType()!=TRANSFORM_C14N) {\r
+                        valid=false;\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+    \r
+    if (!valid)\r
+        throw xmlsignature::SignatureException("Invalid signature profile for SAML object.");\r
+}\r
diff --git a/saml/signature/VerifyingContext.h b/saml/signature/VerifyingContext.h
new file mode 100644 (file)
index 0000000..77d730d
--- /dev/null
@@ -0,0 +1,63 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file VerifyingContext.h\r
+ * \r
+ * SAML-specific signature verification \r
+ */\r
+\r
+#ifndef __saml_verctx_h__\r
+#define __saml_verctx_h__\r
+\r
+#include <saml/base.h>\r
+#include <xmltooling/signature/VerifyingContext.h>\r
+\r
+namespace opensaml {\r
+\r
+    /**\r
+     * Singleton object that manages library startup/shutdown.configuration.\r
+     */\r
+    class SAML_API VerifyingContext : public virtual xmlsignature::VerifyingContext\r
+    {\r
+    public:\r
+        /**\r
+         * Constructor.\r
+         * \r
+         * @param id    identifier of object being verified\r
+         */\r
+        VerifyingContext(const XMLCh* id) : m_id(id) {}\r
+        \r
+        virtual ~VerifyingContext() {}\r
+\r
+        /**\r
+         * Given a native signature, asks the context to verify the signature\r
+         * in accordance with the relying party's requirements.\r
+         * \r
+         * @param sig   native signature object\r
+         * \r
+         * @throws SignatureException   raised if signature is invalid\r
+         */\r
+        virtual void verifySignature(DSIGSignature* sig) const;\r
+        \r
+    protected:\r
+        /** Identifier of object to verify. */\r
+        const XMLCh* m_id;\r
+    };\r
+\r
+};\r
+\r
+#endif /* __saml_verctx_h__ */\r
index d45c891..ba32aaa 100644 (file)
@@ -9,7 +9,16 @@ endif
 
 samltest_h = \
     samltest.h \
-    saml1/core/impl/ActionTest.h
+    saml1/core/impl/ActionTest.h \
+    saml1/core/impl/AdviceTest.h \
+    saml1/core/impl/AssertionIDReferenceTest.h \
+    saml1/core/impl/AssertionTest.h \
+    saml1/core/impl/AttributeDesignatorTest.h \
+    saml1/core/impl/AttributeStatementTest.h \
+    saml1/core/impl/AttributeTest.h \
+    saml1/core/impl/AudienceRestrictionConditionTest.h \
+    saml1/core/impl/AudienceTest.h \
+    saml1/core/impl/AuthenticationStatementTest.h
 
 noinst_HEADERS = \
     internal.h
diff --git a/samltest/saml1/core/impl/AudienceRestrictionConditionTest.h b/samltest/saml1/core/impl/AudienceRestrictionConditionTest.h
new file mode 100644 (file)
index 0000000..afacde3
--- /dev/null
@@ -0,0 +1,56 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "internal.h"\r
+#include <saml/saml1/core/Assertions.h>\r
+\r
+using namespace opensaml::saml1;\r
+\r
+class AudienceRestrictionConditionTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase {\r
+public:\r
+    void setUp() {\r
+        singleElementFile = data_path + "saml1/core/impl/singleAudienceRestrictionCondition.xml";\r
+        childElementsFile = data_path + "saml1/core/impl/AudienceRestrictionConditionWithChildren.xml";\r
+        SAMLObjectBaseTestCase::setUp();\r
+    }\r
+    \r
+    void tearDown() {\r
+        SAMLObjectBaseTestCase::tearDown();\r
+    }\r
+\r
+    void testSingleElementUnmarshall() {\r
+        auto_ptr<XMLObject> xo(unmarshallElement(singleElementFile));\r
+        AudienceRestrictionCondition& a = dynamic_cast<AudienceRestrictionCondition&>(*xo.get());\r
+        TSM_ASSERT_EQUALS("Count of child Audience elements !=0", 0, a.getAudiences().size());\r
+    }\r
+\r
+    void testChildElementsUnmarshall() {\r
+        auto_ptr<XMLObject> xo(unmarshallElement(childElementsFile));\r
+        AudienceRestrictionCondition& a = dynamic_cast<AudienceRestrictionCondition&>(*xo.get());\r
+        TSM_ASSERT_EQUALS("Count of child Audience elements", 2, a.getAudiences().size());\r
+    }\r
+\r
+    void testSingleElementMarshall() {\r
+        assertEquals(expectedDOM, AudienceRestrictionConditionBuilder::buildAudienceRestrictionCondition());\r
+    }\r
+\r
+    void testChildElementsMarshall(){\r
+        AudienceRestrictionCondition* a=AudienceRestrictionConditionBuilder::buildAudienceRestrictionCondition();\r
+        a->getAudiences().push_back(AudienceBuilder::buildAudience());\r
+        a->getAudiences().push_back(AudienceBuilder::buildAudience());\r
+        assertEquals(expectedChildElementsDOM, a);\r
+    }\r
+};\r
diff --git a/samltest/saml1/core/impl/AudienceTest.h b/samltest/saml1/core/impl/AudienceTest.h
new file mode 100644 (file)
index 0000000..aa281c2
--- /dev/null
@@ -0,0 +1,60 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "internal.h"\r
+#include <saml/saml1/core/Assertions.h>\r
+\r
+using namespace opensaml::saml1;\r
+\r
+class AudienceTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase {\r
+    XMLCh* expectedUri;\r
+\r
+public:\r
+    void setUp() {\r
+        expectedUri=XMLString::transcode("urn:oasis:names:tc:SAML:1.0:assertion");\r
+        singleElementFile = data_path + "saml1/core/impl/singleAudience.xml";\r
+        singleElementOptionalAttributesFile = data_path + "saml1/core/impl/singleAudienceAttributes.xml";\r
+        SAMLObjectBaseTestCase::setUp();\r
+    }\r
+    \r
+    void tearDown() {\r
+        XMLString::release(&expectedUri);\r
+        SAMLObjectBaseTestCase::tearDown();\r
+    }\r
+\r
+    void testSingleElementUnmarshall() {\r
+        auto_ptr<XMLObject> xo(unmarshallElement(singleElementFile));\r
+        Audience& a = dynamic_cast<Audience&>(*xo.get());\r
+        TSM_ASSERT("Uri is non-null", a.getUri()==NULL);\r
+    }\r
+\r
+    void testSingleElementOptionalAttributesUnmarshall() {\r
+        auto_ptr<XMLObject> xo(unmarshallElement(singleElementOptionalAttributesFile));\r
+        Audience& a = dynamic_cast<Audience&>(*xo.get());\r
+        TSM_ASSERT_SAME_DATA("Uri", expectedUri, a.getUri(), XMLString::stringLen(expectedUri));\r
+    }\r
+\r
+    void testSingleElementMarshall() {\r
+        assertEquals(expectedDOM, AudienceBuilder::buildAudience());\r
+    }\r
+\r
+    void testSingleElementOptionalAttributesMarshall() {\r
+        Audience* a=AudienceBuilder::buildAudience();\r
+        a->setUri(expectedUri);\r
+        assertEquals(expectedOptionalAttributesDOM, a);\r
+    }\r
+\r
+};\r
diff --git a/samltest/saml1/core/impl/AuthenticationStatementTest.h b/samltest/saml1/core/impl/AuthenticationStatementTest.h
new file mode 100644 (file)
index 0000000..26e583d
--- /dev/null
@@ -0,0 +1,93 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "internal.h"\r
+#include <saml/saml1/core/Assertions.h>\r
+\r
+using namespace opensaml::saml1;\r
+\r
+class AuthenticationStatementTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase {\r
+    XMLCh* expectedAuthenticationMethod;\r
+    XMLCh* expectedAuthenticationInstant;\r
+\r
+public:\r
+    void setUp() {\r
+        expectedAuthenticationInstant=XMLString::transcode("1970-01-02T01:01:02.123Z");\r
+        expectedAuthenticationMethod=XMLString::transcode("trustme");\r
+        singleElementFile = data_path + "saml1/core/impl/singleAuthenticationStatement.xml";\r
+        singleElementOptionalAttributesFile = data_path + "saml1/core/impl/singleAuthenticationStatementAttributes.xml";\r
+        childElementsFile  = data_path + "saml1/core/impl/AuthenticationStatementWithChildren.xml";    \r
+        SAMLObjectBaseTestCase::setUp();\r
+    }\r
+    \r
+    void tearDown() {\r
+        XMLString::release(&expectedAuthenticationInstant);\r
+        XMLString::release(&expectedAuthenticationMethod);\r
+        SAMLObjectBaseTestCase::tearDown();\r
+    }\r
+\r
+    void testSingleElementUnmarshall() {\r
+        auto_ptr<XMLObject> xo(unmarshallElement(singleElementFile));\r
+        AuthenticationStatement& as = dynamic_cast<AuthenticationStatement&>(*xo.get());\r
+        TSM_ASSERT("AuthenticationMethod attribute present", as.getAuthenticationMethod()==NULL);\r
+        TSM_ASSERT("AuthenticationInstant attribute present", as.getAuthenticationInstant()==NULL);\r
+\r
+        TSM_ASSERT("Subject element", as.getSubject()==NULL);\r
+        TSM_ASSERT("SubjectLocality element", as.getSubjectLocality()==NULL);\r
+        TSM_ASSERT_EQUALS("AuthorityBinding element count", 0, as.getAuthorityBindings().size());\r
+    }\r
+\r
+    void testSingleElementOptionalAttributesUnmarshall() {\r
+        auto_ptr<XMLObject> xo(unmarshallElement(singleElementOptionalAttributesFile));\r
+        AuthenticationStatement& as = dynamic_cast<AuthenticationStatement&>(*xo.get());\r
+\r
+        TSM_ASSERT_SAME_DATA("AuthenticationMethod attribute", expectedAuthenticationMethod, as.getAuthenticationMethod(), XMLString::stringLen(expectedAuthenticationMethod));\r
+        TSM_ASSERT_SAME_DATA("AuthenticationInstant attribute", expectedAuthenticationInstant, as.getAuthenticationInstant()->getRawData(), XMLString::stringLen(expectedAuthenticationInstant));\r
+    }\r
+\r
+    void testChildElementsUnmarshall() {\r
+        auto_ptr<XMLObject> xo(unmarshallElement(childElementsFile));\r
+        AuthenticationStatement& as = dynamic_cast<AuthenticationStatement&>(*xo.get());\r
+\r
+        TSM_ASSERT("Subject element", as.getSubject()!=NULL);\r
+        TSM_ASSERT("SubjectLocality element", as.getSubjectLocality()!=NULL);\r
+\r
+        TSM_ASSERT_EQUALS("AuthorityBinding element count", 2, as.getAuthorityBindings().size());\r
+        as.getAuthorityBindings().erase(as.getAuthorityBindings().begin());\r
+        TSM_ASSERT_EQUALS("AuthorityBinding element count", 1, as.getAuthorityBindings().size());\r
+    }\r
+\r
+    void testSingleElementMarshall() {\r
+        assertEquals(expectedDOM, AuthenticationStatementBuilder::buildAuthenticationStatement());\r
+    }\r
+\r
+    void testSingleElementOptionalAttributesMarshall() {\r
+        AuthenticationStatement* as=AuthenticationStatementBuilder::buildAuthenticationStatement();\r
+        as->setAuthenticationInstant(expectedAuthenticationInstant);\r
+        as->setAuthenticationMethod(expectedAuthenticationMethod);\r
+        assertEquals(expectedOptionalAttributesDOM, as);\r
+    }\r
+\r
+    void testChildElementsMarshall() {\r
+        AuthenticationStatement* as=AuthenticationStatementBuilder::buildAuthenticationStatement();\r
+        as->setSubject(SubjectBuilder::buildSubject());\r
+        as->setSubjectLocality(SubjectLocalityBuilder::buildSubjectLocality());\r
+        as->getAuthorityBindings().push_back(AuthorityBindingBuilder::buildAuthorityBinding());\r
+        as->getAuthorityBindings().push_back(AuthorityBindingBuilder::buildAuthorityBinding());\r
+        assertEquals(expectedChildElementsDOM, as);\r
+    }\r
+\r
+};\r
index c6f5e45..a9df5f2 100644 (file)
@@ -61,7 +61,7 @@
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="..\..\cpp-xmltooling\Debug\xmltooling_1D.lib xerces-c_2D.lib xsec_1D.lib"\r
+                               AdditionalDependencies="..\..\cpp-xmltooling\Debug\xmltooling_1D.lib xerces-c_2D.lib xsec_1D.lib libeay32_0_9_8D.lib"\r
                                LinkIncremental="2"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="..\..\cpp-xmltooling\Release\xmltooling_1.lib xerces-c_2.lib xsec_1.lib"\r
+                               AdditionalDependencies="..\..\cpp-xmltooling\Release\xmltooling_1.lib xerces-c_2.lib xsec_1.lib libeay32_0_9_8.lib"\r
                                LinkIncremental="1"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
                                                        RelativePath=".\saml1\core\impl\AttributeTest.cpp"\r
                                                        >\r
                                                </File>\r
+                                               <File\r
+                                                       RelativePath=".\saml1\core\impl\AudienceRestrictionConditionTest.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
+                                                       RelativePath=".\saml1\core\impl\AudienceTest.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
+                                                       RelativePath=".\saml1\core\impl\AuthenticationStatementTest.cpp"\r
+                                                       >\r
+                                               </File>\r
                                        </Filter>\r
                                </Filter>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="signature"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\signature\SAML1AssertionTest.cpp"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Unit Tests"\r
                                                                />\r
                                                        </FileConfiguration>\r
                                                </File>\r
+                                               <File\r
+                                                       RelativePath=".\saml1\core\impl\AudienceRestrictionConditionTest.h"\r
+                                                       >\r
+                                                       <FileConfiguration\r
+                                                               Name="Debug|Win32"\r
+                                                               >\r
+                                                               <Tool\r
+                                                                       Name="VCCustomBuildTool"\r
+                                                                       CommandLine="\perl\bin\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\bin\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
+                                               <File\r
+                                                       RelativePath=".\saml1\core\impl\AudienceTest.h"\r
+                                                       >\r
+                                                       <FileConfiguration\r
+                                                               Name="Debug|Win32"\r
+                                                               >\r
+                                                               <Tool\r
+                                                                       Name="VCCustomBuildTool"\r
+                                                                       CommandLine="\perl\bin\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\bin\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
+                                               <File\r
+                                                       RelativePath=".\saml1\core\impl\AuthenticationStatementTest.h"\r
+                                                       >\r
+                                                       <FileConfiguration\r
+                                                               Name="Debug|Win32"\r
+                                                               >\r
+                                                               <Tool\r
+                                                                       Name="VCCustomBuildTool"\r
+                                                                       CommandLine="\perl\bin\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\bin\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
+                       <Filter\r
+                               Name="signature"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\signature\SAML1AssertionTest.h"\r
+                                       >\r
+                                       <FileConfiguration\r
+                                               Name="Debug|Win32"\r
+                                               >\r
+                                               <Tool\r
+                                                       Name="VCCustomBuildTool"\r
+                                                       CommandLine="\perl\bin\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\bin\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="Resource Files"\r
diff --git a/samltest/signature/.gitignore b/samltest/signature/.gitignore
new file mode 100644 (file)
index 0000000..e16b497
--- /dev/null
@@ -0,0 +1 @@
+/*.cpp
diff --git a/samltest/signature/SAML1AssertionTest.h b/samltest/signature/SAML1AssertionTest.h
new file mode 100644 (file)
index 0000000..910d20a
--- /dev/null
@@ -0,0 +1,141 @@
+/*\r
+ *  Copyright 2001-2005 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "internal.h"\r
+#include <saml/saml1/core/Assertions.h>\r
+#include <saml/signature/SigningContext.h>\r
+#include <saml/signature/VerifyingContext.h>\r
+\r
+using namespace opensaml::saml1;\r
+\r
+#include <fstream>\r
+#include <openssl/pem.h>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+#include <xsec/enc/XSECKeyInfoResolverDefault.hpp>\r
+#include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>\r
+#include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>\r
+#include <xmltooling/signature/Signature.h>\r
+\r
+class TestContext : public VerifyingContext\r
+{\r
+    SigningContext* m_signing;\r
+    vector<XSECCryptoX509*> m_certs;\r
+public:\r
+    TestContext(const XMLCh* uri) : VerifyingContext(uri), m_signing(NULL) {\r
+        OpenSSLCryptoKeyRSA* key=NULL;\r
+        string keypath=data_path + "key.pem";\r
+        BIO* in=BIO_new(BIO_s_file_internal());\r
+        if (in && BIO_read_filename(in,keypath.c_str())>0) {\r
+            EVP_PKEY* pkey=PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);\r
+            if (pkey) {\r
+                key=new OpenSSLCryptoKeyRSA(pkey);\r
+                EVP_PKEY_free(pkey);\r
+            }\r
+        }\r
+        if (in) BIO_free(in);\r
+        TS_ASSERT(key!=NULL);\r
+\r
+        string certpath=data_path + "cert.pem";\r
+        in=BIO_new(BIO_s_file_internal());\r
+        if (in && BIO_read_filename(in,certpath.c_str())>0) {\r
+            X509* x=NULL;\r
+            while (x=PEM_read_bio_X509(in,NULL,NULL,NULL)) {\r
+                m_certs.push_back(new OpenSSLCryptoX509(x));\r
+                X509_free(x);\r
+            }\r
+        }\r
+        if (in) BIO_free(in);\r
+        TS_ASSERT(m_certs.size()>0);\r
+        m_signing=new SigningContext(uri, key, &m_certs);\r
+    }\r
+    \r
+    virtual ~TestContext() {\r
+        delete m_signing;\r
+        for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup<XSECCryptoX509>());\r
+    }\r
+    \r
+    SigningContext* getSigningContext() { return m_signing; }\r
+    \r
+    void verifySignature(DSIGSignature* sig) const {\r
+        VerifyingContext::verifySignature(sig);\r
+        sig->setSigningKey(NULL);\r
+        XSECKeyInfoResolverDefault resolver;\r
+        sig->setKeyInfoResolver(&resolver);\r
+        sig->verify();\r
+    }\r
+};\r
+\r
+class SAML1AssertionTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase {\r
+public:\r
+    void setUp() {\r
+        childElementsFile  = data_path + "signature/SAML1Assertion.xml";\r
+        SAMLObjectBaseTestCase::setUp();\r
+    }\r
+\r
+    void tearDown() {\r
+        SAMLObjectBaseTestCase::tearDown();\r
+    }\r
+\r
+    void testSignature() {\r
+        auto_ptr_XMLCh issuer("issuer");\r
+        auto_ptr_XMLCh issueInstant("1970-01-02T01:01:02.100Z");\r
+        auto_ptr_XMLCh id("ident");\r
+        auto_ptr_XMLCh method("method");\r
+        auto_ptr_XMLCh nameid("John Doe");\r
+        \r
+        NameIdentifier* n=NameIdentifierBuilder::buildNameIdentifier();\r
+        n->setName(nameid.get());        \r
+        Subject* subject=SubjectBuilder::buildSubject();\r
+        subject->setNameIdentifier(n);\r
+\r
+        AuthenticationStatement* statement=AuthenticationStatementBuilder::buildAuthenticationStatement();\r
+        statement->setAuthenticationInstant(issueInstant.get());\r
+        statement->setAuthenticationMethod(method.get());\r
+        statement->setSubject(subject);\r
+        \r
+        auto_ptr<Assertion> assertion(AssertionBuilder::buildAssertion());\r
+        assertion->setAssertionID(id.get());\r
+        assertion->setIssueInstant(issueInstant.get());\r
+        assertion->setIssuer(issuer.get());\r
+        assertion->getAuthenticationStatements().push_back(statement);\r
+\r
+        // Append a Signature.\r
+        xmlsignature::Signature* sig=xmlsignature::SignatureBuilder::newSignature();\r
+        assertion->setSignature(sig);\r
+        \r
+        // Signing context for the assertion.\r
+        TestContext tc(id.get());\r
+        MarshallingContext mctx(sig,tc.getSigningContext());\r
+        DOMElement* rootElement = assertion->marshall((DOMDocument*)NULL,&mctx);\r
+        \r
+        string buf;\r
+        XMLHelper::serialize(rootElement, buf);\r
+        istringstream in(buf);\r
+        DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);\r
+        const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());\r
+        \r
+        assertEquals(expectedChildElementsDOM, b->buildFromDocument(doc));\r
+        \r
+        try {\r
+            assertion->getSignature()->verify(tc);\r
+        }\r
+        catch (xmlsignature::SignatureException& e) {\r
+            TS_TRACE(e.what());\r
+            throw;\r
+        }\r
+    }\r
+\r
+};\r