From: cantor Date: Sun, 21 May 2006 19:54:38 +0000 (+0000) Subject: Additional signature tests, including nesting. X-Git-Tag: 2.4.1~590 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fopensaml2.git;a=commitdiff_plain;h=a15da963e3d616bf78a678f62130a5c1b306f973 Additional signature tests, including nesting. git-svn-id: https://svn.middleware.georgetown.edu/cpp-opensaml2/trunk@24 fb386ef7-a10c-0410-8ebf-fd3f8e989ab0 --- diff --git a/saml/saml1/core/impl/ProtocolsImpl.cpp b/saml/saml1/core/impl/ProtocolsImpl.cpp index 24317e4..1c6ee51 100644 --- a/saml/saml1/core/impl/ProtocolsImpl.cpp +++ b/saml/saml1/core/impl/ProtocolsImpl.cpp @@ -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); diff --git a/samltest/Makefile.am b/samltest/Makefile.am index ba32aaa..394483f 100644 --- a/samltest/Makefile.am +++ b/samltest/Makefile.am @@ -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 index 0000000..e40d5e2 --- /dev/null +++ b/samltest/data/signature/SAML1Request.xml @@ -0,0 +1,31 @@ + + + + + + + + + + +pqhIt8nUldh3KVL6IEewRxKXYhM= + + +UE5p832pLFYvMloRofN3y0rrFY7B8zOcF7+CHYyxFn6pqgPeEYGqkbUWlV15/tJ5 +wXJ3LiLQroYQI3XHPvKRSV4OtF9ZFm4QDK7RNd6gnUmHed6Zje//e6z2ekA0UzTl +IeWCuD84mWemMJzRAhSFKcnqJDBHA61Krvg1kf/2c2E= +MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV +BAYTAlVTMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDnNwLmV4YW1wbGUu +b3JnMB4XDTA1MDYyMDE1NDgzNFoXDTMyMTEwNTE1NDgzNFowOjELMAkGA1UEBhMC +VVMxEjAQBgNVBAoTCUludGVybmV0MjEXMBUGA1UEAxMOc3AuZXhhbXBsZS5vcmcw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANlZ1L1mKzYbUVKiMQLhZlfGDyYa +/jjCiaXP0WhLNgvJpOTeajvsrApYNnFX5MLNzuC3NeQIjXUNLN2Yo2MCSthBIOL5 +qE5dka4z9W9zytoflW1LmJ8vXpx8Ay/meG4z//J5iCpYVEquA0xl28HUIlownZUF +7w7bx0cF/02qrR23AgMBAAGjgZwwgZkwHQYDVR0OBBYEFJZiO1qsyAyc3HwMlL9p +JpN6fbGwMGoGA1UdIwRjMGGAFJZiO1qsyAyc3HwMlL9pJpN6fbGwoT6kPDA6MQsw +CQYDVQQGEwJVUzESMBAGA1UEChMJSW50ZXJuZXQyMRcwFQYDVQQDEw5zcC5leGFt +cGxlLm9yZ4IJAKk8t1hYcMkhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD +gYEAMFq/UeSQyngE0GpZueyD2UW0M358uhseYOgGEIfm+qXIFQF6MYwNoX7WFzhC +LJZ2E6mEvZZFHCHUtl7mGDvsRwgZ85YCtRbvleEpqfgNQToto9pLYe+X6vvH9Z6p +gmYsTmak+kxO93JprrOd9xp8aZPMEprL7VCdrhbZEfyYER0=John Doe diff --git a/samltest/data/signature/SAML1Response.xml b/samltest/data/signature/SAML1Response.xml new file mode 100644 index 0000000..281957b --- /dev/null +++ b/samltest/data/signature/SAML1Response.xml @@ -0,0 +1,63 @@ + + + + + + + + + + +WjLtIcoArwwdHVOks5QnbnFuE9g= + + +cwC985/W+J8HrkDgMK1fYPfRP7e6aAAKJM/8rTWbOnI6feF8jrsQhSQ9qBon5o46 +4eHMDYAcH4xd9rGPeYib4jjH2hAPAF0rqLX1FWNTZgS+lJQFhhj5Sys0Ja6C0wsx +0CoEWraR/IiDpRwnz9gGj2jGnfokfBdsLiomuxC2ZNY= +MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV +BAYTAlVTMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDnNwLmV4YW1wbGUu +b3JnMB4XDTA1MDYyMDE1NDgzNFoXDTMyMTEwNTE1NDgzNFowOjELMAkGA1UEBhMC +VVMxEjAQBgNVBAoTCUludGVybmV0MjEXMBUGA1UEAxMOc3AuZXhhbXBsZS5vcmcw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANlZ1L1mKzYbUVKiMQLhZlfGDyYa +/jjCiaXP0WhLNgvJpOTeajvsrApYNnFX5MLNzuC3NeQIjXUNLN2Yo2MCSthBIOL5 +qE5dka4z9W9zytoflW1LmJ8vXpx8Ay/meG4z//J5iCpYVEquA0xl28HUIlownZUF +7w7bx0cF/02qrR23AgMBAAGjgZwwgZkwHQYDVR0OBBYEFJZiO1qsyAyc3HwMlL9p +JpN6fbGwMGoGA1UdIwRjMGGAFJZiO1qsyAyc3HwMlL9pJpN6fbGwoT6kPDA6MQsw +CQYDVQQGEwJVUzESMBAGA1UEChMJSW50ZXJuZXQyMRcwFQYDVQQDEw5zcC5leGFt +cGxlLm9yZ4IJAKk8t1hYcMkhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD +gYEAMFq/UeSQyngE0GpZueyD2UW0M358uhseYOgGEIfm+qXIFQF6MYwNoX7WFzhC +LJZ2E6mEvZZFHCHUtl7mGDvsRwgZ85YCtRbvleEpqfgNQToto9pLYe+X6vvH9Z6p +gmYsTmak+kxO93JprrOd9xp8aZPMEprL7VCdrhbZEfyYER0=John Doe + + + + + + + + + +/owFROXYYru5+/j0TpHEz+hjXqY= + + +d4SsRgDSjboTRA2YUD68TPp+17AqRmxbY/LrWJhueIC/JY+Ct7+Fd6bugUXliIeD +NVRDACsEB7PqYWZ99+Ecf8XAmQYCw5elj8mWxPp0o+UVHtBZOR2bC+/YjNitSM+x +G/F3JgZqfunUcg7mcj6WEAUt4pjKhjaTY8Z7QJltdKc= +MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV +BAYTAlVTMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDnNwLmV4YW1wbGUu +b3JnMB4XDTA1MDYyMDE1NDgzNFoXDTMyMTEwNTE1NDgzNFowOjELMAkGA1UEBhMC +VVMxEjAQBgNVBAoTCUludGVybmV0MjEXMBUGA1UEAxMOc3AuZXhhbXBsZS5vcmcw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANlZ1L1mKzYbUVKiMQLhZlfGDyYa +/jjCiaXP0WhLNgvJpOTeajvsrApYNnFX5MLNzuC3NeQIjXUNLN2Yo2MCSthBIOL5 +qE5dka4z9W9zytoflW1LmJ8vXpx8Ay/meG4z//J5iCpYVEquA0xl28HUIlownZUF +7w7bx0cF/02qrR23AgMBAAGjgZwwgZkwHQYDVR0OBBYEFJZiO1qsyAyc3HwMlL9p +JpN6fbGwMGoGA1UdIwRjMGGAFJZiO1qsyAyc3HwMlL9pJpN6fbGwoT6kPDA6MQsw +CQYDVQQGEwJVUzESMBAGA1UEChMJSW50ZXJuZXQyMRcwFQYDVQQDEw5zcC5leGFt +cGxlLm9yZ4IJAKk8t1hYcMkhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD +gYEAMFq/UeSQyngE0GpZueyD2UW0M358uhseYOgGEIfm+qXIFQF6MYwNoX7WFzhC +LJZ2E6mEvZZFHCHUtl7mGDvsRwgZ85YCtRbvleEpqfgNQToto9pLYe+X6vvH9Z6p +gmYsTmak+kxO93JprrOd9xp8aZPMEprL7VCdrhbZEfyYER0= diff --git a/samltest/samltest.vcproj b/samltest/samltest.vcproj index a9df5f2..2887473 100644 --- a/samltest/samltest.vcproj +++ b/samltest/samltest.vcproj @@ -241,6 +241,14 @@ RelativePath=".\signature\SAML1AssertionTest.cpp" > + + + + + + + + + + + + + + + + + + + + diff --git a/samltest/signature/SAML1RequestTest.h b/samltest/signature/SAML1RequestTest.h new file mode 100644 index 0000000..61ca7f9 --- /dev/null +++ b/samltest/signature/SAML1RequestTest.h @@ -0,0 +1,175 @@ +/* + * Copyright 2001-2005 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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace opensaml::saml1; +using namespace xmlsignature; + +class TestValidator : public Validator +{ +public: + TestValidator() {} + virtual ~TestValidator() {} + + Validator* clone() const { + return new TestValidator(); + } + + void validate(const XMLObject* xmlObject) const { + DSIGSignature* sig=dynamic_cast(xmlObject)->getXMLSignature(); + if (!sig) + throw SignatureException("Only a marshalled Signature object can be verified."); + XSECKeyInfoResolverDefault resolver; + sig->setKeyInfoResolver(&resolver); // It will clone the resolver for us. + try { + if (!sig->verify()) + throw SignatureException("Signature did not verify."); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + e.getMsg()); + } + } +}; + +class _addcert : public std::binary_function { +public: + void operator()(X509Data* bag, XSECCryptoX509* cert) const { + safeBuffer& buf=cert->getDEREncodingSB(); + X509Certificate* x=X509CertificateBuilder::buildX509Certificate(); + x->setValue(buf.sbStrToXMLCh()); + bag->getX509Certificates().push_back(x); + } +}; + +class SAML1RequestTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase { + XSECCryptoKey* m_key; + vector m_certs; +public: + void setUp() { + childElementsFile = data_path + "signature/SAML1Request.xml"; + SAMLObjectBaseTestCase::setUp(); + string keypath=data_path + "key.pem"; + BIO* in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,keypath.c_str())>0) { + EVP_PKEY* pkey=PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); + if (pkey) { + m_key=new OpenSSLCryptoKeyRSA(pkey); + EVP_PKEY_free(pkey); + } + } + if (in) BIO_free(in); + TS_ASSERT(m_key!=NULL); + + string certpath=data_path + "cert.pem"; + in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,certpath.c_str())>0) { + X509* x=NULL; + while (x=PEM_read_bio_X509(in,NULL,NULL,NULL)) { + m_certs.push_back(new OpenSSLCryptoX509(x)); + X509_free(x); + } + } + if (in) BIO_free(in); + TS_ASSERT(m_certs.size()>0); + } + + void tearDown() { + SAMLObjectBaseTestCase::tearDown(); + delete m_key; + for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup()); + } + + void testSignature() { + 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"); + + NameIdentifier* n=NameIdentifierBuilder::buildNameIdentifier(); + n->setName(nameid.get()); + Subject* subject=SubjectBuilder::buildSubject(); + subject->setNameIdentifier(n); + + AuthenticationQuery* query=AuthenticationQueryBuilder::buildAuthenticationQuery(); + query->setAuthenticationMethod(method.get()); + query->setSubject(subject); + + auto_ptr request(RequestBuilder::buildRequest()); + request->setRequestID(id.get()); + request->setIssueInstant(issueInstant.get()); + request->setAuthenticationQuery(query); + + // Append a Signature. + Signature* sig=SignatureBuilder::buildSignature(); + request->setSignature(sig); + sig->setSigningKey(m_key->clone()); + + // Build KeyInfo. + KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo(); + X509Data* x509Data=X509DataBuilder::buildX509Data(); + keyInfo->getX509Datas().push_back(x509Data); + for_each(m_certs.begin(),m_certs.end(),bind1st(_addcert(),x509Data)); + sig->setKeyInfo(keyInfo); + + // Sign while marshalling. + vector sigs(1,sig); + DOMElement* rootElement = NULL; + try { + rootElement=request->marshall((DOMDocument*)NULL,&sigs); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + throw; + } + + string buf; + XMLHelper::serialize(rootElement, buf); + istringstream in(buf); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + + assertEquals(expectedChildElementsDOM, b->buildFromDocument(doc)); + + try { + request->getSignature()->registerValidator(new SignatureProfileValidator()); + request->getSignature()->registerValidator(new TestValidator()); + request->getSignature()->validate(true); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + throw; + } + } + +}; diff --git a/samltest/signature/SAML1ResponseTest.h b/samltest/signature/SAML1ResponseTest.h new file mode 100644 index 0000000..e63856f --- /dev/null +++ b/samltest/signature/SAML1ResponseTest.h @@ -0,0 +1,208 @@ +/* + * Copyright 2001-2005 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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace opensaml::saml1; +using namespace xmlsignature; + +class TestValidator : public Validator +{ +public: + TestValidator() {} + virtual ~TestValidator() {} + + Validator* clone() const { + return new TestValidator(); + } + + void validate(const XMLObject* xmlObject) const { + DSIGSignature* sig=dynamic_cast(xmlObject)->getXMLSignature(); + if (!sig) + throw SignatureException("Only a marshalled Signature object can be verified."); + XSECKeyInfoResolverDefault resolver; + sig->setKeyInfoResolver(&resolver); // It will clone the resolver for us. + try { + if (!sig->verify()) + throw SignatureException("Signature did not verify."); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + e.getMsg()); + } + } +}; + +class _addcert : public std::binary_function { +public: + void operator()(X509Data* bag, XSECCryptoX509* cert) const { + safeBuffer& buf=cert->getDEREncodingSB(); + X509Certificate* x=X509CertificateBuilder::buildX509Certificate(); + x->setValue(buf.sbStrToXMLCh()); + bag->getX509Certificates().push_back(x); + } +}; + +class SAML1ResponseTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase { + XSECCryptoKey* m_key; + vector m_certs; +public: + void setUp() { + childElementsFile = data_path + "signature/SAML1Response.xml"; + SAMLObjectBaseTestCase::setUp(); + string keypath=data_path + "key.pem"; + BIO* in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,keypath.c_str())>0) { + EVP_PKEY* pkey=PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); + if (pkey) { + m_key=new OpenSSLCryptoKeyRSA(pkey); + EVP_PKEY_free(pkey); + } + } + if (in) BIO_free(in); + TS_ASSERT(m_key!=NULL); + + string certpath=data_path + "cert.pem"; + in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,certpath.c_str())>0) { + X509* x=NULL; + while (x=PEM_read_bio_X509(in,NULL,NULL,NULL)) { + m_certs.push_back(new OpenSSLCryptoX509(x)); + X509_free(x); + } + } + if (in) BIO_free(in); + TS_ASSERT(m_certs.size()>0); + } + + void tearDown() { + SAMLObjectBaseTestCase::tearDown(); + delete m_key; + for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup()); + } + + void testSignature() { + auto_ptr_XMLCh issuer("issuer"); + auto_ptr_XMLCh issueInstant("1970-01-02T01:01:02.100Z"); + auto_ptr_XMLCh aid("aident"); + auto_ptr_XMLCh rid("rident"); + auto_ptr_XMLCh method("method"); + auto_ptr_XMLCh nameid("John Doe"); + + NameIdentifier* n=NameIdentifierBuilder::buildNameIdentifier(); + n->setName(nameid.get()); + Subject* subject=SubjectBuilder::buildSubject(); + subject->setNameIdentifier(n); + + AuthenticationStatement* statement=AuthenticationStatementBuilder::buildAuthenticationStatement(); + statement->setAuthenticationInstant(issueInstant.get()); + statement->setAuthenticationMethod(method.get()); + statement->setSubject(subject); + + Assertion* assertion=AssertionBuilder::buildAssertion(); + assertion->setAssertionID(aid.get()); + assertion->setIssueInstant(issueInstant.get()); + assertion->setIssuer(issuer.get()); + assertion->getAuthenticationStatements().push_back(statement); + + // Append a Signature. + assertion->setSignature(SignatureBuilder::buildSignature()); + assertion->getSignature()->setSigningKey(m_key->clone()); + + // Build KeyInfo. + KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo(); + X509Data* x509Data=X509DataBuilder::buildX509Data(); + keyInfo->getX509Datas().push_back(x509Data); + for_each(m_certs.begin(),m_certs.end(),bind1st(_addcert(),x509Data)); + assertion->getSignature()->setKeyInfo(keyInfo); + + // Sign assertion while marshalling. + vector sigs(1,assertion->getSignature()); + DOMElement* rootElement = NULL; + try { + rootElement=assertion->marshall((DOMDocument*)NULL,&sigs); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + delete assertion; + throw; + } + + StatusCode* sc=StatusCodeBuilder::buildStatusCode(); + sc->setValue(&StatusCode::SUCCESS); + Status* status=StatusBuilder::buildStatus(); + status->setStatusCode(sc); + + auto_ptr response(ResponseBuilder::buildResponse()); + response->setResponseID(rid.get()); + response->setIssueInstant(issueInstant.get()); + response->setStatus(status); + response->getAssertions().push_back(assertion); + response->setSignature(SignatureBuilder::buildSignature()); + response->getSignature()->setSigningKey(m_key->clone()); + response->getSignature()->setKeyInfo(keyInfo->cloneKeyInfo()); + + // Sign response while marshalling. + sigs.clear(); + sigs.push_back(response->getSignature()); + rootElement = NULL; + try { + rootElement=response->marshall((DOMDocument*)NULL,&sigs); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + throw; + } + + string buf; + XMLHelper::serialize(rootElement, buf); + istringstream in(buf); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + + assertEquals(expectedChildElementsDOM, b->buildFromDocument(doc)); + + try { + assertion->getSignature()->registerValidator(new SignatureProfileValidator()); + assertion->getSignature()->registerValidator(new TestValidator()); + assertion->getSignature()->validate(true); + response->getSignature()->registerValidator(new SignatureProfileValidator()); + response->getSignature()->registerValidator(new TestValidator()); + response->getSignature()->validate(true); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + throw; + } + } + +};