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/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
29 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
30 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
32 using namespace shibboleth::logging;
33 using namespace shibboleth;
37 IPlugIn* BasicTrustFactory(const DOMElement* e)
39 return new BasicTrust(e);
42 static const XMLCh resolver[] =
43 { chLatin_K, chLatin_e, chLatin_y, chLatin_I, chLatin_n, chLatin_f, chLatin_o,
44 chLatin_R, chLatin_e, chLatin_s, chLatin_o, chLatin_l, chLatin_v, chLatin_e, chLatin_r, chNull
46 static const XMLCh type[] =
47 { chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull };
49 static const XMLCh debug[] =
50 { chLatin_d, chLatin_e, chLatin_b, chLatin_u, chLatin_g, chNull };
52 BasicTrust::BasicTrust(const DOMElement* e) : m_debug(false)
55 const XMLCh* flag=e->getAttributeNS(NULL,debug);
56 if (flag && (*flag==chLatin_t || *flag==chDigit_1))
59 // Find any KeyResolver plugins.
60 e=saml::XML::getFirstChildElement(e);
62 if (!XMLString::compareString(resolver,e->getLocalName()) && e->hasAttributeNS(NULL,type)) {
64 auto_ptr_char temp(e->getAttributeNS(NULL,type));
65 m_resolvers.push_back(KeyInfoResolver::getInstance(temp.get(),e));
67 catch (SAMLException& ex) {
68 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error(
69 "caught SAML exception building KeyInfoResolver plugin: %s",ex.what()
74 Category::getInstance(SHIB_LOGCAT".Trust.Basic").error("caught unknown exception building KeyInfoResolver plugin");
78 e=saml::XML::getNextSiblingElement(e);
80 m_resolvers.push_back(KeyInfoResolver::getInstance(e));
83 BasicTrust::~BasicTrust()
85 for (vector<KeyInfoResolver*>::iterator i=m_resolvers.begin(); i!=m_resolvers.end(); i++)
89 bool BasicTrust::validate(void* certEE, const Iterator<void*>& certChain, const IRoleDescriptor* role, bool checkName)
92 saml::NDC ndc("validate");
94 Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
97 log.error("no certificate provided for comparison");
102 log.warn("running in debug mode, we accept anything!");
106 // The new "basic" trust implementation relies solely on certificates living within the
107 // role interface to verify the EE certificate.
109 log.debug("comparing key inside certificate to KeyDescriptors");
110 Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
111 while (kd_i.hasNext()) {
112 const IKeyDescriptor* kd=kd_i.next();
113 if (kd->getUse()==IKeyDescriptor::encryption)
115 DSIGKeyInfoList* KIL=kd->getKeyInfo();
118 Iterator<KeyInfoResolver*> resolvers(m_resolvers);
119 while (resolvers.hasNext()) {
120 XSECCryptoKey* key=((XSECKeyInfoResolver*)*resolvers.next())->resolveKey(KIL);
122 log.debug("KeyDescriptor resolved into a key, comparing it...");
123 if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
124 log.error("only the OpenSSL XSEC provider is supported");
128 switch (key->getKeyType()) {
129 case XSECCryptoKey::KEY_RSA_PUBLIC:
130 case XSECCryptoKey::KEY_RSA_PAIR:
132 RSA* rsa = static_cast<OpenSSLCryptoKeyRSA*>(key)->getOpenSSLRSA();
133 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(reinterpret_cast<X509*>(certEE)));
134 if (rsa && evp && evp->type == EVP_PKEY_RSA &&
135 BN_cmp(rsa->n,evp->pkey.rsa->n) == 0 && BN_cmp(rsa->e,evp->pkey.rsa->e) == 0) {
138 log.debug("matching key found in KeyDescriptor");
146 case XSECCryptoKey::KEY_DSA_PUBLIC:
147 case XSECCryptoKey::KEY_DSA_PAIR:
149 DSA* dsa = static_cast<OpenSSLCryptoKeyDSA*>(key)->getOpenSSLDSA();
150 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(reinterpret_cast<X509*>(certEE)));
151 if (dsa && evp && evp->type == EVP_PKEY_DSA && BN_cmp(dsa->pub_key,evp->pkey.dsa->pub_key) == 0) {
154 log.debug("matching key found in KeyDescriptor");
163 log.warn("unknown key type in KeyDescriptor, skipping...");
169 log.debug("failed to find a matching key for certificate in KeyDescriptors");
173 bool BasicTrust::validate(const saml::SAMLSignedObject& token, const IRoleDescriptor* role, ITrust* certValidator)
176 saml::NDC ndc("validate");
178 Category& log=Category::getInstance(SHIB_LOGCAT".Trust.Basic");
181 log.warn("running in debug mode, we accept anything!");
185 // The new "basic" trust implementation relies solely on keys living within the
186 // role interface to verify the token. No indirection of any sort is allowed,
187 // unless an alternate key resolver is involved.
189 log.debug("validating signature with KeyDescriptors");
190 Iterator<const IKeyDescriptor*> kd_i=role->getKeyDescriptors();
191 while (kd_i.hasNext()) {
192 const IKeyDescriptor* kd=kd_i.next();
193 if (kd->getUse()==IKeyDescriptor::encryption)
195 DSIGKeyInfoList* KIL=kd->getKeyInfo();
198 Iterator<KeyInfoResolver*> resolvers(m_resolvers);
199 while (resolvers.hasNext()) {
200 XSECCryptoKey* key=((XSECKeyInfoResolver*)*resolvers.next())->resolveKey(KIL);
202 log.debug("KeyDescriptor resolved into a key, trying it...");
205 log.info("signature verified with KeyDescriptor");
208 catch (SAMLException& e) {
209 log.debug("verification with KeyDescriptor failed: %s", e.what());
215 log.debug("failed to validate signature with KeyDescriptors");