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