From 0d4d73adf7fa522e14d34932c0bd56e2907481cb Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Tue, 1 Aug 2006 18:15:11 +0000 Subject: [PATCH] SAML 2.0 artifact bits plus tests --- saml/Makefile.am | 8 +- saml/SAMLArtifact.cpp | 6 +- saml/saml.vcproj | 16 ++++ saml/saml1/core/SAMLArtifactType0001.h | 2 +- saml/saml1/core/SAMLArtifactType0002.h | 2 +- saml/saml2/core/SAML2Artifact.h | 61 +++++++++++++++ saml/saml2/core/SAML2ArtifactType0004.h | 89 +++++++++++++++++++++ saml/saml2/core/impl/SAML2Artifact.cpp | 37 +++++++++ saml/saml2/core/impl/SAML2ArtifactType0004.cpp | 85 ++++++++++++++++++++ samltest/Makefile.am | 4 + samltest/SAMLArtifactCreationTest.h | 84 ++++++++++++++++++++ samltest/SAMLArtifactType0001Test.h | 44 +++++++++++ samltest/SAMLArtifactType0002Test.h | 42 ++++++++++ samltest/SAMLArtifactType0004Test.h | 45 +++++++++++ samltest/samltest.vcproj | 104 +++++++++++++++++++++++++ 15 files changed, 622 insertions(+), 7 deletions(-) create mode 100644 saml/saml2/core/SAML2Artifact.h create mode 100644 saml/saml2/core/SAML2ArtifactType0004.h create mode 100644 saml/saml2/core/impl/SAML2Artifact.cpp create mode 100644 saml/saml2/core/impl/SAML2ArtifactType0004.cpp create mode 100644 samltest/SAMLArtifactCreationTest.h create mode 100644 samltest/SAMLArtifactType0001Test.h create mode 100644 samltest/SAMLArtifactType0002Test.h create mode 100644 samltest/SAMLArtifactType0004Test.h diff --git a/saml/Makefile.am b/saml/Makefile.am index 97ea7b1..31abc1a 100644 --- a/saml/Makefile.am +++ b/saml/Makefile.am @@ -42,7 +42,9 @@ saml1coreinclude_HEADERS = \ saml2coreinclude_HEADERS = \ saml2/core/Assertions.h \ - saml2/core/Protocols.h + saml2/core/Protocols.h \ + saml2/core/SAML2Artifact.h \ + saml2/core/SAML2ArtifactType0004.h saml2mdinclude_HEADERS = \ saml2/metadata/Metadata.h @@ -53,7 +55,7 @@ noinst_HEADERS = \ internal.h libsaml_la_SOURCES = \ - SAMLArtifact.h \ + SAMLArtifact.cpp \ SAMLConfig.cpp \ encryption/EncryptedKeyResolver.cpp \ saml1/core/impl/AssertionsImpl.cpp \ @@ -66,6 +68,8 @@ libsaml_la_SOURCES = \ saml2/core/impl/Assertions20SchemaValidators.cpp \ saml2/core/impl/Protocols20Impl.cpp \ saml2/core/impl/Protocols20SchemaValidators.cpp \ + saml2/core/impl/SAML2Artifact.cpp \ + saml2/core/impl/SAML2ArtifactType0004.cpp \ saml2/metadata/impl/BlacklistMetadataFilter.cpp \ saml2/metadata/impl/FilesystemMetadataProvider.cpp \ saml2/metadata/impl/MetadataImpl.cpp \ diff --git a/saml/SAMLArtifact.cpp b/saml/SAMLArtifact.cpp index 1f1bead..5c8d0fe 100644 --- a/saml/SAMLArtifact.cpp +++ b/saml/SAMLArtifact.cpp @@ -36,7 +36,7 @@ namespace opensaml { }; namespace saml2p { - //SAML_DLLLOCAL PluginManager::Factory SAMLArtifactType0004Factory; + SAML_DLLLOCAL PluginManager::Factory SAML2ArtifactType0004Factory; }; }; @@ -50,8 +50,8 @@ void SAML_API opensaml::registerSAMLArtifacts() conf.SAMLArtifactManager.registerFactory(typecode, saml1p::SAMLArtifactType0001Factory); typecode[1]=(char)0x2; conf.SAMLArtifactManager.registerFactory(typecode, saml1p::SAMLArtifactType0002Factory); - //typecode[1]=(char)0x4; - //conf.SAMLArtifactManager.registerFactory(typecode, saml2p::SAMLArtifactType0004Factory); + typecode[1]=(char)0x4; + conf.SAMLArtifactManager.registerFactory(typecode, saml2p::SAML2ArtifactType0004Factory); } const unsigned int SAMLArtifact::TYPECODE_LENGTH = 2; diff --git a/saml/saml.vcproj b/saml/saml.vcproj index 80c81c0..58ba323 100644 --- a/saml/saml.vcproj +++ b/saml/saml.vcproj @@ -278,6 +278,14 @@ RelativePath=".\saml2\core\impl\Protocols20SchemaValidators.cpp" > + + + + + + + + + +namespace opensaml { + namespace saml2p { + + /** + * Base class for SAML 2.0 artifacts + */ + class SAML_API SAML2Artifact : public SAMLArtifact + { + SAML2Artifact& operator=(const SAML2Artifact& src); + public: + virtual ~SAML2Artifact() {} + + /** + * Returns the endpoint index of the artifact. + * + * @return endpoint index + */ + virtual int getEndpointIndex() const; + + /** Length of endpoint index */ + static const unsigned int INDEX_LENGTH; + + protected: + SAML2Artifact() {} + + SAML2Artifact(const char* s) : SAMLArtifact(s) {} + + SAML2Artifact(const SAML2Artifact& src) : SAMLArtifact(src) {} + }; + + }; +}; + +#endif /* __saml2_artifact_h__ */ diff --git a/saml/saml2/core/SAML2ArtifactType0004.h b/saml/saml2/core/SAML2ArtifactType0004.h new file mode 100644 index 0000000..7a0375c --- /dev/null +++ b/saml/saml2/core/SAML2ArtifactType0004.h @@ -0,0 +1,89 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file saml/saml2/core/SAML2ArtifactType0004.h + * + * Type 0x0004 SAML 2.0 artifact class + */ + +#ifndef __saml_artifacttype0004_h__ +#define __saml_artifacttype0004_h__ + +#include + +namespace opensaml { + namespace saml2p { + + /** + * Type 0x0004 SAML 2.0 artifact class + */ + class SAML_API SAML2ArtifactType0004 : public SAML2Artifact + { + SAML2ArtifactType0004& operator=(const SAML2ArtifactType0004& src); + public: + /** + * Decodes a base64-encoded type 0x0004 artifact + * + * @param s NULL-terminated base64-encoded string + */ + SAML2ArtifactType0004(const char* s); + + /** + * Constructs an artifact with the specified source ID and index, but a random message handle. + * + * @param sourceid SOURCEID_LENGTH bytes of binary data + * @param index endpoint index + */ + SAML2ArtifactType0004(const std::string& sourceid, int index); + + /** + * Constructs an artifact with the specified source ID and assertion handle. + * + * @param sourceid SOURCEID_LENGTH bytes of binary data + * @param index endpoint index + * @param handle HANDLE_LENGTH bytes of binary data + */ + SAML2ArtifactType0004(const std::string& sourceid, int index, const std::string& handle); + + virtual ~SAML2ArtifactType0004() {} + + virtual SAML2ArtifactType0004* clone() const { + return new SAML2ArtifactType0004(*this); + } + + virtual std::string getSource() const { + return m_raw.substr(TYPECODE_LENGTH + INDEX_LENGTH, SOURCEID_LENGTH); // bytes 5-24 + } + + virtual std::string getMessageHandle() const { + return m_raw.substr(TYPECODE_LENGTH + INDEX_LENGTH + SOURCEID_LENGTH, HANDLE_LENGTH); // bytes 25-44 + } + + /** Length of source ID */ + static const unsigned int SOURCEID_LENGTH; + + /** Length of message handle */ + static const unsigned int HANDLE_LENGTH; + + protected: + SAML2ArtifactType0004(const SAML2ArtifactType0004& src) : SAML2Artifact(src) {} + }; + + }; +}; + +#endif /* __saml_artifacttype0004_h__ */ diff --git a/saml/saml2/core/impl/SAML2Artifact.cpp b/saml/saml2/core/impl/SAML2Artifact.cpp new file mode 100644 index 0000000..dcbd0f2 --- /dev/null +++ b/saml/saml2/core/impl/SAML2Artifact.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 2001-2006 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. + */ + +/** + * SAML2Artifact.cpp + * + * Base class for SAML 2.0 artifacts + */ + +#include "internal.h" +#include "saml2/core/SAML2Artifact.h" + +using namespace opensaml::saml2p; + +const unsigned int SAML2Artifact::INDEX_LENGTH = 2; + +int SAML2Artifact::getEndpointIndex() const +{ + int index=0; + if (m_raw.size()>=TYPECODE_LENGTH+INDEX_LENGTH) { + index = (16 * static_cast(m_raw[TYPECODE_LENGTH])) + static_cast(m_raw[TYPECODE_LENGTH+1]); + } + return index; +} diff --git a/saml/saml2/core/impl/SAML2ArtifactType0004.cpp b/saml/saml2/core/impl/SAML2ArtifactType0004.cpp new file mode 100644 index 0000000..22e6362 --- /dev/null +++ b/saml/saml2/core/impl/SAML2ArtifactType0004.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2001-2006 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. + */ + +/** + * SAML2ArtifactType0004.cpp + * + * Type 0x0004 SAML 2.0 artifact class + */ + +#include "internal.h" +#include "saml2/core/SAML2ArtifactType0004.h" + +using namespace opensaml::saml2p; +using namespace opensaml; +using namespace xmltooling; +using namespace std; + +namespace opensaml { + namespace saml2p { + SAMLArtifact* SAML_DLLLOCAL SAML2ArtifactType0004Factory(const char* const & s) + { + return new SAML2ArtifactType0004(s); + } + } +}; + +const unsigned int SAML2ArtifactType0004::SOURCEID_LENGTH = 20; +const unsigned int SAML2ArtifactType0004::HANDLE_LENGTH = 20; + +SAML2ArtifactType0004::SAML2ArtifactType0004(const char* s) : SAML2Artifact(s) +{ + // The base class does the work, we just do the checking. + if (m_raw.size() != TYPECODE_LENGTH + INDEX_LENGTH + SOURCEID_LENGTH + HANDLE_LENGTH) + throw ArtifactException("Type 0x0004 artifact is of incorrect length."); + else if (m_raw[0] != 0x0 || m_raw[1] != 0x4) + throw ArtifactException( + string("Type 0x0004 artifact given an artifact of invalid type (") + toHex(getTypeCode()) + ")." + ); +} + +SAML2ArtifactType0004::SAML2ArtifactType0004(const string& sourceid, int index) +{ + if (sourceid.size()!=SOURCEID_LENGTH) + throw ArtifactException("Type 0x0004 artifact sourceid of incorrect length."); + if (index < 0 || index > (1 << 16)-1) + throw ArtifactException("Type 0x0004 artifact index is invalid."); + m_raw+=(char)0x0; + m_raw+=(char)0x4; + m_raw+=(char)(index / 256); + m_raw+=(char)(index % 256); + m_raw.append(sourceid,0,SOURCEID_LENGTH); + char buf[HANDLE_LENGTH]; + SAMLConfig::getConfig().generateRandomBytes(buf,HANDLE_LENGTH); + for (int i=0; i (1 << 16)-1) + throw ArtifactException("Type 0x0004 artifact index is invalid."); + if (handle.size()!=HANDLE_LENGTH) + throw ArtifactException("Type 0x0004 artifact message handle of incorrect length."); + m_raw+=(char)0x0; + m_raw+=(char)0x4; + m_raw+=(char)(index / 256); + m_raw+=(char)(index % 256); + m_raw.append(sourceid,0,SOURCEID_LENGTH); + m_raw.append(handle,0,HANDLE_LENGTH); +} diff --git a/samltest/Makefile.am b/samltest/Makefile.am index f5de16d..0c83dbe 100644 --- a/samltest/Makefile.am +++ b/samltest/Makefile.am @@ -9,6 +9,10 @@ endif samltest_h = \ samltest.h \ + SAMLArtifactCreationTest.h \ + SAMLArtifactType0001Test.h \ + SAMLArtifactType0002Test.h \ + SAMLArtifactType0004Test.h \ signature/SAML1AssertionTest.h \ signature/SAML1RequestTest.h \ signature/SAML1ResponseTest.h \ diff --git a/samltest/SAMLArtifactCreationTest.h b/samltest/SAMLArtifactCreationTest.h new file mode 100644 index 0000000..104e7b1 --- /dev/null +++ b/samltest/SAMLArtifactCreationTest.h @@ -0,0 +1,84 @@ +/* + * 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 + +using namespace opensaml::saml1p; +using namespace opensaml::saml2p; +using namespace opensaml; +using namespace std; + +class SAMLArtifactCreationTest : public CxxTest::TestSuite +{ +public: + string providerIdStr; + string handle; + void setUp() { + if (handle.empty()) { + providerIdStr = "https://idp.org/SAML"; + SAMLConfig::getConfig().generateRandomBytes(handle,SAMLArtifactType0001::HANDLE_LENGTH); + } + } + void testSAMLArtifactType0001(void) { + SAMLConfig& conf=SAMLConfig::getConfig(); + string sourceId; + conf.generateRandomBytes(sourceId,SAMLArtifactType0001::SOURCEID_LENGTH); + SAMLArtifactType0001 artifact1(sourceId,handle); + //printResults(artifact1); + + SAMLArtifactType0001 artifact2(conf.hashSHA1(providerIdStr.c_str()),handle); + //printResults(artifact2,providerIdStr.c_str()); + } + + void testSAMLArtifactType0002(void) { + SAMLArtifactType0002 artifact(providerIdStr,handle); + //printResults(artifact,providerIdStr.c_str()); + } + + void testSAMLArtifactType0004(void) { + SAML2ArtifactType0004 artifact(SAMLConfig::getConfig().hashSHA1(providerIdStr.c_str()),666,handle); + //printResults(artifact,providerIdStr.c_str()); + } + + void printResults(SAMLArtifact& artifact, const char* str=NULL) { + // print heading: + cout << "Artifact Type " << SAMLArtifact::toHex(artifact.getTypeCode()); + cout << " (size = " << artifact.getBytes().size() << ")" << endl; + + // print URI: + if (str) { + cout << "URI: " << str << endl; + } + else { + cout << "URI: NONE" << endl; + } + + // print hex-encoded artifact: + cout << "Hex: " << SAMLArtifact::toHex(artifact.getBytes()) << endl; + + // print base64-encoded artifact: + cout << "Base64: " << artifact.encode() << endl; + + // print ruler: + cout << " ----------------------------------------------------------------------" << endl; + cout << " 1234567890123456789012345678901234567890123456789012345678901234567890" << endl; + cout << " 1 2 3 4 5 6 7" << endl; + cout << " ----------------------------------------------------------------------" << endl; + } +}; diff --git a/samltest/SAMLArtifactType0001Test.h b/samltest/SAMLArtifactType0001Test.h new file mode 100644 index 0000000..48c8754 --- /dev/null +++ b/samltest/SAMLArtifactType0001Test.h @@ -0,0 +1,44 @@ +/* + * 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 + +using namespace opensaml::saml1p; +using namespace opensaml; +using namespace std; + +class SAMLArtifactType0001Test : public CxxTest::TestSuite +{ +public: + string providerIdStr; + + void setUp() { + providerIdStr = "https://idp.org/SAML"; + } + + void testSAMLArtifactType0001(void) { + string sourceId = SAMLConfig::getConfig().hashSHA1(providerIdStr.c_str()); + auto_ptr artifact(new SAMLArtifactType0001(sourceId)); + auto_ptr tempArtifact(SAMLArtifact::parse(artifact->encode().c_str())); + + TS_ASSERT_EQUALS(artifact->getSource(),tempArtifact->getSource()); + TS_ASSERT_EQUALS(artifact->getMessageHandle(),tempArtifact->getMessageHandle()); + + TS_ASSERT_THROWS(auto_ptr bogus1(new SAMLArtifactType0001(sourceId + sourceId)), ArtifactException); + TS_ASSERT_THROWS(auto_ptr bogus2(new SAMLArtifactType0001(sourceId, artifact->getMessageHandle() + artifact->getMessageHandle())), ArtifactException); + } +}; diff --git a/samltest/SAMLArtifactType0002Test.h b/samltest/SAMLArtifactType0002Test.h new file mode 100644 index 0000000..8556105 --- /dev/null +++ b/samltest/SAMLArtifactType0002Test.h @@ -0,0 +1,42 @@ +/* + * 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 + +using namespace opensaml::saml1p; +using namespace opensaml; +using namespace std; + +class SAMLArtifactType0002Test : public CxxTest::TestSuite +{ +public: + string providerIdStr; + + void setUp() { + providerIdStr = "https://idp.org/SAML"; + } + + void testSAMLArtifactType0002(void) { + auto_ptr artifact(new SAMLArtifactType0002(providerIdStr)); + auto_ptr tempArtifact(SAMLArtifact::parse(artifact->encode().c_str())); + + TS_ASSERT_SAME_DATA(artifact->getSource().c_str(),tempArtifact->getSource().c_str(),artifact->getSource().length()); + TS_ASSERT_EQUALS(artifact->getMessageHandle(),tempArtifact->getMessageHandle()); + + TS_ASSERT_THROWS(auto_ptr bogus1(new SAMLArtifactType0002(providerIdStr, artifact->getMessageHandle() + artifact->getMessageHandle())), ArtifactException); + } +}; diff --git a/samltest/SAMLArtifactType0004Test.h b/samltest/SAMLArtifactType0004Test.h new file mode 100644 index 0000000..e2f57d0 --- /dev/null +++ b/samltest/SAMLArtifactType0004Test.h @@ -0,0 +1,45 @@ +/* + * 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 + +using namespace opensaml::saml2p; +using namespace opensaml; +using namespace std; + +class SAMLArtifactType0004Test : public CxxTest::TestSuite +{ +public: + string providerIdStr; + + void setUp() { + providerIdStr = "https://idp.org/SAML"; + } + + void testSAMLArtifactType0004(void) { + string sourceId = SAMLConfig::getConfig().hashSHA1(providerIdStr.c_str()); + auto_ptr artifact(new SAML2ArtifactType0004(sourceId,666)); + auto_ptr tempArtifact(dynamic_cast(SAMLArtifact::parse(artifact->encode().c_str()))); + + TS_ASSERT_EQUALS(artifact->getSource(),tempArtifact->getSource()); + TS_ASSERT_EQUALS(artifact->getEndpointIndex(),tempArtifact->getEndpointIndex()); + TS_ASSERT_EQUALS(artifact->getMessageHandle(),tempArtifact->getMessageHandle()); + + TS_ASSERT_THROWS(auto_ptr bogus1(new SAML2ArtifactType0004(sourceId, 100000)), ArtifactException); + TS_ASSERT_THROWS(auto_ptr bogus2(new SAML2ArtifactType0004(sourceId, 666, artifact->getMessageHandle() + artifact->getMessageHandle())), ArtifactException); + } +}; diff --git a/samltest/samltest.vcproj b/samltest/samltest.vcproj index 0771976..e3eb662 100644 --- a/samltest/samltest.vcproj +++ b/samltest/samltest.vcproj @@ -179,6 +179,22 @@ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + + + + + + + @@ -517,6 +533,94 @@ > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +