81fbd559ff73510e2e4bd47876b2c5cc2db98224
[shibboleth/cpp-xmltooling.git] / xmltooling / security / impl / ChainingTrustEngine.cpp
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20
21 /**
22  * ChainingTrustEngine.cpp
23  * 
24  * OpenSSLTrustEngine that uses multiple engines in sequence.
25  */
26
27 #include "internal.h"
28 #include "exceptions.h"
29 #include "logging.h"
30 #include "security/ChainingTrustEngine.h"
31 #include "security/CredentialCriteria.h"
32 #include "util/XMLHelper.h"
33
34 #include <algorithm>
35 #include <boost/lambda/lambda.hpp>
36 #include <xercesc/util/XMLUniDefs.hpp>
37
38 using namespace xmlsignature;
39 using namespace xmltooling::logging;
40 using namespace xmltooling;
41 using namespace boost::lambda;
42 using namespace boost;
43 using namespace std;
44
45 using xercesc::DOMElement;
46
47 namespace xmltooling {
48     TrustEngine* XMLTOOL_DLLLOCAL ChainingTrustEngineFactory(const DOMElement* const & e)
49     {
50         return new ChainingTrustEngine(e);
51     }
52 };
53
54 static const XMLCh _TrustEngine[] =                 UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);
55 static const XMLCh type[] =                         UNICODE_LITERAL_4(t,y,p,e);
56
57 ChainingTrustEngine::ChainingTrustEngine(const DOMElement* e) : TrustEngine(e)
58 {
59     Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."CHAINING_TRUSTENGINE);
60     e = e ? XMLHelper::getFirstChildElement(e, _TrustEngine) : nullptr;
61     while (e) {
62         try {
63             string t = XMLHelper::getAttrString(e, nullptr, type);
64             if (!t.empty()) {
65                 log.info("building TrustEngine of type %s", t.c_str());
66                 addTrustEngine(XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), e));
67             }
68         }
69         catch (exception& ex) {
70             log.error("error building TrustEngine: %s", ex.what());
71         }
72         e = XMLHelper::getNextSiblingElement(e, _TrustEngine);
73     }
74 }
75
76 ChainingTrustEngine::~ChainingTrustEngine()
77 {
78 }
79
80 void ChainingTrustEngine::addTrustEngine(TrustEngine* newEngine)
81 {
82     m_engines.push_back(newEngine);
83     SignatureTrustEngine* sig = dynamic_cast<SignatureTrustEngine*>(newEngine);
84     if (sig)
85         m_sigEngines.push_back(sig);
86     X509TrustEngine* x509 = dynamic_cast<X509TrustEngine*>(newEngine);
87     if (x509)
88         m_x509Engines.push_back(x509);
89     OpenSSLTrustEngine* ossl = dynamic_cast<OpenSSLTrustEngine*>(newEngine);
90     if (ossl)
91         m_osslEngines.push_back(ossl);
92 }
93
94 TrustEngine* ChainingTrustEngine::removeTrustEngine(TrustEngine* oldEngine)
95 {
96     ptr_vector<TrustEngine>::iterator i =
97         find_if(m_engines.begin(), m_engines.end(), (&_1 == oldEngine));
98     if (i != m_engines.end()) {
99         SignatureTrustEngine* sig = dynamic_cast<SignatureTrustEngine*>(oldEngine);
100         if (sig) {
101             ptr_vector<SignatureTrustEngine>::iterator s =
102                 find_if(m_sigEngines.begin(), m_sigEngines.end(), (&_1 == sig));
103             if (s != m_sigEngines.end())
104                 m_sigEngines.erase(s);
105         }
106
107         X509TrustEngine* x509 = dynamic_cast<X509TrustEngine*>(oldEngine);
108         if (x509) {
109             ptr_vector<X509TrustEngine>::iterator x =
110                 find_if(m_x509Engines.begin(), m_x509Engines.end(), (&_1 == x509));
111             if (x != m_x509Engines.end())
112                 m_x509Engines.erase(x);
113         }
114
115         OpenSSLTrustEngine* ossl = dynamic_cast<OpenSSLTrustEngine*>(oldEngine);
116         if (ossl) {
117             ptr_vector<OpenSSLTrustEngine>::iterator o =
118                 find_if(m_osslEngines.begin(), m_osslEngines.end(), (&_1 == ossl));
119             if (o != m_osslEngines.end())
120                 m_osslEngines.erase(o);
121         }
122
123         return (m_engines.release(i)).release();
124     }
125     return nullptr;
126 }
127
128 bool ChainingTrustEngine::validate(Signature& sig, const CredentialResolver& credResolver, CredentialCriteria* criteria) const
129 {
130     unsigned int usage = criteria ? criteria->getUsage() : 0;
131     for (ptr_vector<SignatureTrustEngine>::const_iterator i=m_sigEngines.begin(); i!=m_sigEngines.end(); ++i) {
132         if (i->validate(sig,credResolver,criteria))
133             return true;
134         if (criteria) {
135             criteria->reset();
136             criteria->setUsage(usage);
137         }
138     }
139     return false;
140 }
141
142 bool ChainingTrustEngine::validate(
143     const XMLCh* sigAlgorithm,
144     const char* sig,
145     KeyInfo* keyInfo,
146     const char* in,
147     unsigned int in_len,
148     const CredentialResolver& credResolver,
149     CredentialCriteria* criteria
150     ) const
151 {
152     unsigned int usage = criteria ? criteria->getUsage() : 0;
153     for (ptr_vector<SignatureTrustEngine>::const_iterator i=m_sigEngines.begin(); i!=m_sigEngines.end(); ++i) {
154         if (i->validate(sigAlgorithm, sig, keyInfo, in, in_len, credResolver, criteria))
155             return true;
156         if (criteria) {
157             criteria->reset();
158             criteria->setUsage(usage);
159         }
160     }
161     return false;
162 }
163
164 bool ChainingTrustEngine::validate(
165     XSECCryptoX509* certEE,
166     const vector<XSECCryptoX509*>& certChain,
167     const CredentialResolver& credResolver,
168     CredentialCriteria* criteria
169     ) const
170 {
171     unsigned int usage = criteria ? criteria->getUsage() : 0;
172     for (ptr_vector<X509TrustEngine>::const_iterator i=m_x509Engines.begin(); i!=m_x509Engines.end(); ++i) {
173         if (i->validate(certEE,certChain,credResolver,criteria))
174             return true;
175         if (criteria) {
176             criteria->reset();
177             criteria->setUsage(usage);
178         }
179     }
180     return false;
181 }
182
183 bool ChainingTrustEngine::validate(
184     X509* certEE,
185     STACK_OF(X509)* certChain,
186     const CredentialResolver& credResolver,
187     CredentialCriteria* criteria
188     ) const
189 {
190     unsigned int usage = criteria ? criteria->getUsage() : 0;
191     for (ptr_vector<OpenSSLTrustEngine>::const_iterator i=m_osslEngines.begin(); i!=m_osslEngines.end(); ++i) {
192         if (i->validate(certEE,certChain,credResolver,criteria))
193             return true;
194         if (criteria) {
195             criteria->reset();
196             criteria->setUsage(usage);
197         }
198     }
199     return false;
200 }