Update gitignore to account for subdirs / missing files.
[shibboleth/cpp-opensaml.git] / samltest / encryption / EncryptedAssertionTest.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 "signature/SAMLSignatureTestBase.h"
22
23 #include <fstream>
24 #include <sstream>
25 #include <saml/SAMLConfig.h>
26 #include <saml/saml2/core/Assertions.h>
27 #include <saml/saml2/metadata/Metadata.h>
28 #include <saml/saml2/metadata/MetadataProvider.h>
29 #include <saml/saml2/metadata/MetadataCredentialContext.h>
30 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
31 #include <xmltooling/security/Credential.h>
32 #include <xsec/dsig/DSIGConstants.hpp>
33
34 using namespace opensaml::saml2md;
35 using namespace opensaml::saml2;
36
37 class EncryptedAssertionTest : public CxxTest::TestSuite, public SAMLSignatureTestBase {
38     MetadataProvider* m_metadata;
39 public:
40     void setUp() {
41         childElementsFile  = data_path + "signature/SAML2Assertion.xml";
42         SAMLSignatureTestBase::setUp();
43         
44         string config = data_path + "binding/ExampleMetadataProvider.xml";
45         ifstream in(config.c_str());
46         DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
47         XercesJanitor<DOMDocument> janitor(doc);
48
49         auto_ptr_XMLCh path("path");
50         string s = data_path + "binding/example-metadata.xml";
51         auto_ptr_XMLCh file(s.c_str());
52         doc->getDocumentElement()->setAttributeNS(nullptr,path.get(),file.get());
53
54         m_metadata = opensaml::SAMLConfig::getConfig().MetadataProviderManager.newPlugin(
55             XML_METADATA_PROVIDER,doc->getDocumentElement()
56             );
57         m_metadata->init();
58     }
59
60     void tearDown() {
61         delete m_metadata;
62         m_metadata=nullptr;
63         SAMLSignatureTestBase::tearDown();
64     }
65
66     void testEncryptedAssertion() {
67         auto_ptr_XMLCh issuer("issuer");
68         auto_ptr_XMLCh issueInstant("1970-01-02T01:01:02.100Z");
69         auto_ptr_XMLCh id("ident");
70         auto_ptr_XMLCh method("method");
71         auto_ptr_XMLCh nameid("John Doe");
72         
73         Issuer* is=IssuerBuilder::buildIssuer();
74         is->setName(issuer.get());
75
76         NameID* n=NameIDBuilder::buildNameID();
77         n->setName(nameid.get());        
78         Subject* subject=SubjectBuilder::buildSubject();
79         subject->setNameID(n);
80
81         AuthnStatement* statement=AuthnStatementBuilder::buildAuthnStatement();
82         statement->setAuthnInstant(issueInstant.get());
83
84         AuthnContext* ac=AuthnContextBuilder::buildAuthnContext();
85         AuthnContextClassRef* acc=AuthnContextClassRefBuilder::buildAuthnContextClassRef();
86         acc->setReference(method.get());
87         ac->setAuthnContextClassRef(acc);
88         statement->setAuthnContext(ac);
89         
90         auto_ptr<Assertion> assertion(AssertionBuilder::buildAssertion());
91         assertion->setID(id.get());
92         assertion->setIssueInstant(issueInstant.get());
93         assertion->setIssuer(is);
94         assertion->setSubject(subject);
95         assertion->getAuthnStatements().push_back(statement);
96
97         // Append a Signature.
98         Signature* sig=SignatureBuilder::buildSignature();
99         assertion->setSignature(sig);
100
101         // Sign while marshalling.
102         vector<Signature*> sigs(1,sig);
103         CredentialCriteria cc;
104         cc.setUsage(Credential::SIGNING_CREDENTIAL);
105         Locker locker(m_resolver);
106         const Credential* cred = m_resolver->resolve(&cc);
107         TSM_ASSERT("Retrieved credential was null", cred!=nullptr);
108
109         DOMElement* rootElement = nullptr;
110         try {
111             rootElement=assertion->marshall((DOMDocument*)nullptr,&sigs,cred);
112         }
113         catch (XMLToolingException& e) {
114             TS_TRACE(e.what());
115             throw;
116         }
117         
118         // Now encrypt this puppy to the SP role in the example metadata.
119         auto_ptr<EncryptedAssertion> encrypted(EncryptedAssertionBuilder::buildEncryptedAssertion());
120         Locker mlocker(m_metadata);
121         MetadataProvider::Criteria mc("https://sp.example.org/", &SPSSODescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS);
122         pair<const EntityDescriptor*,const RoleDescriptor*> sp = m_metadata->getEntityDescriptor(mc);
123         TSM_ASSERT("No metadata for recipient.", sp.first!=nullptr); 
124         TSM_ASSERT("No SP role for recipient.", sp.second!=nullptr);
125         MetadataCredentialCriteria mcc(*sp.second);
126         vector< pair<const MetadataProvider*,MetadataCredentialCriteria*> > recipients(
127             1, pair<const MetadataProvider*,MetadataCredentialCriteria*>(m_metadata, &mcc)
128             );
129 #ifdef XSEC_OPENSSL_HAVE_GCM
130         encrypted->encrypt(*assertion.get(), recipients, false, DSIGConstants::s_unicodeStrURIAES256_GCM);
131 #else
132         encrypted->encrypt(*assertion.get(), recipients);
133 #endif
134
135         // Roundtrip it.
136         string buf;
137         XMLHelper::serialize(encrypted->marshall(), buf);
138         //TS_TRACE(buf.c_str());
139         istringstream in(buf);
140         DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
141         const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
142         
143         // Unpack, then decypt with our key.
144         auto_ptr<EncryptedAssertion> encrypted2(dynamic_cast<EncryptedAssertion*>(b->buildFromDocument(doc)));
145         auto_ptr<Assertion> assertion2(dynamic_cast<Assertion*>(encrypted2->decrypt(*m_resolver, sp.first->getEntityID())));
146         assertEquals("Unmarshalled assertion does not match", expectedChildElementsDOM, assertion2.get(), false);
147         
148         // And check the signature.
149         try {
150             opensaml::SignatureProfileValidator spv;
151             SignatureValidator sv(cred);
152             spv.validate(dynamic_cast<Assertion*>(assertion2.get())->getSignature());
153             sv.validate(dynamic_cast<Assertion*>(assertion2.get())->getSignature());
154         }
155         catch (XMLToolingException& e) {
156             TS_TRACE(e.what());
157             throw;
158         }
159     }
160
161 };