First cut at signing support.
[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 <fstream>\r
20 #include <openssl/pem.h>\r
21 #include <xercesc/util/XMLUniDefs.hpp>\r
22 #include <xsec/dsig/DSIGReference.hpp>\r
23 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>\r
24 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>\r
25 \r
26 class TestContext : public SigningContext\r
27 {\r
28     XSECCryptoKey* m_key;\r
29     vector<XSECCryptoX509*> m_certs;\r
30     XMLCh* m_uri;\r
31     \r
32 public:\r
33     TestContext(const XMLCh* uri) {\r
34         string keypath=data_path + "key.pem";\r
35         BIO* in=BIO_new(BIO_s_file_internal());\r
36         if (in && BIO_read_filename(in,keypath.c_str())>0) {\r
37             EVP_PKEY* pkey=PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);\r
38             if (pkey) {\r
39                 m_key=new OpenSSLCryptoKeyRSA(pkey);\r
40                 EVP_PKEY_free(pkey);\r
41             }\r
42         }\r
43         if (in) BIO_free(in);\r
44         TS_ASSERT(m_key!=NULL);\r
45 \r
46         string certpath=data_path + "cert.pem";\r
47         in=BIO_new(BIO_s_file_internal());\r
48         if (in && BIO_read_filename(in,certpath.c_str())>0) {\r
49             X509* x=NULL;\r
50             while (x=PEM_read_bio_X509(in,NULL,NULL,NULL)) {\r
51                 m_certs.push_back(new OpenSSLCryptoX509(x));\r
52                 X509_free(x);\r
53             }\r
54         }\r
55         if (in) BIO_free(in);\r
56         TS_ASSERT(m_certs.size()>0);\r
57         \r
58         m_uri=XMLString::replicate(uri);\r
59     }\r
60     \r
61     virtual ~TestContext() {\r
62         delete m_key;\r
63         for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup<XSECCryptoX509>());\r
64         XMLString::release(&m_uri);\r
65     }\r
66 \r
67     void createSignature(DSIGSignature* sig) const {\r
68         DSIGReference* ref=sig->createReference(m_uri);\r
69         ref->appendEnvelopedSignatureTransform();\r
70         ref->appendCanonicalizationTransform(CANON_C14NE_NOC);\r
71     }\r
72     \r
73     const std::vector<XSECCryptoX509*>& getX509Certificates() const { return m_certs; }\r
74     XSECCryptoKey* getSigningKey() const { return m_key->clone(); }\r
75 };\r
76 \r
77 class SignatureTest : public CxxTest::TestSuite {\r
78     QName m_qname;\r
79 public:\r
80     SignatureTest() : m_qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME) {}\r
81 \r
82     void setUp() {\r
83         XMLObjectBuilder::registerBuilder(m_qname, new SimpleXMLObjectBuilder());\r
84         Marshaller::registerMarshaller(m_qname, new SimpleXMLObjectMarshaller());\r
85         Unmarshaller::registerUnmarshaller(m_qname, new SimpleXMLObjectUnmarshaller());\r
86     }\r
87 \r
88     void tearDown() {\r
89         XMLObjectBuilder::deregisterBuilder(m_qname);\r
90         Marshaller::deregisterMarshaller(m_qname);\r
91         Unmarshaller::deregisterUnmarshaller(m_qname);\r
92     }\r
93 \r
94     void testSignature() {\r
95         TS_TRACE("testSignature");\r
96 \r
97         const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(m_qname);\r
98         TS_ASSERT(b!=NULL);\r
99         \r
100         auto_ptr<SimpleXMLObject> sxObject(dynamic_cast<SimpleXMLObject*>(b->buildObject()));\r
101         TS_ASSERT(sxObject.get()!=NULL);\r
102         VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects();\r
103         kids.push_back(dynamic_cast<SimpleXMLObject*>(b->buildObject()));\r
104         kids.push_back(dynamic_cast<SimpleXMLObject*>(b->buildObject()));\r
105         \r
106         // Test some collection stuff\r
107         auto_ptr_XMLCh foo("Foo");\r
108         auto_ptr_XMLCh bar("Bar");\r
109         kids.begin()->setId(foo.get());\r
110         kids[1]->setValue(bar.get());\r
111         \r
112         // Append a Signature.\r
113         Signature* sig=dynamic_cast<Signature*>(XMLObjectBuilder::buildObject(QName(XMLConstants::XMLSIG_NS,Signature::LOCAL_NAME)));\r
114         sxObject->setSignature(sig);\r
115         \r
116         // Signing context for the whole document.\r
117         TestContext tc(&chNull);\r
118         MarshallingContext mctx(sig,&tc);\r
119         DOMElement* rootElement = Marshaller::getMarshaller(sxObject.get())->marshall(sxObject.get(),(DOMDocument*)NULL,&mctx);\r
120         \r
121         string buf;\r
122         XMLHelper::serialize(rootElement, buf);\r
123         TS_TRACE(buf.c_str());\r
124 \r
125         istringstream in(buf);\r
126         DOMDocument* doc=nonvalidatingPool->parse(in);\r
127         const Unmarshaller* u = Unmarshaller::getUnmarshaller(doc->getDocumentElement());\r
128         auto_ptr<SimpleXMLObject> sxObject2(dynamic_cast<SimpleXMLObject*>(u->unmarshall(doc->getDocumentElement(),true)));\r
129         TS_ASSERT(sxObject2.get()!=NULL);\r
130         TS_ASSERT(sxObject2->getSignature()!=NULL);\r
131     }\r
132 \r
133 };\r