2 * Copyright 2001-2005 Internet2
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /* BasicTrust.cpp - a trust implementation that relies solely on standard SAML metadata
27 #include <openssl/x509.h>
28 #include <xsec/enc/XSECCryptoException.hpp>
29 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
30 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
31 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
33 using namespace shibboleth::logging;
34 using namespace shibboleth;
38 IPlugIn* BasicTrustFactory(const DOMElement* e)
40 return new BasicTrust(e);
43 static const XMLCh resolver[] =
44 { chLatin_K, chLatin_e, chLatin_y, chLatin_I, chLatin_n, chLatin_f, chLatin_o,
45 chLatin_R, chLatin_e, chLatin_s, chLatin_o, chLatin_l, chLatin_v, chLatin_e, chLatin_r, chNull
47 static const XMLCh type[] =
48 { chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull };
50 static const XMLCh debug[] =
51 { chLatin_d, chLatin_e, chLatin_b, chLatin_u, chLatin_g, chNull };
53 BasicTrust::BasicTrust(const DOMElement* e) : m_debug(false)
56 const XMLCh* flag=e->getAttributeNS(NULL,debug);
57 if (flag && (*flag==chLatin_t || *flag==chDigit_1))
60 // Find any KeyResolver plugins.
61 e=saml::XML::getFirstChildElement(e);
63 if (!XMLString::compareString(resolver,e->getLocalName()) && e->hasAttributeNS(NULL,type)) {
65 auto_ptr_char temp(e->getAttributeNS(NULL,type));
66 m_resolvers.push_back(KeyInfoResolver::getInstance(temp.get(),e));
68 catch (SAMLException& ex) {
69 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error(
70 "caught SAML exception building KeyInfoResolver plugin: %s",ex.what()
75 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error("caught unknown exception building KeyInfoResolver plugin");
79 e=saml::XML::getNextSiblingElement(e);
81 m_resolvers.push_back(KeyInfoResolver::getInstance(e));
84 BasicTrust::~BasicTrust()
86 for (vector<KeyInfoResolver*>::iterator i=m_resolvers.begin(); i!=m_resolvers.end(); i++)
90 bool BasicTrust::validate(void* certEE, const Iterator<void*>& certChain, const IRoleDescriptor* role, bool checkName)
93 saml::NDC ndc("validate");
95 Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
98 log.error("no certificate provided for comparison");
103 log.warn("running in debug mode, we accept anything!");
107 // The new "basic" trust implementation relies solely on certificates living within the
108 // role interface to verify the EE certificate.
110 log.debug("comparing key inside certificate to KeyDescriptors");
111 Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
112 while (kd_i.hasNext()) {
113 const IKeyDescriptor* kd=kd_i.next();
114 if (kd->getUse()==IKeyDescriptor::encryption)
116 DSIGKeyInfoList* KIL=kd->getKeyInfo();
119 Iterator<KeyInfoResolver*> resolvers(m_resolvers);
120 while (resolvers.hasNext()) {
121 XSECCryptoKey* key=NULL;
123 key=((XSECKeyInfoResolver*)*resolvers.next())->resolveKey(KIL);
125 catch (XSECCryptoException& ex) {
126 log.error("caught an XMLSec crypto exception while resolving key: %s", ex.getMsg());
129 log.debug("KeyDescriptor resolved into a key, comparing it...");
130 if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
131 log.error("only the OpenSSL XSEC provider is supported");
135 switch (key->getKeyType()) {
136 case XSECCryptoKey::KEY_RSA_PUBLIC:
137 case XSECCryptoKey::KEY_RSA_PAIR:
139 RSA* rsa = static_cast<OpenSSLCryptoKeyRSA*>(key)->getOpenSSLRSA();
140 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(reinterpret_cast<X509*>(certEE)));
141 if (rsa && evp && evp->type == EVP_PKEY_RSA &&
142 BN_cmp(rsa->n,evp->pkey.rsa->n) == 0 && BN_cmp(rsa->e,evp->pkey.rsa->e) == 0) {
145 log.debug("matching key found in KeyDescriptor");
153 case XSECCryptoKey::KEY_DSA_PUBLIC:
154 case XSECCryptoKey::KEY_DSA_PAIR:
156 DSA* dsa = static_cast<OpenSSLCryptoKeyDSA*>(key)->getOpenSSLDSA();
157 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(reinterpret_cast<X509*>(certEE)));
158 if (dsa && evp && evp->type == EVP_PKEY_DSA && BN_cmp(dsa->pub_key,evp->pkey.dsa->pub_key) == 0) {
161 log.debug("matching key found in KeyDescriptor");
170 log.warn("unknown key type in KeyDescriptor, skipping...");
176 log.debug("failed to find a matching key for certificate in KeyDescriptors");
180 bool BasicTrust::validate(const saml::SAMLSignedObject& token, const IRoleDescriptor* role, ITrust* certValidator)
183 saml::NDC ndc("validate");
185 Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
188 log.warn("running in debug mode, we accept anything!");
192 // The new "basic" trust implementation relies solely on keys living within the
193 // role interface to verify the token. No indirection of any sort is allowed,
194 // unless an alternate key resolver is involved.
196 log.debug("validating signature with KeyDescriptors");
197 Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
198 while (kd_i.hasNext()) {
199 const IKeyDescriptor* kd=kd_i.next();
200 if (kd->getUse()==IKeyDescriptor::encryption)
202 DSIGKeyInfoList* KIL=kd->getKeyInfo();
205 Iterator<KeyInfoResolver*> resolvers(m_resolvers);
206 while (resolvers.hasNext()) {
207 XSECCryptoKey* key=NULL;
209 key=((XSECKeyInfoResolver*)*resolvers.next())->resolveKey(KIL);
211 catch (XSECCryptoException& ex) {
212 log.error("caught an XMLSec crypto exception while resolving key: %s", ex.getMsg());
215 log.debug("KeyDescriptor resolved into a key, trying it...");
218 log.debug("signature verified with KeyDescriptor");
221 catch (SAMLException& e) {
222 log.debug("verification with KeyDescriptor failed: %s", e.what());
228 log.debug("failed to validate signature with KeyDescriptors");