Fix 64-bit cast.
[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::logging;
31 using namespace shibboleth;
32 using namespace saml;
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 static const XMLCh debug[] =
48 { chLatin_d, chLatin_e, chLatin_b, chLatin_u, chLatin_g, chNull };
49
50 BasicTrust::BasicTrust(const DOMElement* e) : m_debug(false)
51 {
52     // Debug mode?
53     const XMLCh* flag=e->getAttributeNS(NULL,debug);
54     if (flag && (*flag==chLatin_t || *flag==chDigit_1))
55         m_debug=true;
56     
57     // Find any KeyResolver plugins.
58     e=saml::XML::getFirstChildElement(e);
59     while (e) {
60         if (!XMLString::compareString(resolver,e->getLocalName()) && e->hasAttributeNS(NULL,type)) {
61             try {
62                 auto_ptr_char temp(e->getAttributeNS(NULL,type));
63                 m_resolvers.push_back(KeyInfoResolver::getInstance(temp.get(),e));
64             }
65             catch (SAMLException& ex) {
66                 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error(
67                     "caught SAML exception building KeyInfoResolver plugin: %s",ex.what()
68                     );
69             }
70 #ifndef _DEBUG
71             catch (...) {
72                 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error("caught unknown exception building KeyInfoResolver plugin");
73             }
74 #endif
75         }
76         e=saml::XML::getNextSiblingElement(e);
77     }
78     m_resolvers.push_back(KeyInfoResolver::getInstance(e));
79 }
80
81 BasicTrust::~BasicTrust()
82 {
83     for (vector<KeyInfoResolver*>::iterator i=m_resolvers.begin(); i!=m_resolvers.end(); i++)
84         delete *i;
85 }
86
87 bool BasicTrust::validate(void* certEE, const Iterator<void*>& certChain, const IRoleDescriptor* role, bool checkName)
88 {
89 #ifdef _DEBUG
90     saml::NDC ndc("validate");
91 #endif
92     Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
93
94     if (!certEE) {
95         log.error("no certificate provided for comparison");
96         return false;
97     }
98
99     if (m_debug) {
100         log.warn("running in debug mode, we accept anything!");
101         return true;
102     }
103
104     // The new "basic" trust implementation relies solely on certificates living within the
105     // role interface to verify the EE certificate.
106
107     log.debug("comparing certificate to KeyDescriptors");
108     Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
109     while (kd_i.hasNext()) {
110         const IKeyDescriptor* kd=kd_i.next();
111         if (kd->getUse()==IKeyDescriptor::encryption)
112             continue;
113         DSIGKeyInfoList* KIL=kd->getKeyInfo();
114         if (!KIL)
115             continue;
116         Iterator<KeyInfoResolver*> resolvers(m_resolvers);
117         while (resolvers.hasNext()) {
118             XSECCryptoX509* cert=resolvers.next()->resolveCert(KIL);
119             if (cert) {
120                 log.debug("KeyDescriptor resolved into a certificate, comparing it...");
121                 if (cert->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
122                     log.warn("only the OpenSSL XSEC provider is supported");
123                     continue;
124                 }
125                 else if (!X509_cmp(reinterpret_cast<X509*>(certEE),static_cast<OpenSSLCryptoX509*>(cert)->getOpenSSLX509())) {
126                     log.info("certificate match found in KeyDescriptor");
127                     return true;
128                 }
129                 else
130                     log.debug("certificate did not match");
131             }
132         }
133     }
134     
135     log.debug("failed to find an exact match for certificate in KeyDescriptors");
136     return false;
137 }
138
139 bool BasicTrust::validate(const saml::SAMLSignedObject& token, const IRoleDescriptor* role, ITrust* certValidator)
140 {
141 #ifdef _DEBUG
142     saml::NDC ndc("validate");
143 #endif
144     Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
145
146     if (m_debug) {
147         log.warn("running in debug mode, we accept anything!");
148         return true;
149     }
150
151     // The new "basic" trust implementation relies solely on keys living within the
152     // role interface to verify the token. No indirection of any sort is allowed,
153     // unless an alternate key resolver is involved.
154  
155     log.debug("validating signature with KeyDescriptors");
156     Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
157     while (kd_i.hasNext()) {
158         const IKeyDescriptor* kd=kd_i.next();
159         if (kd->getUse()==IKeyDescriptor::encryption)
160             continue;
161         DSIGKeyInfoList* KIL=kd->getKeyInfo();
162         if (!KIL)
163             continue;
164         Iterator<KeyInfoResolver*> resolvers(m_resolvers);
165         while (resolvers.hasNext()) {
166             XSECCryptoKey* key=((XSECKeyInfoResolver*)*resolvers.next())->resolveKey(KIL);
167             if (key) {
168                 log.debug("KeyDescriptor resolved into a key, trying it...");
169                 try {
170                     token.verify(key);
171                     log.info("signature verified with KeyDescriptor");
172                     return true;
173                 }
174                 catch (SAMLException& e) {
175                     log.debug("verification with KeyDescriptor failed: %s", e.what());
176                 }
177             }
178         }
179     }
180     
181     log.debug("failed to validate signature with KeyDescriptors");
182     return false;
183 }