Multi-line svn commit, see body.
authorScott Cantor <cantor.2@osu.edu>
Fri, 20 Apr 2007 19:51:04 +0000 (19:51 +0000)
committerScott Cantor <cantor.2@osu.edu>
Fri, 20 Apr 2007 19:51:04 +0000 (19:51 +0000)
Encrypted assertion test.
SAML-specific encryption key resolver needs to call base class.

.cdtproject
saml/encryption/EncryptedKeyResolver.cpp
saml/saml2/core/impl/Assertions.cpp
samltest/Makefile.am
samltest/data/binding/example-metadata.xml
samltest/encryption/EncryptedAssertionTest.cpp [new file with mode: 0644]
samltest/encryption/EncryptedAssertionTest.h [new file with mode: 0644]
samltest/samltest.vcproj

index 5bc0b69..7053798 100644 (file)
@@ -73,7 +73,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/" kind="src" path="samltest"/>\r
+<pathentry excluding="saml1/core/impl/|signature/|saml2/core/impl/|saml2/metadata/|security/|saml1/binding/|saml2/binding/|encryption/" 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
@@ -90,6 +90,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 kind="src" path="samltest/encryption"/>\r
 </item>\r
 </data>\r
 </cdtproject>\r
index 8831717..449a753 100644 (file)
@@ -29,6 +29,10 @@ using namespace std;
 
 const EncryptedKey* opensaml::EncryptedKeyResolver::resolveKey(const EncryptedData& encryptedData, const XMLCh* recipient) const
 {
+    const EncryptedKey* base = xmlencryption::EncryptedKeyResolver::resolveKey(encryptedData, recipient);
+    if (base)
+        return base;
+
     const vector<EncryptedKey*>& keys=m_ref.getEncryptedKeys();
     for (vector<EncryptedKey*>::const_iterator i=keys.begin(); i!=keys.end(); i++) {
         if (XMLString::equals(recipient,(*i)->getRecipient()))
index 585723a..dbbc6e3 100644 (file)
@@ -79,9 +79,6 @@ void EncryptedElementType::encrypt(
     const XMLCh* algorithm
     )
 {
-    if (recipients.size()==1)
-        return encrypt(xmlObject, *recipients.front().first, *recipients.front().second, compact, algorithm);
-
     // With multiple recipients, we have to generate an encryption key and then multicast it,
     // so we need to split the encryption and key wrapping steps.
     if (!algorithm || !*algorithm)
index 932a2c5..706d38b 100644 (file)
@@ -14,6 +14,7 @@ samltest_h = \
     SAMLArtifactType0002Test.h \
     SAMLArtifactType0004Test.h \
     ArtifactMapTest.h \
+    encryption/EncryptedAssertionTest.h \
     signature/SAML1AssertionTest.h \
     signature/SAML1RequestTest.h \
     signature/SAML1ResponseTest.h \
index f4e82f8..1a3f5f3 100644 (file)
@@ -6,7 +6,7 @@
        <EntityDescriptor entityID="https://idp.example.org/">\r
                \r
                <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">\r
-                       <KeyDescriptor use="signing">\r
+                       <KeyDescriptor>\r
                            <ds:KeyInfo>\r
                                <ds:RetrievalMethod URI="#samplekey" Type="http://www.w3.org/2000/09/xmldsig#X509Data"/>
                            </ds:KeyInfo>\r
@@ -31,8 +31,9 @@
        <EntityDescriptor entityID="https://sp.example.org/">\r
        \r
                <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">\r
-                       <KeyDescriptor use="signing">\r
+                       <KeyDescriptor>\r
                                <ds:KeyInfo Id="samplekey">\r
+                                       <ds:KeyName>sp.example.org</ds:KeyName>\r
                                <ds:X509Data>
                                        <ds:X509Certificate>
                                                MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV
diff --git a/samltest/encryption/EncryptedAssertionTest.cpp b/samltest/encryption/EncryptedAssertionTest.cpp
new file mode 100644 (file)
index 0000000..c835ff6
--- /dev/null
@@ -0,0 +1,27 @@
+/* Generated file, do not edit */\r
+\r
+#ifndef CXXTEST_RUNNING\r
+#define CXXTEST_RUNNING\r
+#endif\r
+\r
+#define _CXXTEST_HAVE_STD\r
+#define _CXXTEST_HAVE_EH\r
+#define _CXXTEST_ABORT_TEST_ON_FAIL\r
+#include <cxxtest/TestListener.h>\r
+#include <cxxtest/TestTracker.h>\r
+#include <cxxtest/TestRunner.h>\r
+#include <cxxtest/RealDescriptions.h>\r
+\r
+#include "c:\cvs\cpp-opensaml2\samltest\encryption\EncryptedAssertionTest.h"\r
+\r
+static EncryptedAssertionTest suite_EncryptedAssertionTest;\r
+\r
+static CxxTest::List Tests_EncryptedAssertionTest = { 0, 0 };\r
+CxxTest::StaticSuiteDescription suiteDescription_EncryptedAssertionTest( "c:\\cvs\\cpp-opensaml2\\samltest\\encryption\\EncryptedAssertionTest.h", 30, "EncryptedAssertionTest", suite_EncryptedAssertionTest, Tests_EncryptedAssertionTest );\r
+\r
+static class TestDescription_EncryptedAssertionTest_testEncryptedAssertion : public CxxTest::RealTestDescription {\r
+public:\r
+ TestDescription_EncryptedAssertionTest_testEncryptedAssertion() : CxxTest::RealTestDescription( Tests_EncryptedAssertionTest, suiteDescription_EncryptedAssertionTest, 59, "testEncryptedAssertion" ) {}\r
+ void runTest() { suite_EncryptedAssertionTest.testEncryptedAssertion(); }\r
+} testDescription_EncryptedAssertionTest_testEncryptedAssertion;\r
+\r
diff --git a/samltest/encryption/EncryptedAssertionTest.h b/samltest/encryption/EncryptedAssertionTest.h
new file mode 100644 (file)
index 0000000..70eb860
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ *  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 "signature/SAMLSignatureTestBase.h"
+
+#include <fstream>
+#include <saml/SAMLConfig.h>
+#include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataProvider.h>
+#include <saml/saml2/metadata/MetadataCredentialContext.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+
+using namespace opensaml::saml2md;
+using namespace opensaml::saml2;
+
+class EncryptedAssertionTest : public CxxTest::TestSuite, public SAMLSignatureTestBase {
+    MetadataProvider* m_metadata;
+public:
+    void setUp() {
+        childElementsFile  = data_path + "signature/SAML2Assertion.xml";
+        SAMLSignatureTestBase::setUp();
+        
+        string config = data_path + "binding/ExampleMetadataProvider.xml";
+        ifstream in(config.c_str());
+        DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
+        XercesJanitor<DOMDocument> janitor(doc);
+
+        auto_ptr_XMLCh path("path");
+        string s = data_path + "binding/example-metadata.xml";
+        auto_ptr_XMLCh file(s.c_str());
+        doc->getDocumentElement()->setAttributeNS(NULL,path.get(),file.get());
+
+        m_metadata = opensaml::SAMLConfig::getConfig().MetadataProviderManager.newPlugin(
+            XML_METADATA_PROVIDER,doc->getDocumentElement()
+            );
+        m_metadata->init();
+    }
+
+    void tearDown() {
+        delete m_metadata;
+        m_metadata=NULL;
+        SAMLSignatureTestBase::tearDown();
+    }
+
+    void testEncryptedAssertion() {
+        auto_ptr_XMLCh issuer("issuer");
+        auto_ptr_XMLCh issueInstant("1970-01-02T01:01:02.100Z");
+        auto_ptr_XMLCh id("ident");
+        auto_ptr_XMLCh method("method");
+        auto_ptr_XMLCh nameid("John Doe");
+        
+        Issuer* is=IssuerBuilder::buildIssuer();
+        is->setName(issuer.get());
+
+        NameID* n=NameIDBuilder::buildNameID();
+        n->setName(nameid.get());        
+        Subject* subject=SubjectBuilder::buildSubject();
+        subject->setNameID(n);
+
+        AuthnStatement* statement=AuthnStatementBuilder::buildAuthnStatement();
+        statement->setAuthnInstant(issueInstant.get());
+
+        AuthnContext* ac=AuthnContextBuilder::buildAuthnContext();
+        AuthnContextClassRef* acc=AuthnContextClassRefBuilder::buildAuthnContextClassRef();
+        acc->setReference(method.get());
+        ac->setAuthnContextClassRef(acc);
+        statement->setAuthnContext(ac);
+        
+        auto_ptr<Assertion> assertion(AssertionBuilder::buildAssertion());
+        assertion->setID(id.get());
+        assertion->setIssueInstant(issueInstant.get());
+        assertion->setIssuer(is);
+        assertion->setSubject(subject);
+        assertion->getAuthnStatements().push_back(statement);
+
+        // Append a Signature.
+        Signature* sig=SignatureBuilder::buildSignature();
+        assertion->setSignature(sig);
+
+        // Sign while marshalling.
+        vector<Signature*> sigs(1,sig);
+        CredentialCriteria cc;
+        cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
+        Locker locker(m_resolver);
+        const Credential* cred = m_resolver->resolve(&cc);
+        TSM_ASSERT("Retrieved credential was null", cred!=NULL);
+
+        DOMElement* rootElement = NULL;
+        try {
+            rootElement=assertion->marshall((DOMDocument*)NULL,&sigs,cred);
+        }
+        catch (XMLToolingException& e) {
+            TS_TRACE(e.what());
+            throw;
+        }
+        
+        // Now encrypt this puppy to the SP role in the example metadata.
+        auto_ptr<EncryptedAssertion> encrypted(EncryptedAssertionBuilder::buildEncryptedAssertion());
+        Locker mlocker(m_metadata);
+        const EntityDescriptor* sp = m_metadata->getEntityDescriptor("https://sp.example.org/");
+        TSM_ASSERT("No metadata for recipient.", sp!=NULL); 
+        const SPSSODescriptor* sprole =  sp->getSPSSODescriptor(samlconstants::SAML20P_NS);
+        TSM_ASSERT("No SP role for recipient.", sprole!=NULL);
+        MetadataCredentialCriteria mcc(*sprole);
+        vector< pair<const MetadataProvider*,MetadataCredentialCriteria*> > recipients(1, make_pair(m_metadata, &mcc));
+        encrypted->encrypt(*assertion.get(), recipients);
+        
+        // Roundtrip it.
+        string buf;
+        XMLHelper::serialize(encrypted->marshall(), buf);
+        //TS_TRACE(buf.c_str());
+        istringstream in(buf);
+        DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
+        const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
+        
+        // Unpack, then decypt with our key.
+        auto_ptr<EncryptedAssertion> encrypted2(dynamic_cast<EncryptedAssertion*>(b->buildFromDocument(doc)));
+        auto_ptr<Assertion> assertion2(dynamic_cast<Assertion*>(encrypted2->decrypt(*m_resolver, sp->getEntityID())));
+        assertEquals("Unmarshalled assertion does not match", expectedChildElementsDOM, assertion2.get(), false);
+        
+        // And check the signature.
+        try {
+            opensaml::SignatureProfileValidator spv;
+            SignatureValidator sv(cred);
+            spv.validate(dynamic_cast<Assertion*>(assertion2.get())->getSignature());
+            sv.validate(dynamic_cast<Assertion*>(assertion2.get())->getSignature());
+        }
+        catch (XMLToolingException& e) {
+            TS_TRACE(e.what());
+            throw;
+        }
+    }
+
+};
index 0eeb2b0..543520e 100644 (file)
                                        >\r
                                </File>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="encryption"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\encryption\EncryptedAssertionTest.cpp"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Unit Tests"\r
                                        </FileConfiguration>\r
                                </File>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="encryption"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\encryption\EncryptedAssertionTest.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="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
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r