Multi-line svn commit, see body.
[shibboleth/cpp-opensaml.git] / samltest / saml2 / binding / SAML2ArtifactTest.h
1 /*
2  *  Copyright 2001-2007 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         SAMLBindingBaseTestCase::setUp();
32     }
33
34     void tearDown() {
35         SAMLBindingBaseTestCase::tearDown();
36     }
37
38     void testSAML2Artifact() {
39         try {
40             QName idprole(samlconstants::SAML20MD_NS, IDPSSODescriptor::LOCAL_NAME);
41             SecurityPolicy policy(m_metadata, &idprole, m_trust, false);
42             policy.getRules().assign(m_rules.begin(), m_rules.end());
43
44             // Read message to use from file.
45             string path = data_path + "saml2/binding/SAML2Response.xml";
46             ifstream in(path.c_str());
47             DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
48             XercesJanitor<DOMDocument> janitor(doc);
49             auto_ptr<Response> toSend(
50                 dynamic_cast<Response*>(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(),true))
51                 );
52             janitor.release();
53
54             CredentialCriteria cc;
55             cc.setUsage(Credential::SIGNING_CREDENTIAL);
56             Locker clocker(m_creds);
57             const Credential* cred = m_creds->resolve(&cc);
58             TSM_ASSERT("Retrieved credential was null", cred!=NULL);
59
60             // Freshen timestamp.
61             toSend->setIssueInstant(time(NULL));
62
63             // Encode message.
64             auto_ptr<MessageEncoder> encoder(
65                 SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
66                     samlconstants::SAML20_BINDING_HTTP_ARTIFACT, pair<const DOMElement*,const XMLCh*>(NULL,NULL)
67                     )
68                 );
69             Locker locker(m_metadata);
70             encoder->encode(
71                 *this,toSend.get(),"https://sp.example.org/SAML/SSO",m_metadata->getEntityDescriptor("https://sp.example.org/"),"state",this,cred
72                 );
73             toSend.release();
74             
75             // Decode message.
76             string relayState;
77             auto_ptr<MessageDecoder> decoder(
78                 SAMLConfig::getConfig().MessageDecoderManager.newPlugin(
79                     samlconstants::SAML20_BINDING_HTTP_ARTIFACT, pair<const DOMElement*,const XMLCh*>(NULL,NULL)
80                     )
81                 );
82             decoder->setArtifactResolver(this);
83             auto_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState,*this,policy)));
84             
85             // Test the results.
86             TSM_ASSERT_EQUALS("RelayState was not the expected result.", relayState, "state");
87             TSM_ASSERT("SAML Response not decoded successfully.", response.get());
88             TSM_ASSERT("Message was not verified.", policy.isAuthenticated());
89             auto_ptr_char entityID(policy.getIssuer()->getName());
90             TSM_ASSERT("Issuer was not expected.", !strcmp(entityID.get(),"https://idp.example.org/"));
91             TSM_ASSERT_EQUALS("Assertion count was not correct.", response->getAssertions().size(), 1);
92
93             // Trigger a replay.
94             policy.reset();
95             TSM_ASSERT_THROWS("Did not catch the replay.", decoder->decode(relayState,*this,policy), BindingException);
96         }
97         catch (XMLToolingException& ex) {
98             TS_TRACE(ex.what());
99             throw;
100         }
101     }
102     
103     SAMLArtifact* generateSAML1Artifact(const EntityDescriptor* relyingParty) const {
104         throw BindingException("Not implemented.");
105     }
106     
107     saml2p::SAML2Artifact* generateSAML2Artifact(const EntityDescriptor* relyingParty) const {
108         return new SAML2ArtifactType0004(SAMLConfig::getConfig().hashSHA1("https://idp.example.org/"),1);
109     }
110     
111     saml1p::Response* resolve(
112         const vector<SAMLArtifact*>& artifacts,
113         const IDPSSODescriptor& idpDescriptor,
114         SecurityPolicy& policy
115         ) const {
116         throw BindingException("Not implemented.");
117     }
118
119     ArtifactResponse* resolve(
120         const SAML2Artifact& artifact,
121         const SSODescriptorType& ssoDescriptor,
122         SecurityPolicy& policy
123         ) const {
124         XMLObject* xmlObject =
125             SAMLConfig::getConfig().getArtifactMap()->retrieveContent(&artifact, "https://sp.example.org/");
126         Response* payload = dynamic_cast<Response*>(xmlObject);
127         TSM_ASSERT("Not a response.", payload!=NULL);
128
129         auto_ptr<ArtifactResponse> response(ArtifactResponseBuilder::buildArtifactResponse());
130         response->setPayload(payload);
131         Status* status = StatusBuilder::buildStatus();
132         response->setStatus(status);
133         StatusCode* sc = StatusCodeBuilder::buildStatusCode();
134         status->setStatusCode(sc);
135         sc->setValue(StatusCode::SUCCESS);
136         response->marshall();
137         SchemaValidators.validate(response.get());
138         policy.evaluate(*(response.get()), this);
139         return response.release();
140     }
141 };