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