Additional signature tests, including nesting.
authorcantor <cantor@fb386ef7-a10c-0410-8ebf-fd3f8e989ab0>
Sun, 21 May 2006 19:54:38 +0000 (19:54 +0000)
committercantor <cantor@fb386ef7-a10c-0410-8ebf-fd3f8e989ab0>
Sun, 21 May 2006 19:54:38 +0000 (19:54 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-opensaml2/trunk@24 fb386ef7-a10c-0410-8ebf-fd3f8e989ab0

saml/saml1/core/impl/ProtocolsImpl.cpp
samltest/Makefile.am
samltest/data/signature/SAML1Request.xml [new file with mode: 0644]
samltest/data/signature/SAML1Response.xml [new file with mode: 0644]
samltest/samltest.vcproj
samltest/signature/SAML1RequestTest.h [new file with mode: 0644]
samltest/signature/SAML1ResponseTest.h [new file with mode: 0644]

index 24317e4..1c6ee51 100644 (file)
@@ -314,7 +314,9 @@ namespace opensaml {
                 m_pos_Signature=m_children.begin();
             }
         protected:
-            AbstractRequestImpl() {}
+            AbstractRequestImpl() {
+                init();
+            }
         public:
             virtual ~AbstractRequestImpl() {
                 XMLString::release(&m_RequestID);
@@ -636,7 +638,9 @@ namespace opensaml {
                 m_pos_Signature=m_children.begin();
             }
         protected:
-            AbstractResponseImpl() {}
+            AbstractResponseImpl() {
+                init();
+            }
         public:
             virtual ~AbstractResponseImpl() {
                 XMLString::release(&m_ResponseID);
index ba32aaa..394483f 100644 (file)
@@ -9,6 +9,9 @@ endif
 
 samltest_h = \
     samltest.h \
+    saml/signature/SAML1AssertionTest.h \
+    saml/signature/SAML1RequestTest.h \
+    saml/signature/SAML1ResponseTest.h \
     saml1/core/impl/ActionTest.h \
     saml1/core/impl/AdviceTest.h \
     saml1/core/impl/AssertionIDReferenceTest.h \
diff --git a/samltest/data/signature/SAML1Request.xml b/samltest/data/signature/SAML1Request.xml
new file mode 100644 (file)
index 0000000..e40d5e2
--- /dev/null
@@ -0,0 +1,31 @@
+<samlp:Request xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="1970-01-02T01:01:02.100Z"
+MajorVersion="1" MinorVersion="1" RequestID="ident"><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+<ds:SignedInfo>
+<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+<ds:Reference URI="#ident">
+<ds:Transforms>
+<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+</ds:Transforms>
+<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+<ds:DigestValue>pqhIt8nUldh3KVL6IEewRxKXYhM=</ds:DigestValue>
+</ds:Reference>
+</ds:SignedInfo>
+<ds:SignatureValue>UE5p832pLFYvMloRofN3y0rrFY7B8zOcF7+CHYyxFn6pqgPeEYGqkbUWlV15/tJ5
+wXJ3LiLQroYQI3XHPvKRSV4OtF9ZFm4QDK7RNd6gnUmHed6Zje//e6z2ekA0UzTl
+IeWCuD84mWemMJzRAhSFKcnqJDBHA61Krvg1kf/2c2E=</ds:SignatureValue>
+<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV
+BAYTAlVTMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDnNwLmV4YW1wbGUu
+b3JnMB4XDTA1MDYyMDE1NDgzNFoXDTMyMTEwNTE1NDgzNFowOjELMAkGA1UEBhMC
+VVMxEjAQBgNVBAoTCUludGVybmV0MjEXMBUGA1UEAxMOc3AuZXhhbXBsZS5vcmcw
+gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANlZ1L1mKzYbUVKiMQLhZlfGDyYa
+/jjCiaXP0WhLNgvJpOTeajvsrApYNnFX5MLNzuC3NeQIjXUNLN2Yo2MCSthBIOL5
+qE5dka4z9W9zytoflW1LmJ8vXpx8Ay/meG4z//J5iCpYVEquA0xl28HUIlownZUF
+7w7bx0cF/02qrR23AgMBAAGjgZwwgZkwHQYDVR0OBBYEFJZiO1qsyAyc3HwMlL9p
+JpN6fbGwMGoGA1UdIwRjMGGAFJZiO1qsyAyc3HwMlL9pJpN6fbGwoT6kPDA6MQsw
+CQYDVQQGEwJVUzESMBAGA1UEChMJSW50ZXJuZXQyMRcwFQYDVQQDEw5zcC5leGFt
+cGxlLm9yZ4IJAKk8t1hYcMkhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD
+gYEAMFq/UeSQyngE0GpZueyD2UW0M358uhseYOgGEIfm+qXIFQF6MYwNoX7WFzhC
+LJZ2E6mEvZZFHCHUtl7mGDvsRwgZ85YCtRbvleEpqfgNQToto9pLYe+X6vvH9Z6p
+gmYsTmak+kxO93JprrOd9xp8aZPMEprL7VCdrhbZEfyYER0=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><samlp:AuthenticationQuery AuthenticationMethod="method"><saml:Subject xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"><saml:NameIdentifier>John Doe</saml:NameIdentifier></saml:Subject></samlp:AuthenticationQuery></samlp:Request>
diff --git a/samltest/data/signature/SAML1Response.xml b/samltest/data/signature/SAML1Response.xml
new file mode 100644 (file)
index 0000000..281957b
--- /dev/null
@@ -0,0 +1,63 @@
+<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="1970-01-02T01:01:02.100Z" MajorVersion="1" MinorVersion="1" ResponseID="rident"><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+<ds:SignedInfo>
+<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+<ds:Reference URI="#rident">
+<ds:Transforms>
+<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+</ds:Transforms>
+<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+<ds:DigestValue>WjLtIcoArwwdHVOks5QnbnFuE9g=</ds:DigestValue>
+</ds:Reference>
+</ds:SignedInfo>
+<ds:SignatureValue>cwC985/W+J8HrkDgMK1fYPfRP7e6aAAKJM/8rTWbOnI6feF8jrsQhSQ9qBon5o46
+4eHMDYAcH4xd9rGPeYib4jjH2hAPAF0rqLX1FWNTZgS+lJQFhhj5Sys0Ja6C0wsx
+0CoEWraR/IiDpRwnz9gGj2jGnfokfBdsLiomuxC2ZNY=</ds:SignatureValue>
+<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV
+BAYTAlVTMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDnNwLmV4YW1wbGUu
+b3JnMB4XDTA1MDYyMDE1NDgzNFoXDTMyMTEwNTE1NDgzNFowOjELMAkGA1UEBhMC
+VVMxEjAQBgNVBAoTCUludGVybmV0MjEXMBUGA1UEAxMOc3AuZXhhbXBsZS5vcmcw
+gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANlZ1L1mKzYbUVKiMQLhZlfGDyYa
+/jjCiaXP0WhLNgvJpOTeajvsrApYNnFX5MLNzuC3NeQIjXUNLN2Yo2MCSthBIOL5
+qE5dka4z9W9zytoflW1LmJ8vXpx8Ay/meG4z//J5iCpYVEquA0xl28HUIlownZUF
+7w7bx0cF/02qrR23AgMBAAGjgZwwgZkwHQYDVR0OBBYEFJZiO1qsyAyc3HwMlL9p
+JpN6fbGwMGoGA1UdIwRjMGGAFJZiO1qsyAyc3HwMlL9pJpN6fbGwoT6kPDA6MQsw
+CQYDVQQGEwJVUzESMBAGA1UEChMJSW50ZXJuZXQyMRcwFQYDVQQDEw5zcC5leGFt
+cGxlLm9yZ4IJAKk8t1hYcMkhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD
+gYEAMFq/UeSQyngE0GpZueyD2UW0M358uhseYOgGEIfm+qXIFQF6MYwNoX7WFzhC
+LJZ2E6mEvZZFHCHUtl7mGDvsRwgZ85YCtRbvleEpqfgNQToto9pLYe+X6vvH9Z6p
+gmYsTmak+kxO93JprrOd9xp8aZPMEprL7VCdrhbZEfyYER0=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><samlp:Status><samlp:StatusCode
+Value="samlp:Success"/></samlp:Status><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="aident"
+IssueInstant="1970-01-02T01:01:02.100Z" Issuer="issuer" MajorVersion="1" MinorVersion="1"><saml:AuthenticationStatement
+AuthenticationInstant="1970-01-02T01:01:02.100Z"
+AuthenticationMethod="method"><saml:Subject><saml:NameIdentifier>John Doe</saml:NameIdentifier></saml:Subject></saml:AuthenticationStatement><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+<ds:SignedInfo>
+<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+<ds:Reference URI="#aident">
+<ds:Transforms>
+<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+</ds:Transforms>
+<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+<ds:DigestValue>/owFROXYYru5+/j0TpHEz+hjXqY=</ds:DigestValue>
+</ds:Reference>
+</ds:SignedInfo>
+<ds:SignatureValue>d4SsRgDSjboTRA2YUD68TPp+17AqRmxbY/LrWJhueIC/JY+Ct7+Fd6bugUXliIeD
+NVRDACsEB7PqYWZ99+Ecf8XAmQYCw5elj8mWxPp0o+UVHtBZOR2bC+/YjNitSM+x
+G/F3JgZqfunUcg7mcj6WEAUt4pjKhjaTY8Z7QJltdKc=</ds:SignatureValue>
+<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV
+BAYTAlVTMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDnNwLmV4YW1wbGUu
+b3JnMB4XDTA1MDYyMDE1NDgzNFoXDTMyMTEwNTE1NDgzNFowOjELMAkGA1UEBhMC
+VVMxEjAQBgNVBAoTCUludGVybmV0MjEXMBUGA1UEAxMOc3AuZXhhbXBsZS5vcmcw
+gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANlZ1L1mKzYbUVKiMQLhZlfGDyYa
+/jjCiaXP0WhLNgvJpOTeajvsrApYNnFX5MLNzuC3NeQIjXUNLN2Yo2MCSthBIOL5
+qE5dka4z9W9zytoflW1LmJ8vXpx8Ay/meG4z//J5iCpYVEquA0xl28HUIlownZUF
+7w7bx0cF/02qrR23AgMBAAGjgZwwgZkwHQYDVR0OBBYEFJZiO1qsyAyc3HwMlL9p
+JpN6fbGwMGoGA1UdIwRjMGGAFJZiO1qsyAyc3HwMlL9pJpN6fbGwoT6kPDA6MQsw
+CQYDVQQGEwJVUzESMBAGA1UEChMJSW50ZXJuZXQyMRcwFQYDVQQDEw5zcC5leGFt
+cGxlLm9yZ4IJAKk8t1hYcMkhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD
+gYEAMFq/UeSQyngE0GpZueyD2UW0M358uhseYOgGEIfm+qXIFQF6MYwNoX7WFzhC
+LJZ2E6mEvZZFHCHUtl7mGDvsRwgZ85YCtRbvleEpqfgNQToto9pLYe+X6vvH9Z6p
+gmYsTmak+kxO93JprrOd9xp8aZPMEprL7VCdrhbZEfyYER0=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></saml:Assertion></samlp:Response>
index a9df5f2..2887473 100644 (file)
                                        RelativePath=".\signature\SAML1AssertionTest.cpp"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\signature\SAML1RequestTest.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\signature\SAML1ResponseTest.cpp"\r
+                                       >\r
+                               </File>\r
                        </Filter>\r
                </Filter>\r
                <Filter\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=".\signature\SAML1RequestTest.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
+                               <File\r
+                                       RelativePath=".\signature\SAML1ResponseTest.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
diff --git a/samltest/signature/SAML1RequestTest.h b/samltest/signature/SAML1RequestTest.h
new file mode 100644 (file)
index 0000000..61ca7f9
--- /dev/null
@@ -0,0 +1,175 @@
+/*\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/Protocols.h>\r
+#include <saml/signature/SignatureProfileValidator.h>\r
+\r
+#include <xmltooling/signature/Signature.h>\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 <xsec/enc/XSECCryptoException.hpp>\r
+#include <xsec/framework/XSECException.hpp>\r
+\r
+using namespace opensaml::saml1;\r
+using namespace xmlsignature;\r
+\r
+class TestValidator : public Validator\r
+{\r
+public:\r
+    TestValidator() {}\r
+    virtual ~TestValidator() {}\r
+\r
+    Validator* clone() const {\r
+        return new TestValidator();\r
+    }\r
+\r
+    void validate(const XMLObject* xmlObject) const {\r
+        DSIGSignature* sig=dynamic_cast<const Signature*>(xmlObject)->getXMLSignature();\r
+        if (!sig)\r
+            throw SignatureException("Only a marshalled Signature object can be verified.");\r
+        XSECKeyInfoResolverDefault resolver;\r
+        sig->setKeyInfoResolver(&resolver); // It will clone the resolver for us.\r
+        try {\r
+            if (!sig->verify())\r
+                throw SignatureException("Signature did not verify.");\r
+        }\r
+        catch(XSECException& e) {\r
+            auto_ptr_char temp(e.getMsg());\r
+            throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + temp.get());\r
+        }\r
+        catch(XSECCryptoException& e) {\r
+            throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + e.getMsg());\r
+        }\r
+    }\r
+};\r
+\r
+class _addcert : public std::binary_function<X509Data*,XSECCryptoX509*,void> {\r
+public:\r
+    void operator()(X509Data* bag, XSECCryptoX509* cert) const {\r
+        safeBuffer& buf=cert->getDEREncodingSB();\r
+        X509Certificate* x=X509CertificateBuilder::buildX509Certificate();\r
+        x->setValue(buf.sbStrToXMLCh());\r
+        bag->getX509Certificates().push_back(x);\r
+    }\r
+};\r
+\r
+class SAML1RequestTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase {\r
+    XSECCryptoKey* m_key;\r
+    vector<XSECCryptoX509*> m_certs;\r
+public:\r
+    void setUp() {\r
+        childElementsFile  = data_path + "signature/SAML1Request.xml";\r
+        SAMLObjectBaseTestCase::setUp();\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
+                m_key=new OpenSSLCryptoKeyRSA(pkey);\r
+                EVP_PKEY_free(pkey);\r
+            }\r
+        }\r
+        if (in) BIO_free(in);\r
+        TS_ASSERT(m_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
+    }\r
+\r
+    void tearDown() {\r
+        SAMLObjectBaseTestCase::tearDown();\r
+        delete m_key;\r
+        for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup<XSECCryptoX509>());\r
+    }\r
+\r
+    void testSignature() {\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
+        AuthenticationQuery* query=AuthenticationQueryBuilder::buildAuthenticationQuery();\r
+        query->setAuthenticationMethod(method.get());\r
+        query->setSubject(subject);\r
+        \r
+        auto_ptr<Request> request(RequestBuilder::buildRequest());\r
+        request->setRequestID(id.get());\r
+        request->setIssueInstant(issueInstant.get());\r
+        request->setAuthenticationQuery(query);\r
+\r
+        // Append a Signature.\r
+        Signature* sig=SignatureBuilder::buildSignature();\r
+        request->setSignature(sig);\r
+        sig->setSigningKey(m_key->clone());\r
+\r
+        // Build KeyInfo.\r
+        KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo();\r
+        X509Data* x509Data=X509DataBuilder::buildX509Data();\r
+        keyInfo->getX509Datas().push_back(x509Data);\r
+        for_each(m_certs.begin(),m_certs.end(),bind1st(_addcert(),x509Data));\r
+        sig->setKeyInfo(keyInfo);\r
+\r
+        // Sign while marshalling.\r
+        vector<Signature*> sigs(1,sig);\r
+        DOMElement* rootElement = NULL;\r
+        try {\r
+            rootElement=request->marshall((DOMDocument*)NULL,&sigs);\r
+        }\r
+        catch (XMLToolingException& e) {\r
+            TS_TRACE(e.what());\r
+            throw;\r
+        }\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
+            request->getSignature()->registerValidator(new SignatureProfileValidator());\r
+            request->getSignature()->registerValidator(new TestValidator());\r
+            request->getSignature()->validate(true);\r
+        }\r
+        catch (XMLToolingException& e) {\r
+            TS_TRACE(e.what());\r
+            throw;\r
+        }\r
+    }\r
+\r
+};\r
diff --git a/samltest/signature/SAML1ResponseTest.h b/samltest/signature/SAML1ResponseTest.h
new file mode 100644 (file)
index 0000000..e63856f
--- /dev/null
@@ -0,0 +1,208 @@
+/*\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/Protocols.h>\r
+#include <saml/signature/SignatureProfileValidator.h>\r
+\r
+#include <xmltooling/signature/Signature.h>\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 <xsec/enc/XSECCryptoException.hpp>\r
+#include <xsec/framework/XSECException.hpp>\r
+\r
+using namespace opensaml::saml1;\r
+using namespace xmlsignature;\r
+\r
+class TestValidator : public Validator\r
+{\r
+public:\r
+    TestValidator() {}\r
+    virtual ~TestValidator() {}\r
+\r
+    Validator* clone() const {\r
+        return new TestValidator();\r
+    }\r
+\r
+    void validate(const XMLObject* xmlObject) const {\r
+        DSIGSignature* sig=dynamic_cast<const Signature*>(xmlObject)->getXMLSignature();\r
+        if (!sig)\r
+            throw SignatureException("Only a marshalled Signature object can be verified.");\r
+        XSECKeyInfoResolverDefault resolver;\r
+        sig->setKeyInfoResolver(&resolver); // It will clone the resolver for us.\r
+        try {\r
+            if (!sig->verify())\r
+                throw SignatureException("Signature did not verify.");\r
+        }\r
+        catch(XSECException& e) {\r
+            auto_ptr_char temp(e.getMsg());\r
+            throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + temp.get());\r
+        }\r
+        catch(XSECCryptoException& e) {\r
+            throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + e.getMsg());\r
+        }\r
+    }\r
+};\r
+\r
+class _addcert : public std::binary_function<X509Data*,XSECCryptoX509*,void> {\r
+public:\r
+    void operator()(X509Data* bag, XSECCryptoX509* cert) const {\r
+        safeBuffer& buf=cert->getDEREncodingSB();\r
+        X509Certificate* x=X509CertificateBuilder::buildX509Certificate();\r
+        x->setValue(buf.sbStrToXMLCh());\r
+        bag->getX509Certificates().push_back(x);\r
+    }\r
+};\r
+\r
+class SAML1ResponseTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase {\r
+    XSECCryptoKey* m_key;\r
+    vector<XSECCryptoX509*> m_certs;\r
+public:\r
+    void setUp() {\r
+        childElementsFile  = data_path + "signature/SAML1Response.xml";\r
+        SAMLObjectBaseTestCase::setUp();\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
+                m_key=new OpenSSLCryptoKeyRSA(pkey);\r
+                EVP_PKEY_free(pkey);\r
+            }\r
+        }\r
+        if (in) BIO_free(in);\r
+        TS_ASSERT(m_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
+    }\r
+\r
+    void tearDown() {\r
+        SAMLObjectBaseTestCase::tearDown();\r
+        delete m_key;\r
+        for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup<XSECCryptoX509>());\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 aid("aident");\r
+        auto_ptr_XMLCh rid("rident");\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
+        Assertion* assertion=AssertionBuilder::buildAssertion();\r
+        assertion->setAssertionID(aid.get());\r
+        assertion->setIssueInstant(issueInstant.get());\r
+        assertion->setIssuer(issuer.get());\r
+        assertion->getAuthenticationStatements().push_back(statement);\r
+\r
+        // Append a Signature.\r
+        assertion->setSignature(SignatureBuilder::buildSignature());\r
+        assertion->getSignature()->setSigningKey(m_key->clone());\r
+\r
+        // Build KeyInfo.\r
+        KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo();\r
+        X509Data* x509Data=X509DataBuilder::buildX509Data();\r
+        keyInfo->getX509Datas().push_back(x509Data);\r
+        for_each(m_certs.begin(),m_certs.end(),bind1st(_addcert(),x509Data));\r
+        assertion->getSignature()->setKeyInfo(keyInfo);\r
+\r
+        // Sign assertion while marshalling.\r
+        vector<Signature*> sigs(1,assertion->getSignature());\r
+        DOMElement* rootElement = NULL;\r
+        try {\r
+            rootElement=assertion->marshall((DOMDocument*)NULL,&sigs);\r
+        }\r
+        catch (XMLToolingException& e) {\r
+            TS_TRACE(e.what());\r
+            delete assertion;\r
+            throw;\r
+        }\r
+\r
+        StatusCode* sc=StatusCodeBuilder::buildStatusCode();\r
+        sc->setValue(&StatusCode::SUCCESS);\r
+        Status* status=StatusBuilder::buildStatus();\r
+        status->setStatusCode(sc);\r
+\r
+        auto_ptr<Response> response(ResponseBuilder::buildResponse());\r
+        response->setResponseID(rid.get());\r
+        response->setIssueInstant(issueInstant.get());\r
+        response->setStatus(status);\r
+        response->getAssertions().push_back(assertion);\r
+        response->setSignature(SignatureBuilder::buildSignature());\r
+        response->getSignature()->setSigningKey(m_key->clone());\r
+        response->getSignature()->setKeyInfo(keyInfo->cloneKeyInfo());\r
+\r
+        // Sign response while marshalling.\r
+        sigs.clear();\r
+        sigs.push_back(response->getSignature());\r
+        rootElement = NULL;\r
+        try {\r
+            rootElement=response->marshall((DOMDocument*)NULL,&sigs);\r
+        }\r
+        catch (XMLToolingException& e) {\r
+            TS_TRACE(e.what());\r
+            throw;\r
+        }\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()->registerValidator(new SignatureProfileValidator());\r
+            assertion->getSignature()->registerValidator(new TestValidator());\r
+            assertion->getSignature()->validate(true);\r
+            response->getSignature()->registerValidator(new SignatureProfileValidator());\r
+            response->getSignature()->registerValidator(new TestValidator());\r
+            response->getSignature()->validate(true);\r
+        }\r
+        catch (XMLToolingException& e) {\r
+            TS_TRACE(e.what());\r
+            throw;\r
+        }\r
+    }\r
+\r
+};\r