Fix test case reference to Status
[shibboleth/cpp-opensaml.git] / samltest / saml1 / binding / SAML1ArtifactTest.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/saml1/core/Assertions.h>
25 #include <saml/saml1/core/Protocols.h>
26 #include <saml/saml1/binding/SAMLArtifactType0001.h>
27 #include <xmltooling/security/SecurityHelper.h>
28 #include <xmltooling/signature/Signature.h>
29 #include <xmltooling/validation/ValidatorSuite.h>
30
31 using namespace opensaml::saml1p;
32 using namespace opensaml::saml1;
33
34 class SAML1ArtifactTest : public CxxTest::TestSuite,
35         public SAMLBindingBaseTestCase, public MessageEncoder::ArtifactGenerator, public MessageDecoder::ArtifactResolver {
36 public:
37     void setUp() {
38         SAMLBindingBaseTestCase::setUp();
39     }
40
41     void tearDown() {
42         SAMLBindingBaseTestCase::tearDown();
43     }
44
45     void testSAML1Artifact() {
46         try {
47             xmltooling::QName idprole(samlconstants::SAML20MD_NS, IDPSSODescriptor::LOCAL_NAME);
48             SecurityPolicy policy(m_metadata, &idprole, m_trust, false);
49             policy.getRules().assign(m_rules.begin(), m_rules.end());
50
51             // Read message to use from file.
52             string path = data_path + "saml1/binding/SAML1Assertion.xml";
53             ifstream in(path.c_str());
54             DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
55             XercesJanitor<DOMDocument> janitor(doc);
56             auto_ptr<saml1::Assertion> toSend(
57                 dynamic_cast<saml1::Assertion*>(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(),true))
58                 );
59             janitor.release();
60
61             CredentialCriteria cc;
62             cc.setUsage(Credential::SIGNING_CREDENTIAL);
63             Locker clocker(m_creds);
64             const Credential* cred = m_creds->resolve(&cc);
65             TSM_ASSERT("Retrieved credential was null", cred!=nullptr);
66
67             // Encode message.
68             auto_ptr<MessageEncoder> encoder(
69                 SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
70                     samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT, pair<const DOMElement*,const XMLCh*>(nullptr,nullptr)
71                     )
72                 );
73             Locker locker(m_metadata);
74             encoder->encode(
75                 *this,
76                 toSend.get(),
77                 "https://sp.example.org/SAML/SSO",
78                 m_metadata->getEntityDescriptor(MetadataProvider::Criteria("https://sp.example.org/")).first,
79                 "state",
80                 this,
81                 cred
82                 );
83             toSend.release();
84             
85             // Decode message.
86             string relayState;
87             auto_ptr<MessageDecoder> decoder(
88                 SAMLConfig::getConfig().MessageDecoderManager.newPlugin(
89                     samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT, pair<const DOMElement*,const XMLCh*>(nullptr,nullptr)
90                     )
91                 );
92             decoder->setArtifactResolver(this);
93             auto_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState,*this,policy)));
94             
95             // Test the results.
96             TSM_ASSERT_EQUALS("TARGET was not the expected result.", relayState, "state");
97             TSM_ASSERT("SAML Response not decoded successfully.", response.get());
98             TSM_ASSERT("Message was not verified.", policy.isAuthenticated());
99             auto_ptr_char entityID(policy.getIssuer()->getName());
100             TSM_ASSERT("Issuer was not expected.", !strcmp(entityID.get(),"https://idp.example.org/"));
101             TSM_ASSERT_EQUALS("Assertion count was not correct.", response->getAssertions().size(), 1);
102
103             // Trigger a replay.
104             policy.reset();
105             TSM_ASSERT_THROWS("Did not catch the replay.", decoder->decode(relayState,*this,policy), BindingException);
106         }
107         catch (XMLToolingException& ex) {
108             TS_TRACE(ex.what());
109             throw;
110         }
111     }
112
113     SAMLArtifact* generateSAML1Artifact(const EntityDescriptor* relyingParty) const {
114         static const char* providerIdStr = "https://idp.example.org/";
115         return new SAMLArtifactType0001(
116             SecurityHelper::doHash("SHA1", providerIdStr, strlen(providerIdStr), false)
117         );
118     }
119     
120     saml2p::SAML2Artifact* generateSAML2Artifact(const EntityDescriptor* relyingParty) const {
121         throw BindingException("Not implemented.");
122     }
123     
124     Response* resolve(
125         const vector<SAMLArtifact*>& artifacts,
126         const IDPSSODescriptor& idpDescriptor,
127         SecurityPolicy& policy
128         ) const {
129         TSM_ASSERT_EQUALS("Too many artifacts.", artifacts.size(), 1);
130         XMLObject* xmlObject =
131             SAMLConfig::getConfig().getArtifactMap()->retrieveContent(artifacts.front(), "https://sp.example.org/");
132         saml1::Assertion* assertion = dynamic_cast<saml1::Assertion*>(xmlObject);
133         TSM_ASSERT("Not an assertion.", assertion!=nullptr);
134         auto_ptr<Response> response(ResponseBuilder::buildResponse());
135         response->getAssertions().push_back(assertion);
136         saml1p::Status* status = StatusBuilder::buildStatus();
137         response->setStatus(status);
138         StatusCode* sc = StatusCodeBuilder::buildStatusCode();
139         status->setStatusCode(sc);
140         sc->setValue(&StatusCode::SUCCESS);
141         response->setSignature(SignatureBuilder::buildSignature());
142         vector<Signature*> sigs(1,response->getSignature());
143         CredentialCriteria cc;
144         cc.setUsage(Credential::SIGNING_CREDENTIAL);
145         Locker clocker(m_creds);
146         const Credential* cred = m_creds->resolve(&cc);
147         TSM_ASSERT("Retrieved credential was null", cred!=nullptr);
148         response->marshall((DOMDocument*)nullptr,&sigs,cred);
149         SchemaValidators.validate(response.get());
150         policy.evaluate(*(response.get()), this);
151         return response.release();
152     }
153
154     saml2p::ArtifactResponse* resolve(
155         const saml2p::SAML2Artifact& artifact,
156         const SSODescriptorType& ssoDescriptor,
157         SecurityPolicy& policy
158         ) const {
159         throw BindingException("Not implemented.");
160     }
161 };