Removed ValidatingXMLObject interface and implementations.
[shibboleth/cpp-xmltooling.git] / xmltoolingtest / SignatureTest.h
1 /*\r
2  *  Copyright 2001-2005 Internet2\r
3  * \r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *     http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 #include "XMLObjectBaseTestCase.h"\r
18 \r
19 #include <xmltooling/signature/SignatureValidator.h>\r
20 \r
21 #include <fstream>\r
22 #include <openssl/pem.h>\r
23 #include <xercesc/util/XMLUniDefs.hpp>\r
24 #include <xsec/dsig/DSIGReference.hpp>\r
25 #include <xsec/enc/XSECKeyInfoResolverDefault.hpp>\r
26 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>\r
27 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>\r
28 #include <xsec/enc/XSECCryptoException.hpp>\r
29 #include <xsec/framework/XSECException.hpp>\r
30 \r
31 class TestContext : public ContentReference\r
32 {\r
33     XMLCh* m_uri;\r
34     \r
35 public:\r
36     TestContext(const XMLCh* uri) {\r
37         m_uri=XMLString::replicate(uri);\r
38     }\r
39     \r
40     virtual ~TestContext() {\r
41         XMLString::release(&m_uri);\r
42     }\r
43 \r
44     void createReferences(DSIGSignature* sig) {\r
45         DSIGReference* ref=sig->createReference(m_uri);\r
46         ref->appendEnvelopedSignatureTransform();\r
47         ref->appendCanonicalizationTransform(CANON_C14NE_NOC);\r
48     }\r
49 };\r
50 \r
51 class TestValidator : public SignatureValidator\r
52 {\r
53     XMLCh* m_uri;\r
54     \r
55 public:\r
56     TestValidator(const XMLCh* uri, XSECCryptoKey* key) : SignatureValidator(new KeyResolver(key)) {\r
57         m_uri=XMLString::replicate(uri);\r
58     }\r
59     \r
60     virtual ~TestValidator() {\r
61         XMLString::release(&m_uri);\r
62     }\r
63 \r
64     void validate(const Signature* sigObj) const {\r
65         DSIGSignature* sig=sigObj->getXMLSignature();\r
66         if (!sig)\r
67             throw SignatureException("Only a marshalled Signature object can be verified.");\r
68         const XMLCh* uri=sig->getReferenceList()->item(0)->getURI();\r
69         TSM_ASSERT_SAME_DATA("Reference URI does not match.",uri,m_uri,XMLString::stringLen(uri));\r
70         SignatureValidator::validate(sigObj);\r
71     }\r
72 };\r
73 \r
74 class _addcert : public std::binary_function<X509Data*,XSECCryptoX509*,void> {\r
75 public:\r
76     void operator()(X509Data* bag, XSECCryptoX509* cert) const {\r
77         safeBuffer& buf=cert->getDEREncodingSB();\r
78         X509Certificate* x=X509CertificateBuilder::buildX509Certificate();\r
79         x->setValue(buf.sbStrToXMLCh());\r
80         bag->getX509Certificates().push_back(x);\r
81     }\r
82 };\r
83 \r
84 class SignatureTest : public CxxTest::TestSuite {\r
85     XSECCryptoKey* m_key;\r
86     vector<XSECCryptoX509*> m_certs;\r
87 public:\r
88     void setUp() {\r
89         QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME);\r
90         QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME);\r
91         XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder());\r
92         XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder());\r
93         string keypath=data_path + "key.pem";\r
94         BIO* in=BIO_new(BIO_s_file_internal());\r
95         if (in && BIO_read_filename(in,keypath.c_str())>0) {\r
96             EVP_PKEY* pkey=PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);\r
97             if (pkey) {\r
98                 m_key=new OpenSSLCryptoKeyRSA(pkey);\r
99                 EVP_PKEY_free(pkey);\r
100             }\r
101         }\r
102         if (in) BIO_free(in);\r
103         TS_ASSERT(m_key!=NULL);\r
104 \r
105         string certpath=data_path + "cert.pem";\r
106         in=BIO_new(BIO_s_file_internal());\r
107         if (in && BIO_read_filename(in,certpath.c_str())>0) {\r
108             X509* x=NULL;\r
109             while (x=PEM_read_bio_X509(in,NULL,NULL,NULL)) {\r
110                 m_certs.push_back(new OpenSSLCryptoX509(x));\r
111                 X509_free(x);\r
112             }\r
113         }\r
114         if (in) BIO_free(in);\r
115         TS_ASSERT(m_certs.size()>0);\r
116         \r
117     }\r
118 \r
119     void tearDown() {\r
120         QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME);\r
121         QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME);\r
122         XMLObjectBuilder::deregisterBuilder(qname);\r
123         XMLObjectBuilder::deregisterBuilder(qtype);\r
124         delete m_key;\r
125         for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup<XSECCryptoX509>());\r
126     }\r
127 \r
128     void testSignature() {\r
129         TS_TRACE("testSignature");\r
130 \r
131         QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME);\r
132         const SimpleXMLObjectBuilder* b=dynamic_cast<const SimpleXMLObjectBuilder*>(XMLObjectBuilder::getBuilder(qname));\r
133         TS_ASSERT(b!=NULL);\r
134         \r
135         auto_ptr<SimpleXMLObject> sxObject(b->buildObject());\r
136         TS_ASSERT(sxObject.get()!=NULL);\r
137         VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects();\r
138         kids.push_back(b->buildObject());\r
139         kids.push_back(b->buildObject());\r
140         \r
141         // Test some collection stuff\r
142         auto_ptr_XMLCh foo("Foo");\r
143         auto_ptr_XMLCh bar("Bar");\r
144         kids.begin()->setId(foo.get());\r
145         kids[1]->setValue(bar.get());\r
146         \r
147         // Append a Signature.\r
148         Signature* sig=SignatureBuilder::buildSignature();\r
149         sxObject->setSignature(sig);\r
150         sig->setContentReference(new TestContext(&chNull));\r
151         sig->setSigningKey(m_key->clone());\r
152         \r
153         // Build KeyInfo.\r
154         KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo();\r
155         X509Data* x509Data=X509DataBuilder::buildX509Data();\r
156         keyInfo->getX509Datas().push_back(x509Data);\r
157         for_each(m_certs.begin(),m_certs.end(),bind1st(_addcert(),x509Data));\r
158         sig->setKeyInfo(keyInfo);\r
159         \r
160         // Signing context for the whole document.\r
161         vector<Signature*> sigs(1,sig);\r
162         DOMElement* rootElement = NULL;\r
163         try {\r
164             rootElement=sxObject->marshall((DOMDocument*)NULL,&sigs);\r
165         }\r
166         catch (XMLToolingException& e) {\r
167             TS_TRACE(e.what());\r
168             throw;\r
169         }\r
170         \r
171         string buf;\r
172         XMLHelper::serialize(rootElement, buf);\r
173         //TS_TRACE(buf.c_str());\r
174 \r
175         istringstream in(buf);\r
176         DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);\r
177         auto_ptr<SimpleXMLObject> sxObject2(dynamic_cast<SimpleXMLObject*>(b->buildFromDocument(doc)));\r
178         TS_ASSERT(sxObject2.get()!=NULL);\r
179         TS_ASSERT(sxObject2->getSignature()!=NULL);\r
180         \r
181         try {\r
182             TestValidator tv(&chNull,m_key->clone());\r
183             tv.validate(sxObject2->getSignature());\r
184         }\r
185         catch (XMLToolingException& e) {\r
186             TS_TRACE(e.what());\r
187             throw;\r
188         }\r
189     }\r
190 \r
191 };\r