TrustEngine based on static trust roots.
[shibboleth/cpp-xmltooling.git] / xmltooling / security / impl / StaticPKIXTrustEngine.cpp
1 /*
2  *  Copyright 2001-2007 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);\r
42     static const XMLCh type[] =                 UNICODE_LITERAL_4(t,y,p,e);\r
43     static const XMLCh certificate[] =          UNICODE_LITERAL_11(c,e,r,t,i,f,i,c,a,t,e);\r
44     static const XMLCh Certificate[] =          UNICODE_LITERAL_11(C,e,r,t,i,f,i,c,a,t,e);\r
45     static const XMLCh Path[] =                 UNICODE_LITERAL_4(P,a,t,h);\r
46     static const XMLCh verifyDepth[] =          UNICODE_LITERAL_11(v,e,r,i,f,y,D,e,p,t,h);
47 \r
48     class XMLTOOL_DLLLOCAL StaticPKIXTrustEngine : public AbstractPKIXTrustEngine
49     {
50     public:
51         StaticPKIXTrustEngine(const DOMElement* e=NULL);
52
53         virtual ~StaticPKIXTrustEngine() {
54             if (m_credResolver) {
55                 m_credResolver->unlock();
56                 delete m_credResolver;
57             }
58         }
59         
60         AbstractPKIXTrustEngine::PKIXValidationInfoIterator* getPKIXValidationInfoIterator(
61             const CredentialResolver& pkixSource, CredentialCriteria* criteria=NULL
62             ) const;
63
64         const KeyInfoResolver* getKeyInfoResolver() const {
65             return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();
66         }
67
68     private:
69         CredentialResolver* m_credResolver;
70         int m_depth;
71         vector<XSECCryptoX509*> m_certs;
72         vector<XSECCryptoX509CRL*> m_crls;
73         friend class XMLTOOL_DLLLOCAL StaticPKIXIterator;
74     };
75     
76     TrustEngine* XMLTOOL_DLLLOCAL StaticPKIXTrustEngineFactory(const DOMElement* const & e)
77     {
78         return new StaticPKIXTrustEngine(e);
79     }
80
81     class XMLTOOL_DLLLOCAL StaticPKIXIterator : public AbstractPKIXTrustEngine::PKIXValidationInfoIterator
82     {
83     public:
84         StaticPKIXIterator(const StaticPKIXTrustEngine& engine) : m_engine(engine), m_done(false) {
85         }
86
87         virtual ~StaticPKIXIterator() {
88         }
89
90         bool next() {
91             if (m_done)
92                 return false;
93             m_done = true;
94             return true;
95         }
96
97         int getVerificationDepth() const {
98             return m_engine.m_depth;
99         }
100         
101         const vector<XSECCryptoX509*>& getTrustAnchors() const {
102             return m_engine.m_certs;
103         }
104
105         const vector<XSECCryptoX509CRL*>& getCRLs() const {
106             return m_engine.m_crls;
107         }
108     
109     private:
110         const StaticPKIXTrustEngine& m_engine;
111         bool m_done;
112     };
113 };
114
115 StaticPKIXTrustEngine::StaticPKIXTrustEngine(const DOMElement* e) : AbstractPKIXTrustEngine(e)
116 {
117     const XMLCh* depth = e ? e->getAttributeNS(NULL, verifyDepth) : NULL;
118     if (depth && *depth)
119         m_depth = XMLString::parseInt(depth);
120     else
121         m_depth = 1;
122
123     if (e && e->hasAttributeNS(NULL,certificate)) {\r
124         // Dummy up a file resolver.\r
125         DOMElement* dummy = e->getOwnerDocument()->createElementNS(NULL,_CredentialResolver);\r
126         DOMElement* child = e->getOwnerDocument()->createElementNS(NULL,Certificate);\r
127         dummy->appendChild(child);\r
128         DOMElement* path = e->getOwnerDocument()->createElementNS(NULL,Path);\r
129         child->appendChild(path);\r
130         path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(NULL,certificate)));\r
131         m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(FILESYSTEM_CREDENTIAL_RESOLVER,dummy);\r
132     }\r
133     else {\r
134         e = e ? XMLHelper::getFirstChildElement(e, _CredentialResolver) : NULL;\r
135         auto_ptr_char t(e ? e->getAttributeNS(NULL,type) : NULL);\r
136         if (t.get()) {\r
137             m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(t.get(),e);\r
138         }\r
139         else\r
140             throw XMLSecurityException("Missing <CredentialResolver> element, or no type attribute found");\r
141     }\r
142 \r
143     m_credResolver->lock();\r
144
145     // Merge together all X509Credentials we can resolve.
146     try {
147         vector<const Credential*> creds;
148         m_credResolver->resolve(creds);
149         for (vector<const Credential*>::const_iterator i = creds.begin(); i != creds.end(); ++i) {
150             const X509Credential* xcred = dynamic_cast<const X509Credential*>(*i);
151             if (xcred) {
152                 m_certs.insert(m_certs.end(), xcred->getEntityCertificateChain().begin(), xcred->getEntityCertificateChain().end());
153                 if (xcred->getCRL())
154                     m_crls.push_back(xcred->getCRL());
155             }
156         }
157     }
158     catch (exception& ex) {
159         logging::Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine.StaticPKIX").error(ex.what());
160     }
161 }
162
163 AbstractPKIXTrustEngine::PKIXValidationInfoIterator* StaticPKIXTrustEngine::getPKIXValidationInfoIterator(
164     const CredentialResolver& pkixSource, CredentialCriteria* criteria
165     ) const
166 {
167     return new StaticPKIXIterator(*this);
168 }