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