Update copyright.
[shibboleth/cpp-xmltooling.git] / xmltoolingtest / SignatureTest.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 "XMLObjectBaseTestCase.h"
18
19 #include <xmltooling/signature/CredentialResolver.h>
20 #include <xmltooling/signature/KeyInfo.h>
21 #include <xmltooling/signature/SignatureValidator.h>
22
23 #include <fstream>
24 #include <xercesc/util/XMLUniDefs.hpp>
25 #include <xsec/dsig/DSIGReference.hpp>
26
27 class TestContext : public ContentReference
28 {
29     XMLCh* m_uri;
30     
31 public:
32     TestContext(const XMLCh* uri) {
33         m_uri=XMLString::replicate(uri);
34     }
35     
36     virtual ~TestContext() {
37         XMLString::release(&m_uri);
38     }
39
40     void createReferences(DSIGSignature* sig) {
41         DSIGReference* ref=sig->createReference(m_uri);
42         ref->appendEnvelopedSignatureTransform();
43         ref->appendCanonicalizationTransform(CANON_C14NE_NOC);
44     }
45 };
46
47 class TestValidator : public SignatureValidator
48 {
49     XMLCh* m_uri;
50     
51 public:
52     TestValidator(const XMLCh* uri) : SignatureValidator(XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER,NULL)) {
53         m_uri=XMLString::replicate(uri);
54     }
55     
56     virtual ~TestValidator() {
57         XMLString::release(&m_uri);
58     }
59
60     void validate(const Signature* sigObj) const {
61         DSIGSignature* sig=sigObj->getXMLSignature();
62         if (!sig)
63             throw SignatureException("Only a marshalled Signature object can be verified.");
64         const XMLCh* uri=sig->getReferenceList()->item(0)->getURI();
65         TSM_ASSERT_SAME_DATA("Reference URI does not match.",uri,m_uri,XMLString::stringLen(uri));
66         SignatureValidator::validate(sigObj);
67     }
68 };
69
70 class _addcert : public std::binary_function<X509Data*,XSECCryptoX509*,void> {
71 public:
72     void operator()(X509Data* bag, XSECCryptoX509* cert) const {
73         safeBuffer& buf=cert->getDEREncodingSB();
74         X509Certificate* x=X509CertificateBuilder::buildX509Certificate();
75         x->setValue(buf.sbStrToXMLCh());
76         bag->getX509Certificates().push_back(x);
77     }
78 };
79
80 class SignatureTest : public CxxTest::TestSuite {
81     CredentialResolver* m_resolver;
82 public:
83     void setUp() {
84         m_resolver=NULL;
85         QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME);
86         QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME);
87         XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder());
88         XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder());
89
90         string config = data_path + "FilesystemCredentialResolver.xml";
91         ifstream in(config.c_str());
92         DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
93         XercesJanitor<DOMDocument> janitor(doc);
94         m_resolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(
95             FILESYSTEM_CREDENTIAL_RESOLVER,doc->getDocumentElement()
96             );
97     }
98
99     void tearDown() {
100         QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME);
101         QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME);
102         XMLObjectBuilder::deregisterBuilder(qname);
103         XMLObjectBuilder::deregisterBuilder(qtype);
104         delete m_resolver;
105     }
106
107     void testSignature() {
108         QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME);
109         const SimpleXMLObjectBuilder* b=dynamic_cast<const SimpleXMLObjectBuilder*>(XMLObjectBuilder::getBuilder(qname));
110         TS_ASSERT(b!=NULL);
111         
112         auto_ptr<SimpleXMLObject> sxObject(dynamic_cast<SimpleXMLObject*>(b->buildObject()));
113         TS_ASSERT(sxObject.get()!=NULL);
114         VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects();
115         kids.push_back(dynamic_cast<SimpleXMLObject*>(b->buildObject()));
116         kids.push_back(dynamic_cast<SimpleXMLObject*>(b->buildObject()));
117         
118         // Test some collection stuff
119         auto_ptr_XMLCh foo("Foo");
120         auto_ptr_XMLCh bar("Bar");
121         kids.begin()->setId(foo.get());
122         kids[1]->setValue(bar.get());
123         
124         // Append a Signature.
125         Signature* sig=SignatureBuilder::buildSignature();
126         sxObject->setSignature(sig);
127         sig->setContentReference(new TestContext(&chNull));
128
129         Locker locker(m_resolver);
130         sig->setSigningKey(m_resolver->getKey());
131         
132         // Build KeyInfo.
133         KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo();
134         X509Data* x509Data=X509DataBuilder::buildX509Data();
135         keyInfo->getX509Datas().push_back(x509Data);
136         for_each(m_resolver->getCertificates().begin(),m_resolver->getCertificates().end(),bind1st(_addcert(),x509Data));
137         sig->setKeyInfo(keyInfo);
138         
139         DOMElement* rootElement = NULL;
140         try {
141             rootElement=sxObject->marshall((DOMDocument*)NULL);
142             sig->sign();
143         }
144         catch (XMLToolingException& e) {
145             TS_TRACE(e.what());
146             throw;
147         }
148         
149         string buf;
150         XMLHelper::serialize(rootElement, buf);
151         //TS_TRACE(buf.c_str());
152
153         istringstream in(buf);
154         DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
155         auto_ptr<SimpleXMLObject> sxObject2(dynamic_cast<SimpleXMLObject*>(b->buildFromDocument(doc)));
156         TS_ASSERT(sxObject2.get()!=NULL);
157         TS_ASSERT(sxObject2->getSignature()!=NULL);
158         
159         try {
160             TestValidator tv(&chNull);
161             tv.validate(sxObject2->getSignature());
162         }
163         catch (XMLToolingException& e) {
164             TS_TRACE(e.what());
165             throw;
166         }
167     }
168
169 };