9c39c47675d6964f6b83879feb32ce6e436848f0
[shibboleth/cpp-opensaml.git] / samltest / saml1 / binding / SAML1ArtifactTest.h
1 /*\r
2  *  Copyright 2001-2007 Internet2\r
3  * \r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *     http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 #include "binding.h"\r
18 \r
19 #include <saml/binding/ArtifactMap.h>\r
20 #include <saml/saml1/core/Assertions.h>\r
21 #include <saml/saml1/core/Protocols.h>\r
22 #include <saml/saml1/binding/SAMLArtifactType0001.h>\r
23 #include <xmltooling/validation/ValidatorSuite.h>\r
24 \r
25 using namespace opensaml::saml1p;\r
26 using namespace opensaml::saml1;\r
27 \r
28 namespace {\r
29     class SAML_DLLLOCAL _addcert : public binary_function<X509Data*,XSECCryptoX509*,void> {\r
30     public:\r
31         void operator()(X509Data* bag, XSECCryptoX509* cert) const {\r
32             safeBuffer& buf=cert->getDEREncodingSB();\r
33             X509Certificate* x=X509CertificateBuilder::buildX509Certificate();\r
34             x->setValue(buf.sbStrToXMLCh());\r
35             bag->getX509Certificates().push_back(x);\r
36         }\r
37     };\r
38 };\r
39 \r
40 class SAML1ArtifactTest : public CxxTest::TestSuite,\r
41         public SAMLBindingBaseTestCase, public MessageEncoder::ArtifactGenerator, public MessageDecoder::ArtifactResolver {\r
42 public:\r
43     void setUp() {\r
44         SAMLBindingBaseTestCase::setUp();\r
45     }\r
46 \r
47     void tearDown() {\r
48         SAMLBindingBaseTestCase::tearDown();\r
49     }\r
50 \r
51     void testSAML1Artifact() {\r
52         try {\r
53             QName idprole(samlconstants::SAML20MD_NS, IDPSSODescriptor::LOCAL_NAME);\r
54             SecurityPolicy policy(m_rules1, m_metadata, &idprole, m_trust, false);\r
55 \r
56             // Read message to use from file.\r
57             string path = data_path + "saml1/binding/SAML1Assertion.xml";\r
58             ifstream in(path.c_str());\r
59             DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);\r
60             XercesJanitor<DOMDocument> janitor(doc);\r
61             auto_ptr<saml1::Assertion> toSend(\r
62                 dynamic_cast<saml1::Assertion*>(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(),true))\r
63                 );\r
64             janitor.release();\r
65 \r
66             // Encode message.\r
67             auto_ptr<MessageEncoder> encoder(\r
68                 SAMLConfig::getConfig().MessageEncoderManager.newPlugin(samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT, NULL)\r
69                 );\r
70             encoder->setArtifactGenerator(this);\r
71             encoder->encode(*this,toSend.get(),"https://sp.example.org/SAML/SSO","https://sp.example.org/","state",m_creds);\r
72             toSend.release();\r
73             \r
74             // Decode message.\r
75             string relayState;\r
76             auto_ptr<MessageDecoder> decoder(\r
77                 SAMLConfig::getConfig().MessageDecoderManager.newPlugin(samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT, NULL)\r
78                 );\r
79             decoder->setArtifactResolver(this);\r
80             Locker locker(m_metadata);\r
81             auto_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState,*this,policy)));\r
82             \r
83             // Test the results.\r
84             TSM_ASSERT_EQUALS("TARGET was not the expected result.", relayState, "state");\r
85             TSM_ASSERT("SAML Response not decoded successfully.", response.get());\r
86             TSM_ASSERT("Message was not verified.", policy.isSecure());\r
87             auto_ptr_char entityID(policy.getIssuer()->getName());\r
88             TSM_ASSERT("Issuer was not expected.", !strcmp(entityID.get(),"https://idp.example.org/"));\r
89             TSM_ASSERT_EQUALS("Assertion count was not correct.", response->getAssertions().size(), 1);\r
90 \r
91             // Trigger a replay.\r
92             policy.reset();\r
93             TSM_ASSERT_THROWS("Did not catch the replay.", decoder->decode(relayState,*this,policy), BindingException);\r
94         }\r
95         catch (XMLToolingException& ex) {\r
96             TS_TRACE(ex.what());\r
97             throw;\r
98         }\r
99     }\r
100 \r
101     SAMLArtifact* generateSAML1Artifact(const char* relyingParty) const {\r
102         return new SAMLArtifactType0001(SAMLConfig::getConfig().hashSHA1("https://idp.example.org/"));\r
103     }\r
104     \r
105     saml2p::SAML2Artifact* generateSAML2Artifact(const char* relyingParty) const {\r
106         throw BindingException("Not implemented.");\r
107     }\r
108     \r
109     Signature* buildSignature(const CredentialResolver* credResolver) const\r
110     {\r
111         // Build a Signature.\r
112         Signature* sig = SignatureBuilder::buildSignature();\r
113         sig->setSigningKey(credResolver->getKey());\r
114 \r
115         // Build KeyInfo.\r
116         const vector<XSECCryptoX509*>& certs = credResolver->getCertificates();\r
117         if (!certs.empty()) {\r
118             KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo();\r
119             X509Data* x509Data=X509DataBuilder::buildX509Data();\r
120             keyInfo->getX509Datas().push_back(x509Data);\r
121             for_each(certs.begin(),certs.end(),bind1st(_addcert(),x509Data));\r
122             sig->setKeyInfo(keyInfo);\r
123         }\r
124         \r
125         return sig;\r
126     }\r
127 \r
128     Response* resolve(\r
129         const vector<SAMLArtifact*>& artifacts,\r
130         const IDPSSODescriptor& idpDescriptor,\r
131         SecurityPolicy& policy\r
132         ) const {\r
133         TSM_ASSERT_EQUALS("Too many artifacts.", artifacts.size(), 1);\r
134         XMLObject* xmlObject =\r
135             SAMLConfig::getConfig().getArtifactMap()->retrieveContent(artifacts.front(), "https://sp.example.org/");\r
136         saml1::Assertion* assertion = dynamic_cast<saml1::Assertion*>(xmlObject);\r
137         TSM_ASSERT("Not an assertion.", assertion!=NULL);\r
138         auto_ptr<Response> response(ResponseBuilder::buildResponse());\r
139         response->getAssertions().push_back(assertion);\r
140         Status* status = StatusBuilder::buildStatus();\r
141         response->setStatus(status);\r
142         StatusCode* sc = StatusCodeBuilder::buildStatusCode();\r
143         status->setStatusCode(sc);\r
144         sc->setValue(&StatusCode::SUCCESS);\r
145         response->setSignature(buildSignature(m_creds));\r
146         vector<Signature*> sigs(1,response->getSignature());\r
147         response->marshall((DOMDocument*)NULL,&sigs);\r
148         SchemaValidators.validate(response.get());\r
149         policy.evaluate(*(response.get()), this);\r
150         return response.release();\r
151     }\r
152 \r
153     saml2p::ArtifactResponse* resolve(\r
154         const saml2p::SAML2Artifact& artifact,\r
155         const SSODescriptorType& ssoDescriptor,\r
156         SecurityPolicy& policy\r
157         ) const {\r
158         throw BindingException("Not implemented.");\r
159     }\r
160 };\r