Changed "virtual" URL to match between bindings.
[shibboleth/cpp-opensaml.git] / samltest / saml1 / binding / SAML1ArtifactTest.h
1 /*\r
2  *  Copyright 2001-2005 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_rules, m_metadata, &idprole, m_trust);\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<Assertion> toSend(\r
62                 dynamic_cast<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.getIssuer()!=NULL);\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             TSM_ASSERT_THROWS("Did not catch the replay.", decoder->decode(relayState,*this,policy), BindingException);\r
93         }\r
94         catch (XMLToolingException& ex) {\r
95             TS_TRACE(ex.what());\r
96             throw;\r
97         }\r
98     }\r
99 \r
100     SAMLArtifact* generateSAML1Artifact(const char* relyingParty) const {\r
101         return new SAMLArtifactType0001(SAMLConfig::getConfig().hashSHA1("https://idp.example.org/"));\r
102     }\r
103     \r
104     saml2p::SAML2Artifact* generateSAML2Artifact(const char* relyingParty) const {\r
105         throw BindingException("Not implemented.");\r
106     }\r
107     \r
108     Signature* buildSignature(const CredentialResolver* credResolver) const\r
109     {\r
110         // Build a Signature.\r
111         Signature* sig = SignatureBuilder::buildSignature();\r
112         sig->setSigningKey(credResolver->getKey());\r
113 \r
114         // Build KeyInfo.\r
115         const vector<XSECCryptoX509*>& certs = credResolver->getCertificates();\r
116         if (!certs.empty()) {\r
117             KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo();\r
118             X509Data* x509Data=X509DataBuilder::buildX509Data();\r
119             keyInfo->getX509Datas().push_back(x509Data);\r
120             for_each(certs.begin(),certs.end(),bind1st(_addcert(),x509Data));\r
121             sig->setKeyInfo(keyInfo);\r
122         }\r
123         \r
124         return sig;\r
125     }\r
126 \r
127     Response* resolve(\r
128         const vector<SAMLArtifact*>& artifacts,\r
129         const IDPSSODescriptor& idpDescriptor,\r
130         SecurityPolicy& policy\r
131         ) const {\r
132         TSM_ASSERT_EQUALS("Too many artifacts.", artifacts.size(), 1);\r
133         XMLObject* xmlObject =\r
134             SAMLConfig::getConfig().getArtifactMap()->retrieveContent(artifacts.front(), "https://sp.example.org/");\r
135         Assertion* assertion = dynamic_cast<Assertion*>(xmlObject);\r
136         TSM_ASSERT("Not an assertion.", assertion!=NULL);\r
137         auto_ptr<Response> response(ResponseBuilder::buildResponse());\r
138         response->getAssertions().push_back(assertion);\r
139         Status* status = StatusBuilder::buildStatus();\r
140         response->setStatus(status);\r
141         StatusCode* sc = StatusCodeBuilder::buildStatusCode();\r
142         status->setStatusCode(sc);\r
143         sc->setValue(&StatusCode::SUCCESS);\r
144         response->setSignature(buildSignature(m_creds));\r
145         vector<Signature*> sigs(1,response->getSignature());\r
146         response->marshall((DOMDocument*)NULL,&sigs);\r
147         SchemaValidators.validate(response.get());\r
148         return response.release();\r
149     }\r
150 \r
151     saml2p::ArtifactResponse* resolve(\r
152         const saml2p::SAML2Artifact& artifact,\r
153         const SSODescriptorType& ssoDescriptor,\r
154         SecurityPolicy& policy\r
155         ) const {\r
156         throw BindingException("Not implemented.");\r
157     }\r
158 };\r