2 * The Shibboleth License, Version 1.
4 * University Corporation for Advanced Internet Development, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution, if any, must include
17 * the following acknowledgment: "This product includes software developed by
18 * the University Corporation for Advanced Internet Development
19 * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
20 * may appear in the software itself, if and wherever such third-party
21 * acknowledgments normally appear.
23 * Neither the name of Shibboleth nor the names of its contributors, nor
24 * Internet2, nor the University Corporation for Advanced Internet Development,
25 * Inc., nor UCAID may be used to endorse or promote products derived from this
26 * software without specific prior written permission. For written permission,
27 * please contact shibboleth@shibboleth.org
29 * Products derived from this software may not be called Shibboleth, Internet2,
30 * UCAID, or the University Corporation for Advanced Internet Development, nor
31 * may Shibboleth appear in their name, without prior written permission of the
32 * University Corporation for Advanced Internet Development.
35 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36 * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38 * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
39 * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
40 * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
41 * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
42 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 /* BasicTrust.cpp - a trust implementation that relies solely on standard SAML metadata
60 #include <openssl/x509.h>
61 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
63 using namespace shibboleth;
65 using namespace log4cpp;
68 IPlugIn* BasicTrustFactory(const DOMElement* e)
70 return new BasicTrust(e);
73 static const XMLCh resolver[] =
74 { chLatin_K, chLatin_e, chLatin_y, chLatin_I, chLatin_n, chLatin_f, chLatin_o,
75 chLatin_R, chLatin_e, chLatin_s, chLatin_o, chLatin_l, chLatin_v, chLatin_e, chLatin_r, chNull
77 static const XMLCh type[] =
78 { chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull };
80 BasicTrust::BasicTrust(const DOMElement* e)
82 // Find any KeyResolver plugins.
83 e=saml::XML::getFirstChildElement(e);
85 if (!XMLString::compareString(resolver,e->getLocalName()) && e->hasAttributeNS(NULL,type)) {
87 auto_ptr_char temp(e->getAttributeNS(NULL,type));
88 m_resolvers.push_back(KeyInfoResolver::getInstance(temp.get(),e));
90 catch (SAMLException& ex) {
91 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error(
92 "caught SAML exception building KeyInfoResolver plugin: %s",ex.what()
97 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error("caught unknown exception building KeyInfoResolver plugin");
101 e=saml::XML::getNextSiblingElement(e);
103 m_resolvers.push_back(KeyInfoResolver::getInstance(e));
106 BasicTrust::~BasicTrust()
108 for (vector<KeyInfoResolver*>::iterator i=m_resolvers.begin(); i!=m_resolvers.end(); i++)
112 bool BasicTrust::validate(void* certEE, const Iterator<void*>& certChain, const IRoleDescriptor* role, bool checkName)
115 saml::NDC ndc("validate");
117 Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
120 log.error("no certificate provided for comparison");
124 // The new "basic" trust implementation relies solely on certificates living within the
125 // role interface to verify the EE certificate.
127 log.debug("comparing certificate to KeyDescriptors");
128 Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
129 while (kd_i.hasNext()) {
130 const IKeyDescriptor* kd=kd_i.next();
131 if (kd->getUse()==IKeyDescriptor::encryption)
133 DSIGKeyInfoList* KIL=kd->getKeyInfo();
136 Iterator<KeyInfoResolver*> resolvers(m_resolvers);
137 while (resolvers.hasNext()) {
138 XSECCryptoX509* cert=resolvers.next()->resolveCert(KIL);
140 log.debug("KeyDescriptor resolved into a certificate, comparing it...");
141 if (cert->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
142 log.warn("only the OpenSSL XSEC provider is supported");
145 else if (!X509_cmp(reinterpret_cast<X509*>(certEE),static_cast<OpenSSLCryptoX509*>(cert)->getOpenSSLX509())) {
146 log.info("certificate match found in KeyDescriptor");
150 log.debug("certificate did not match");
155 log.debug("failed to find an exact match for certificate in KeyDescriptors");
159 bool BasicTrust::validate(const saml::SAMLSignedObject& token, const IRoleDescriptor* role, ITrust* certValidator)
162 saml::NDC ndc("validate");
164 Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
166 // The new "basic" trust implementation relies solely on keys living within the
167 // role interface to verify the token. No indirection of any sort is allowed,
168 // unless an alternate key resolver is involved.
170 log.debug("validating signature with KeyDescriptors");
171 Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
172 while (kd_i.hasNext()) {
173 const IKeyDescriptor* kd=kd_i.next();
174 if (kd->getUse()!=IKeyDescriptor::signing)
176 DSIGKeyInfoList* KIL=kd->getKeyInfo();
179 Iterator<KeyInfoResolver*> resolvers(m_resolvers);
180 while (resolvers.hasNext()) {
181 XSECCryptoKey* key=((XSECKeyInfoResolver*)*resolvers.next())->resolveKey(KIL);
183 log.debug("KeyDescriptor resolved into a key, trying it...");
186 log.info("signature verified with KeyDescriptor");
189 catch (SAMLException& e) {
190 log.debug("verification with KeyDescriptor failed: %s", e.what());
196 log.debug("failed to validate signature with KeyDescriptors");