Finished adding new metadata/trust plugins to config.
[shibboleth/cpp-sp.git] / shib / BasicTrust.cpp
1 /*
2  *  Copyright 2001-2005 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 /* BasicTrust.cpp - a trust implementation that relies solely on standard SAML metadata
18
19    Scott Cantor
20    4/9/05
21
22    $History:$
23 */
24
25 #include "internal.h"
26
27 #include <openssl/x509.h>
28 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
29
30 using namespace shibboleth;
31 using namespace saml;
32 using namespace log4cpp;
33 using namespace std;
34
35 IPlugIn* BasicTrustFactory(const DOMElement* e)
36 {
37     return new BasicTrust(e);
38 }
39
40 static const XMLCh resolver[] =
41 { chLatin_K, chLatin_e, chLatin_y, chLatin_I, chLatin_n, chLatin_f, chLatin_o,
42   chLatin_R, chLatin_e, chLatin_s, chLatin_o, chLatin_l, chLatin_v, chLatin_e, chLatin_r, chNull
43 };
44 static const XMLCh type[] =
45 { chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull };
46
47 BasicTrust::BasicTrust(const DOMElement* e)
48 {
49     // Find any KeyResolver plugins.
50     e=saml::XML::getFirstChildElement(e);
51     while (e) {
52         if (!XMLString::compareString(resolver,e->getLocalName()) && e->hasAttributeNS(NULL,type)) {
53             try {
54                 auto_ptr_char temp(e->getAttributeNS(NULL,type));
55                 m_resolvers.push_back(KeyInfoResolver::getInstance(temp.get(),e));
56             }
57             catch (SAMLException& ex) {
58                 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error(
59                     "caught SAML exception building KeyInfoResolver plugin: %s",ex.what()
60                     );
61             }
62 #ifndef _DEBUG
63             catch (...) {
64                 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error("caught unknown exception building KeyInfoResolver plugin");
65             }
66 #endif
67         }
68         e=saml::XML::getNextSiblingElement(e);
69     }
70     m_resolvers.push_back(KeyInfoResolver::getInstance(e));
71 }
72
73 BasicTrust::~BasicTrust()
74 {
75     for (vector<KeyInfoResolver*>::iterator i=m_resolvers.begin(); i!=m_resolvers.end(); i++)
76         delete *i;
77 }
78
79 bool BasicTrust::validate(void* certEE, const Iterator<void*>& certChain, const IRoleDescriptor* role, bool checkName)
80 {
81 #ifdef _DEBUG
82     saml::NDC ndc("validate");
83 #endif
84     Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
85
86     if (!certEE) {
87         log.error("no certificate provided for comparison");
88         return false;
89     }
90
91     // The new "basic" trust implementation relies solely on certificates living within the
92     // role interface to verify the EE certificate.
93
94     log.debug("comparing certificate to KeyDescriptors");
95     Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
96     while (kd_i.hasNext()) {
97         const IKeyDescriptor* kd=kd_i.next();
98         if (kd->getUse()==IKeyDescriptor::encryption)
99             continue;
100         DSIGKeyInfoList* KIL=kd->getKeyInfo();
101         if (!KIL)
102             continue;
103         Iterator<KeyInfoResolver*> resolvers(m_resolvers);
104         while (resolvers.hasNext()) {
105             XSECCryptoX509* cert=resolvers.next()->resolveCert(KIL);
106             if (cert) {
107                 log.debug("KeyDescriptor resolved into a certificate, comparing it...");
108                 if (cert->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
109                     log.warn("only the OpenSSL XSEC provider is supported");
110                     continue;
111                 }
112                 else if (!X509_cmp(reinterpret_cast<X509*>(certEE),static_cast<OpenSSLCryptoX509*>(cert)->getOpenSSLX509())) {
113                     log.info("certificate match found in KeyDescriptor");
114                     return true;
115                 }
116                 else
117                     log.debug("certificate did not match");
118             }
119         }
120     }
121     
122     log.debug("failed to find an exact match for certificate in KeyDescriptors");
123     return false;
124 }
125
126 bool BasicTrust::validate(const saml::SAMLSignedObject& token, const IRoleDescriptor* role, ITrust* certValidator)
127 {
128 #ifdef _DEBUG
129     saml::NDC ndc("validate");
130 #endif
131     Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
132
133     // The new "basic" trust implementation relies solely on keys living within the
134     // role interface to verify the token. No indirection of any sort is allowed,
135     // unless an alternate key resolver is involved.
136  
137     log.debug("validating signature with KeyDescriptors");
138     Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
139     while (kd_i.hasNext()) {
140         const IKeyDescriptor* kd=kd_i.next();
141         if (kd->getUse()!=IKeyDescriptor::signing)
142             continue;
143         DSIGKeyInfoList* KIL=kd->getKeyInfo();
144         if (!KIL)
145             continue;
146         Iterator<KeyInfoResolver*> resolvers(m_resolvers);
147         while (resolvers.hasNext()) {
148             XSECCryptoKey* key=((XSECKeyInfoResolver*)*resolvers.next())->resolveKey(KIL);
149             if (key) {
150                 log.debug("KeyDescriptor resolved into a key, trying it...");
151                 try {
152                     token.verify(key);
153                     log.info("signature verified with KeyDescriptor");
154                     return true;
155                 }
156                 catch (SAMLException& e) {
157                     log.debug("verification with KeyDescriptor failed: %s", e.what());
158                 }
159             }
160         }
161     }
162     
163     log.debug("failed to validate signature with KeyDescriptors");
164     return false;
165 }