c785bd34c7e6e1322846e9f8c1f7412f74846a08
[shibboleth/cpp-opensaml.git] / samltest / saml2 / binding / SAML2ArtifactTest.h
1 /*
2  *  Copyright 2001-2005 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "binding.h"
18
19 #include <saml/binding/ArtifactMap.h>
20 #include <saml/saml2/core/Protocols.h>
21 #include <saml/saml2/binding/SAML2ArtifactType0004.h>
22 #include <xmltooling/validation/ValidatorSuite.h>
23
24 using namespace opensaml::saml2p;
25 using namespace opensaml::saml2;
26
27 class SAML2ArtifactTest : public CxxTest::TestSuite,
28     public SAMLBindingBaseTestCase, public MessageEncoder::ArtifactGenerator, public MessageDecoder::ArtifactResolver {
29 public:
30     void setUp() {
31         m_fields.clear();
32         SAMLBindingBaseTestCase::setUp();
33     }
34
35     void tearDown() {
36         m_fields.clear();
37         SAMLBindingBaseTestCase::tearDown();
38     }
39
40     void testSAML2Artifact() {
41         try {
42             // Read message to use from file.
43             string path = data_path + "saml2/binding/SAML2Response.xml";
44             ifstream in(path.c_str());
45             DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
46             XercesJanitor<DOMDocument> janitor(doc);
47             auto_ptr<Response> toSend(
48                 dynamic_cast<Response*>(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(),true))
49                 );
50             janitor.release();
51
52             // Freshen timestamp.
53             toSend->setIssueInstant(time(NULL));
54
55             // Encode message.
56             auto_ptr<MessageEncoder> encoder(
57                 SAMLConfig::getConfig().MessageEncoderManager.newPlugin(SAMLConstants::SAML20_BINDING_HTTP_ARTIFACT, NULL)
58                 );
59             encoder->setArtifactGenerator(this);
60             encoder->encode(m_fields,toSend.get(),"https://sp.example.org/","state",m_creds);
61             toSend.release();
62             
63             // Decode message.
64             string relayState;
65             const RoleDescriptor* issuer=NULL;
66             bool trusted=false;
67             QName idprole(SAMLConstants::SAML20MD_NS, IDPSSODescriptor::LOCAL_NAME);
68             auto_ptr<MessageDecoder> decoder(
69                 SAMLConfig::getConfig().MessageDecoderManager.newPlugin(SAMLConstants::SAML20_BINDING_HTTP_ARTIFACT, NULL)
70                 );
71             decoder->setArtifactResolver(this);
72             Locker locker(m_metadata);
73             auto_ptr<Response> response(
74                 dynamic_cast<Response*>(
75                     decoder->decode(relayState,issuer,trusted,*this,m_metadata,&idprole,m_trust)
76                     )
77                 );
78             
79             // Test the results.
80             TSM_ASSERT_EQUALS("RelayState was not the expected result.", relayState, "state");
81             TSM_ASSERT("SAML Response not decoded successfully.", response.get());
82             TSM_ASSERT("Message was not verified.", issuer && trusted);
83             auto_ptr_char entityID(dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID());
84             TSM_ASSERT("Issuer was not expected.", !strcmp(entityID.get(),"https://idp.example.org/"));
85             TSM_ASSERT_EQUALS("Assertion count was not correct.", response->getAssertions().size(), 1);
86
87             // Trigger a replay.
88             TSM_ASSERT_THROWS("Did not catch the replay.", 
89                 decoder->decode(relayState,issuer,trusted,*this,m_metadata,&idprole,m_trust),
90                 BindingException);
91         }
92         catch (XMLToolingException& ex) {
93             TS_TRACE(ex.what());
94             throw;
95         }
96     }
97
98     const char* getMethod() const {
99         return "GET";
100     } 
101
102     const char* getRequestURL() const {
103         return "https://sp.example.org/SAML/Artifact";
104     }
105     
106     const char* getQueryString() const {
107         return NULL;
108     }
109     
110     SAMLArtifact* generateSAML1Artifact(const char* relyingParty) const {
111         throw BindingException("Not implemented.");
112     }
113     
114     saml2p::SAML2Artifact* generateSAML2Artifact(const char* relyingParty) const {
115         return new SAML2ArtifactType0004(SAMLConfig::getConfig().hashSHA1("https://idp.example.org/"),1);
116     }
117     
118     saml1p::Response* resolve(
119         bool& authenticated,
120         const vector<SAMLArtifact*>& artifacts,
121         const IDPSSODescriptor& idpDescriptor,
122         const X509TrustEngine* trustEngine=NULL
123         ) const {
124         throw BindingException("Not implemented.");
125     }
126
127     ArtifactResponse* resolve(
128         bool& authenticated,
129         const SAML2Artifact& artifact,
130         const SSODescriptorType& ssoDescriptor,
131         const X509TrustEngine* trustEngine=NULL
132         ) const {
133         XMLObject* xmlObject =
134             SAMLConfig::getConfig().getArtifactMap()->retrieveContent(&artifact, "https://sp.example.org/");
135         Response* payload = dynamic_cast<Response*>(xmlObject);
136         TSM_ASSERT("Not a response.", payload!=NULL);
137         auto_ptr<ArtifactResponse> response(ArtifactResponseBuilder::buildArtifactResponse());
138         response->setPayload(payload);
139         Status* status = StatusBuilder::buildStatus();
140         response->setStatus(status);
141         StatusCode* sc = StatusCodeBuilder::buildStatusCode();
142         status->setStatusCode(sc);
143         sc->setValue(StatusCode::SUCCESS);
144         response->marshall();
145         SchemaValidators.validate(response.get());
146         authenticated = true;
147         return response.release();
148     }
149 };