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