89e679ae162e0f3e5d6070dc4c865e28846d4f33
[shibboleth/cpp-opensaml.git] / samltest / signature / SAML1ResponseTest.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 "internal.h"\r
18 #include <saml/saml1/core/Protocols.h>\r
19 #include <saml/signature/SignatureProfileValidator.h>\r
20 #include <xmltooling/signature/SignatureValidator.h>\r
21 \r
22 #include <fstream>\r
23 #include <openssl/pem.h>\r
24 #include <xercesc/util/XMLUniDefs.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 using namespace opensaml::saml1;\r
32 using namespace xmlsignature;\r
33 \r
34 class _addcert : public std::binary_function<X509Data*,XSECCryptoX509*,void> {\r
35 public:\r
36     void operator()(X509Data* bag, XSECCryptoX509* cert) const {\r
37         safeBuffer& buf=cert->getDEREncodingSB();\r
38         X509Certificate* x=X509CertificateBuilder::buildX509Certificate();\r
39         x->setValue(buf.sbStrToXMLCh());\r
40         bag->getX509Certificates().push_back(x);\r
41     }\r
42 };\r
43 \r
44 class SAML1ResponseTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase {\r
45     XSECCryptoKey* m_key;\r
46     vector<XSECCryptoX509*> m_certs;\r
47 public:\r
48     void setUp() {\r
49         childElementsFile  = data_path + "signature/SAML1Response.xml";\r
50         SAMLObjectBaseTestCase::setUp();\r
51         string keypath=data_path + "key.pem";\r
52         BIO* in=BIO_new(BIO_s_file_internal());\r
53         if (in && BIO_read_filename(in,keypath.c_str())>0) {\r
54             EVP_PKEY* pkey=PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);\r
55             if (pkey) {\r
56                 m_key=new OpenSSLCryptoKeyRSA(pkey);\r
57                 EVP_PKEY_free(pkey);\r
58             }\r
59         }\r
60         if (in) BIO_free(in);\r
61         TS_ASSERT(m_key!=NULL);\r
62 \r
63         string certpath=data_path + "cert.pem";\r
64         in=BIO_new(BIO_s_file_internal());\r
65         if (in && BIO_read_filename(in,certpath.c_str())>0) {\r
66             X509* x=NULL;\r
67             while (x=PEM_read_bio_X509(in,NULL,NULL,NULL)) {\r
68                 m_certs.push_back(new OpenSSLCryptoX509(x));\r
69                 X509_free(x);\r
70             }\r
71         }\r
72         if (in) BIO_free(in);\r
73         TS_ASSERT(m_certs.size()>0);\r
74     }\r
75 \r
76     void tearDown() {\r
77         SAMLObjectBaseTestCase::tearDown();\r
78         delete m_key;\r
79         for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup<XSECCryptoX509>());\r
80     }\r
81 \r
82     void testSignature() {\r
83         auto_ptr_XMLCh issuer("issuer");\r
84         auto_ptr_XMLCh issueInstant("1970-01-02T01:01:02.100Z");\r
85         auto_ptr_XMLCh aid("aident");\r
86         auto_ptr_XMLCh rid("rident");\r
87         auto_ptr_XMLCh method("method");\r
88         auto_ptr_XMLCh nameid("John Doe");\r
89         \r
90         NameIdentifier* n=NameIdentifierBuilder::buildNameIdentifier();\r
91         n->setName(nameid.get());        \r
92         Subject* subject=SubjectBuilder::buildSubject();\r
93         subject->setNameIdentifier(n);\r
94 \r
95         AuthenticationStatement* statement=AuthenticationStatementBuilder::buildAuthenticationStatement();\r
96         statement->setAuthenticationInstant(issueInstant.get());\r
97         statement->setAuthenticationMethod(method.get());\r
98         statement->setSubject(subject);\r
99         \r
100         Assertion* assertion=AssertionBuilder::buildAssertion();\r
101         assertion->setAssertionID(aid.get());\r
102         assertion->setIssueInstant(issueInstant.get());\r
103         assertion->setIssuer(issuer.get());\r
104         assertion->getAuthenticationStatements().push_back(statement);\r
105 \r
106         // Append a Signature.\r
107         assertion->setSignature(SignatureBuilder::buildSignature());\r
108         assertion->getSignature()->setSigningKey(m_key->clone());\r
109 \r
110         // Build KeyInfo.\r
111         KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo();\r
112         X509Data* x509Data=X509DataBuilder::buildX509Data();\r
113         keyInfo->getX509Datas().push_back(x509Data);\r
114         for_each(m_certs.begin(),m_certs.end(),bind1st(_addcert(),x509Data));\r
115         assertion->getSignature()->setKeyInfo(keyInfo);\r
116 \r
117         // Sign assertion while marshalling.\r
118         vector<Signature*> sigs(1,assertion->getSignature());\r
119         DOMElement* rootElement = NULL;\r
120         try {\r
121             rootElement=assertion->marshall((DOMDocument*)NULL,&sigs);\r
122         }\r
123         catch (XMLToolingException& e) {\r
124             TS_TRACE(e.what());\r
125             delete assertion;\r
126             throw;\r
127         }\r
128 \r
129         StatusCode* sc=StatusCodeBuilder::buildStatusCode();\r
130         sc->setValue(&StatusCode::SUCCESS);\r
131         Status* status=StatusBuilder::buildStatus();\r
132         status->setStatusCode(sc);\r
133 \r
134         auto_ptr<Response> response(ResponseBuilder::buildResponse());\r
135         response->setResponseID(rid.get());\r
136         response->setIssueInstant(issueInstant.get());\r
137         response->setStatus(status);\r
138         response->getAssertions().push_back(assertion);\r
139         response->setSignature(SignatureBuilder::buildSignature());\r
140         response->getSignature()->setSigningKey(m_key->clone());\r
141         response->getSignature()->setKeyInfo(keyInfo->cloneKeyInfo());\r
142 \r
143         // Sign response while marshalling.\r
144         sigs.clear();\r
145         sigs.push_back(response->getSignature());\r
146         rootElement = NULL;\r
147         try {\r
148             rootElement=response->marshall((DOMDocument*)NULL,&sigs);\r
149         }\r
150         catch (XMLToolingException& e) {\r
151             TS_TRACE(e.what());\r
152             throw;\r
153         }\r
154 \r
155         string buf;\r
156         XMLHelper::serialize(rootElement, buf);\r
157         istringstream in(buf);\r
158         DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);\r
159         const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());\r
160         \r
161         assertEquals(expectedChildElementsDOM, b->buildFromDocument(doc));\r
162         \r
163         try {\r
164             assertion->getSignature()->registerValidator(new SignatureProfileValidator());\r
165             assertion->getSignature()->registerValidator(new SignatureValidator(m_key->clone()));\r
166             assertion->getSignature()->validate(true);\r
167             response->getSignature()->registerValidator(new SignatureProfileValidator());\r
168             response->getSignature()->registerValidator(new SignatureValidator(m_key->clone()));\r
169             response->getSignature()->validate(true);\r
170         }\r
171         catch (XMLToolingException& e) {\r
172             TS_TRACE(e.what());\r
173             throw;\r
174         }\r
175     }\r
176 \r
177 };\r