06fde64a764ec0d484198f7aba2bd82aff25beb7
[shibboleth/cpp-xmltooling.git] / xmltooling / security / impl / StaticPKIXTrustEngine.cpp
1 /*
2  *  Copyright 2001-2010 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  * PKIXTrustEngine.cpp
19  * 
20  * Shibboleth-specific PKIX-validation TrustEngine.
21  */
22
23 #include "internal.h"
24
25 #include "logging.h"
26 #include "XMLToolingConfig.h"
27 #include "security/AbstractPKIXTrustEngine.h"
28 #include "security/CredentialResolver.h"
29 #include "security/X509Credential.h"
30 #include "util/XMLHelper.h"
31
32 #include <xercesc/util/XMLUniDefs.hpp>
33
34 using namespace xmlsignature;
35 using namespace xmltooling;
36 using namespace xercesc;
37 using namespace std;
38
39 namespace xmltooling {
40
41     static const XMLCh _CredentialResolver[] =  UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);
42     static const XMLCh type[] =                 UNICODE_LITERAL_4(t,y,p,e);
43     static const XMLCh certificate[] =          UNICODE_LITERAL_11(c,e,r,t,i,f,i,c,a,t,e);
44     static const XMLCh Certificate[] =          UNICODE_LITERAL_11(C,e,r,t,i,f,i,c,a,t,e);
45     static const XMLCh Path[] =                 UNICODE_LITERAL_4(P,a,t,h);
46     static const XMLCh verifyDepth[] =          UNICODE_LITERAL_11(v,e,r,i,f,y,D,e,p,t,h);
47
48     class XMLTOOL_DLLLOCAL StaticPKIXTrustEngine : public AbstractPKIXTrustEngine
49     {
50     public:
51         StaticPKIXTrustEngine(const DOMElement* e=nullptr);
52
53         virtual ~StaticPKIXTrustEngine() {
54             delete m_credResolver;
55         }
56         
57         AbstractPKIXTrustEngine::PKIXValidationInfoIterator* getPKIXValidationInfoIterator(
58             const CredentialResolver& pkixSource, CredentialCriteria* criteria=nullptr
59             ) const;
60
61         const KeyInfoResolver* getKeyInfoResolver() const {
62             return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();
63         }
64
65     private:
66         int m_depth;
67         CredentialResolver* m_credResolver;
68         friend class XMLTOOL_DLLLOCAL StaticPKIXIterator;
69     };
70     
71     TrustEngine* XMLTOOL_DLLLOCAL StaticPKIXTrustEngineFactory(const DOMElement* const & e)
72     {
73         return new StaticPKIXTrustEngine(e);
74     }
75
76     class XMLTOOL_DLLLOCAL StaticPKIXIterator : public AbstractPKIXTrustEngine::PKIXValidationInfoIterator
77     {
78     public:
79         StaticPKIXIterator(const StaticPKIXTrustEngine& engine) : m_engine(engine), m_done(false) {
80             // Merge together all X509Credentials we can resolve.
81             m_engine.m_credResolver->lock();
82             try {
83                 vector<const Credential*> creds;
84                 m_engine.m_credResolver->resolve(creds);
85                 for (vector<const Credential*>::const_iterator i = creds.begin(); i != creds.end(); ++i) {
86                     const X509Credential* xcred = dynamic_cast<const X509Credential*>(*i);
87                     if (xcred) {
88                         m_certs.insert(m_certs.end(), xcred->getEntityCertificateChain().begin(), xcred->getEntityCertificateChain().end());
89                         m_crls.insert(m_crls.end(), xcred->getCRLs().begin(), xcred->getCRLs().end());
90                     }
91                 }
92             }
93             catch (exception& ex) {
94                 logging::Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine.StaticPKIX").error(ex.what());
95             }
96         }
97
98         virtual ~StaticPKIXIterator() {
99             m_engine.m_credResolver->unlock();
100         }
101
102         bool next() {
103             if (m_done)
104                 return false;
105             m_done = true;
106             return true;
107         }
108
109         int getVerificationDepth() const {
110             return m_engine.m_depth;
111         }
112         
113         const vector<XSECCryptoX509*>& getTrustAnchors() const {
114             return m_certs;
115         }
116
117         const vector<XSECCryptoX509CRL*>& getCRLs() const {
118             return m_crls;
119         }
120     
121     private:
122         const StaticPKIXTrustEngine& m_engine;
123         vector<XSECCryptoX509*> m_certs;
124         vector<XSECCryptoX509CRL*> m_crls;
125         bool m_done;
126     };
127 };
128
129 StaticPKIXTrustEngine::StaticPKIXTrustEngine(const DOMElement* e)
130     : AbstractPKIXTrustEngine(e), m_depth(XMLHelper::getAttrInt(e, 1, verifyDepth)), m_credResolver(nullptr)
131 {
132     if (e && e->hasAttributeNS(nullptr, certificate)) {
133         // Simple File resolver config rooted here.
134         m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(FILESYSTEM_CREDENTIAL_RESOLVER, e);
135     }
136     else {
137         e = e ? XMLHelper::getFirstChildElement(e, _CredentialResolver) : nullptr;
138         string t = XMLHelper::getAttrString(e, nullptr, type);
139         if (!t.empty())
140             m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(t.c_str(), e);
141         else
142             throw XMLSecurityException("Missing <CredentialResolver> element, or no type attribute found");
143     }
144 }
145
146 AbstractPKIXTrustEngine::PKIXValidationInfoIterator* StaticPKIXTrustEngine::getPKIXValidationInfoIterator(
147     const CredentialResolver& pkixSource, CredentialCriteria* criteria
148     ) const
149 {
150     return new StaticPKIXIterator(*this);
151 }