2 * Copyright 2001-2009 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.
18 * FilesystemCredentialResolver.cpp
20 * Supplies credentials from local files.
25 #include "security/BasicX509Credential.h"
26 #include "security/CredentialCriteria.h"
27 #include "security/CredentialResolver.h"
28 #include "security/KeyInfoResolver.h"
29 #include "security/OpenSSLCredential.h"
30 #include "security/SecurityHelper.h"
31 #include "security/XSECCryptoX509CRL.h"
33 #include "util/PathResolver.h"
34 #include "util/Threads.h"
35 #include "util/XMLHelper.h"
39 #include <sys/types.h>
41 #include <openssl/pkcs12.h>
42 #include <xercesc/util/XMLUniDefs.hpp>
43 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
45 using namespace xmlsignature;
46 using namespace xmltooling::logging;
47 using namespace xmltooling;
50 using xercesc::DOMElement;
51 using xercesc::chLatin_f;
52 using xercesc::chDigit_0;
54 namespace xmltooling {
56 // The ManagedResource classes handle memory management, loading of the files
57 // and staleness detection. A copy of the active objects is always stored in
60 class XMLTOOL_DLLLOCAL ManagedResource {
62 ManagedResource() : local(true), reloadChanges(true), filestamp(0), reloadInterval(0) {}
65 SOAPTransport* getTransport() {
66 SOAPTransport::Address addr("FilesystemCredentialResolver", source.c_str(), source.c_str());
67 string scheme(addr.m_endpoint, strchr(addr.m_endpoint,':') - addr.m_endpoint);
68 return XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), addr);
72 bool stale(Category& log, RWLock* lock=NULL) {
75 struct _stat stat_buf;
76 if (_stat(source.c_str(), &stat_buf) != 0)
80 if (stat(source.c_str(), &stat_buf) != 0)
83 if (filestamp >= stat_buf.st_mtime)
86 // If necessary, elevate lock and recheck.
88 log.debug("timestamp of local resource changed, elevating to a write lock");
91 if (filestamp >= stat_buf.st_mtime) {
92 // Somebody else handled it, just downgrade.
93 log.debug("update of local resource handled by another thread, downgrading lock");
100 // Update the timestamp regardless. No point in repeatedly trying.
101 filestamp = stat_buf.st_mtime;
102 log.info("change detected, reloading local resource...");
105 time_t now = time(NULL);
108 if (now - filestamp < reloadInterval)
111 // If necessary, elevate lock and recheck.
113 log.debug("reload interval for remote resource elapsed, elevating to a write lock");
116 if (now - filestamp < reloadInterval) {
117 // Somebody else handled it, just downgrade.
118 log.debug("update of remote resource handled by another thread, downgrading lock");
126 log.info("reloading remote resource...");
131 bool local,reloadChanges;
132 string format,source,backing;
133 time_t filestamp,reloadInterval;
136 class XMLTOOL_DLLLOCAL ManagedKey : public ManagedResource {
138 ManagedKey() : key(NULL) {}
139 ~ManagedKey() { delete key; }
140 void load(Category& log, const char* password) {
143 XSECCryptoKey* nkey=NULL;
145 nkey = SecurityHelper::loadKeyFromFile(source.c_str(), format.c_str(), password);
148 auto_ptr<SOAPTransport> t(getTransport());
149 log.info("loading private key from URL (%s)", source.c_str());
150 nkey = SecurityHelper::loadKeyFromURL(*t.get(), backing.c_str(), format.c_str(), password);
155 format = SecurityHelper::guessEncodingFormat(local ? source.c_str() : backing.c_str());
161 class XMLTOOL_DLLLOCAL ManagedCert : public ManagedResource {
164 ~ManagedCert() { for_each(certs.begin(), certs.end(), xmltooling::cleanup<XSECCryptoX509>()); }
165 void load(Category& log, const char* password) {
168 vector<XSECCryptoX509*> ncerts;
170 SecurityHelper::loadCertificatesFromFile(ncerts, source.c_str(), format.c_str(), password);
173 auto_ptr<SOAPTransport> t(getTransport());
174 log.info("loading certificate(s) from URL (%s)", source.c_str());
175 SecurityHelper::loadCertificatesFromURL(ncerts, *t.get(), backing.c_str(), format.c_str(), password);
177 for_each(certs.begin(), certs.end(), xmltooling::cleanup<XSECCryptoX509>());
180 format = SecurityHelper::guessEncodingFormat(local ? source.c_str() : backing.c_str());
182 vector<XSECCryptoX509*> certs;
185 class XMLTOOL_DLLLOCAL ManagedCRL : public ManagedResource {
188 ~ManagedCRL() { for_each(crls.begin(), crls.end(), xmltooling::cleanup<XSECCryptoX509CRL>()); }
189 void load(Category& log) {
192 vector<XSECCryptoX509CRL*> ncrls;
194 SecurityHelper::loadCRLsFromFile(ncrls, source.c_str(), format.c_str());
197 auto_ptr<SOAPTransport> t(getTransport());
198 log.info("loading CRL(s) from URL (%s)", source.c_str());
199 SecurityHelper::loadCRLsFromURL(ncrls, *t.get(), backing.c_str(), format.c_str());
201 for_each(crls.begin(), crls.end(), xmltooling::cleanup<XSECCryptoX509CRL>());
204 format = SecurityHelper::guessEncodingFormat(local ? source.c_str() : backing.c_str());
206 vector<XSECCryptoX509CRL*> crls;
209 class XMLTOOL_DLLLOCAL FilesystemCredential;
210 class XMLTOOL_DLLLOCAL FilesystemCredentialResolver : public CredentialResolver
213 FilesystemCredentialResolver(const DOMElement* e);
214 virtual ~FilesystemCredentialResolver();
221 const Credential* resolve(const CredentialCriteria* criteria=NULL) const;
223 virtual vector<const Credential*>::size_type resolve(
224 vector<const Credential*>& results, const CredentialCriteria* criteria=NULL
228 Credential* getCredential();
231 Credential* m_credential;
232 string m_keypass,m_certpass;
233 unsigned int m_keyinfomask,m_usage;
235 vector<string> m_keynames;
238 vector<ManagedCert> m_certs;
239 vector<ManagedCRL> m_crls;
241 friend class XMLTOOL_DLLLOCAL FilesystemCredential;
244 #if defined (_MSC_VER)
245 #pragma warning( push )
246 #pragma warning( disable : 4250 )
249 class XMLTOOL_DLLLOCAL FilesystemCredential : public OpenSSLCredential, public BasicX509Credential
252 FilesystemCredential(
253 FilesystemCredentialResolver* resolver,
255 const vector<XSECCryptoX509*>& xseccerts,
256 const vector<XSECCryptoX509CRL*>& crls
257 ) : BasicX509Credential(key ? key : (xseccerts.empty() ? NULL : xseccerts.front()->clonePublicKey()), xseccerts, crls), m_resolver(resolver) {
258 if (m_resolver->m_extractNames)
260 m_keyNames.insert(m_resolver->m_keynames.begin(), m_resolver->m_keynames.end());
263 virtual ~FilesystemCredential() {
266 unsigned int getUsage() const {
267 return m_resolver->m_usage;
270 void initKeyInfo(unsigned int types=0) {
271 BasicX509Credential::initKeyInfo(types);
274 void attach(SSL_CTX* ctx) const;
277 FilesystemCredentialResolver* m_resolver;
280 #if defined (_MSC_VER)
281 #pragma warning( pop )
284 CredentialResolver* XMLTOOL_DLLLOCAL FilesystemCredentialResolverFactory(const DOMElement* const & e)
286 return new FilesystemCredentialResolver(e);
289 static const XMLCh backingFilePath[] = UNICODE_LITERAL_15(b,a,c,k,i,n,g,F,i,l,e,P,a,t,h);
290 static const XMLCh _CredentialResolver[] = UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);
291 static const XMLCh CAPath[] = UNICODE_LITERAL_6(C,A,P,a,t,h);
292 static const XMLCh Certificate[] = UNICODE_LITERAL_11(C,e,r,t,i,f,i,c,a,t,e);
293 static const XMLCh _certificate[] = UNICODE_LITERAL_11(c,e,r,t,i,f,i,c,a,t,e);
294 static const XMLCh CRL[] = UNICODE_LITERAL_3(C,R,L);
295 static const XMLCh extractNames[] = UNICODE_LITERAL_12(e,x,t,r,a,c,t,N,a,m,e,s);
296 static const XMLCh _format[] = UNICODE_LITERAL_6(f,o,r,m,a,t);
297 static const XMLCh Key[] = UNICODE_LITERAL_3(K,e,y);
298 static const XMLCh _key[] = UNICODE_LITERAL_3(k,e,y);
299 static const XMLCh keyInfoMask[] = UNICODE_LITERAL_11(k,e,y,I,n,f,o,M,a,s,k);
300 static const XMLCh keyName[] = UNICODE_LITERAL_7(k,e,y,N,a,m,e);
301 static const XMLCh Name[] = UNICODE_LITERAL_4(N,a,m,e);
302 static const XMLCh password[] = UNICODE_LITERAL_8(p,a,s,s,w,o,r,d);
303 static const XMLCh Path[] = UNICODE_LITERAL_4(P,a,t,h);
304 static const XMLCh _reloadChanges[] = UNICODE_LITERAL_13(r,e,l,o,a,d,C,h,a,n,g,e,s);
305 static const XMLCh _reloadInterval[] = UNICODE_LITERAL_14(r,e,l,o,a,d,I,n,t,e,r,v,a,l);
306 static const XMLCh _URL[] = UNICODE_LITERAL_3(U,R,L);
307 static const XMLCh _use[] = UNICODE_LITERAL_3(u,s,e);
310 FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e)
311 : m_lock(NULL), m_credential(NULL), m_usage(Credential::UNSPECIFIED_CREDENTIAL), m_extractNames(true)
314 NDC ndc("FilesystemCredentialResolver");
316 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".CredentialResolver."FILESYSTEM_CREDENTIAL_RESOLVER);
318 // Default to disable X509IssuerSerial due to schema validation issues.
320 Credential::KEYINFO_KEY_NAME |
321 Credential::KEYINFO_KEY_VALUE |
322 X509Credential::KEYINFO_X509_CERTIFICATE |
323 X509Credential::KEYINFO_X509_SUBJECTNAME;
324 if (e && e->hasAttributeNS(NULL,keyInfoMask))
325 m_keyinfomask = XMLString::parseInt(e->getAttributeNS(NULL,keyInfoMask));
327 if (e && (e->hasAttributeNS(NULL,_certificate) || e->hasAttributeNS(NULL,_key))) {
328 // Dummy up a simple file resolver config using these attributes.
329 DOMElement* dummy = e->getOwnerDocument()->createElementNS(NULL,_CredentialResolver);
332 if (e->hasAttributeNS(NULL,_key)) {
333 child = e->getOwnerDocument()->createElementNS(NULL,Key);
334 dummy->appendChild(child);
335 path = e->getOwnerDocument()->createElementNS(NULL,Path);
336 child->appendChild(path);
337 path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(NULL,_key)));
338 if (e->hasAttributeNS(NULL,password))
339 child->setAttributeNS(NULL,password,e->getAttributeNS(NULL,password));
340 if (e->hasAttributeNS(NULL,keyName)) {
341 path = e->getOwnerDocument()->createElementNS(NULL,Name);
342 child->appendChild(path);
343 path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(NULL,keyName)));
346 if (e->hasAttributeNS(NULL,_certificate)) {
347 child = e->getOwnerDocument()->createElementNS(NULL,Certificate);
348 dummy->appendChild(child);
349 path = e->getOwnerDocument()->createElementNS(NULL,Path);
350 child->appendChild(path);
351 path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(NULL,_certificate)));
352 if (e->hasAttributeNS(NULL, extractNames))
353 child->setAttributeNS(NULL, extractNames, e->getAttributeNS(NULL, extractNames));
355 e = dummy; // reset "root" to the dummy config element
359 const DOMElement* root = e;
361 // Save off usage bits.
362 const XMLCh* usage = root->getAttributeNS(NULL,_use);
363 if (usage && *usage) {
364 auto_ptr_char u(usage);
365 if (!strcmp(u.get(), "signing"))
366 m_usage = Credential::SIGNING_CREDENTIAL | Credential::TLS_CREDENTIAL;
367 else if (!strcmp(u.get(), "TLS"))
368 m_usage = Credential::TLS_CREDENTIAL;
369 else if (!strcmp(u.get(), "encryption"))
370 m_usage = Credential::ENCRYPTION_CREDENTIAL;
374 const DOMElement* keynode = XMLHelper::getFirstChildElement(root,Key);
376 prop = keynode->getAttributeNS(NULL,_format);
378 auto_ptr_char f(prop);
379 m_key.format = f.get();
382 prop = keynode->getAttributeNS(NULL,password);
384 auto_ptr_char kp(prop);
385 m_keypass = kp.get();
388 if ((e=XMLHelper::getFirstChildElement(keynode,Path)) && e->hasChildNodes()) {
389 prop = e->getFirstChild()->getNodeValue();
390 auto_ptr_char kpath(prop);
391 m_key.source = kpath.get();
392 XMLToolingConfig::getConfig().getPathResolver()->resolve(m_key.source, PathResolver::XMLTOOLING_CFG_FILE);
394 prop = e->getAttributeNS(NULL,_reloadChanges);
395 if (prop && (*prop==chLatin_f) || (*prop==chDigit_0))
396 m_key.reloadChanges = false;
398 else if ((e=XMLHelper::getFirstChildElement(keynode,_URL)) && e->hasChildNodes()) {
399 prop = e->getFirstChild()->getNodeValue();
400 auto_ptr_char kpath(prop);
401 m_key.source = kpath.get();
403 prop = e->getAttributeNS(NULL,backingFilePath);
405 throw XMLSecurityException("FilesystemCredentialResolver can't access key, backingFilePath missing from URL element.");
406 auto_ptr_char b(prop);
407 m_key.backing = b.get();
408 XMLToolingConfig::getConfig().getPathResolver()->resolve(m_key.backing, PathResolver::XMLTOOLING_RUN_FILE);
409 prop = e->getAttributeNS(NULL,_reloadInterval);
411 m_key.reloadInterval = XMLString::parseInt(prop);
414 log.error("Path/URL element missing inside Key element");
415 throw XMLSecurityException("FilesystemCredentialResolver can't access key, no Path or URL element specified.");
418 e = XMLHelper::getFirstChildElement(keynode, Name);
420 if (e->hasChildNodes()) {
421 auto_ptr_char n(e->getFirstChild()->getNodeValue());
422 if (n.get() && *n.get())
423 m_keynames.push_back(n.get());
425 e = XMLHelper::getNextSiblingElement(e, Name);
430 const DOMElement* crlnode = XMLHelper::getFirstChildElement(root,CRL);
432 const XMLCh* crlformat = crlnode->getAttributeNS(NULL,_format);
433 e = XMLHelper::getFirstChildElement(crlnode,Path);
435 if (e->hasChildNodes()) {
436 m_crls.push_back(ManagedCRL());
437 ManagedResource& crl = m_crls.back();
438 if (crlformat && *crlformat) {
439 auto_ptr_char f(crlformat);
440 crl.format = f.get();
442 prop = e->getFirstChild()->getNodeValue();
443 auto_ptr_char crlpath(prop);
444 crl.source = crlpath.get();
445 XMLToolingConfig::getConfig().getPathResolver()->resolve(crl.source, PathResolver::XMLTOOLING_CFG_FILE);
447 prop = e->getAttributeNS(NULL,_reloadChanges);
448 if (prop && (*prop==chLatin_f) || (*prop==chDigit_0))
449 crl.reloadChanges = false;
451 e = XMLHelper::getNextSiblingElement(e,Path);
454 e=XMLHelper::getFirstChildElement(crlnode,_URL);
456 if (e->hasChildNodes()) {
457 m_crls.push_back(ManagedCRL());
458 ManagedResource& crl = m_crls.back();
459 if (crlformat && *crlformat) {
460 auto_ptr_char f(crlformat);
461 crl.format = f.get();
463 prop = e->getFirstChild()->getNodeValue();
464 auto_ptr_char crlpath(prop);
465 crl.source = crlpath.get();
467 prop = e->getAttributeNS(NULL,backingFilePath);
469 throw XMLSecurityException("FilesystemCredentialResolver can't access CRL, backingFilePath missing from URL element.");
470 auto_ptr_char b(prop);
471 crl.backing = b.get();
472 XMLToolingConfig::getConfig().getPathResolver()->resolve(crl.backing, PathResolver::XMLTOOLING_RUN_FILE);
473 prop = e->getAttributeNS(NULL,_reloadInterval);
475 crl.reloadInterval = XMLString::parseInt(prop);
477 e = XMLHelper::getNextSiblingElement(e,_URL);
479 if (m_crls.empty()) {
480 log.error("Path/URL element missing inside CRL element");
481 throw XMLSecurityException("FilesystemCredentialResolver can't access CRL, no Path or URL element specified.");
485 // Check for Certificate
486 DOMElement* certnode = XMLHelper::getFirstChildElement(root,Certificate);
488 prop = certnode->getAttributeNS(NULL,password);
490 auto_ptr_char certpass(prop);
491 m_certpass = certpass.get();
494 const XMLCh* certformat = certnode->getAttributeNS(NULL,_format);
496 const XMLCh* extractFlag = certnode->getAttributeNS(NULL, extractNames);
497 if (extractFlag && (*extractFlag == chLatin_f || *extractFlag == chDigit_0))
498 m_extractNames = false;
500 e = XMLHelper::getFirstChildElement(certnode);
502 if (e->hasChildNodes() && (XMLString::equals(e->getLocalName(), Path) || XMLString::equals(e->getLocalName(), CAPath))) {
503 m_certs.push_back(ManagedCert());
504 ManagedResource& cert = m_certs.back();
505 if (certformat && *certformat) {
506 auto_ptr_char f(certformat);
507 cert.format = f.get();
509 prop = e->getFirstChild()->getNodeValue();
510 auto_ptr_char certpath(prop);
511 cert.source = certpath.get();
512 XMLToolingConfig::getConfig().getPathResolver()->resolve(cert.source, PathResolver::XMLTOOLING_CFG_FILE);
514 prop = e->getAttributeNS(NULL,_reloadChanges);
515 if (prop && (*prop==chLatin_f) || (*prop==chDigit_0))
516 cert.reloadChanges = false;
518 else if (e->hasChildNodes() && XMLString::equals(e->getLocalName(), _URL)) {
519 m_certs.push_back(ManagedCert());
520 ManagedResource& cert = m_certs.back();
521 if (certformat && *certformat) {
522 auto_ptr_char f(certformat);
523 cert.format = f.get();
525 prop = e->getFirstChild()->getNodeValue();
526 auto_ptr_char certpath(prop);
527 cert.source = certpath.get();
529 prop = e->getAttributeNS(NULL,backingFilePath);
531 throw XMLSecurityException("FilesystemCredentialResolver can't access certificate, backingFilePath missing from URL element.");
532 auto_ptr_char b(prop);
533 cert.backing = b.get();
534 XMLToolingConfig::getConfig().getPathResolver()->resolve(cert.backing, PathResolver::XMLTOOLING_RUN_FILE);
535 prop = e->getAttributeNS(NULL,_reloadInterval);
537 cert.reloadInterval = XMLString::parseInt(prop);
539 e = XMLHelper::getNextSiblingElement(e);
541 if (m_certs.empty()) {
542 log.error("Path/URL element missing inside Certificate element");
543 throw XMLSecurityException("FilesystemCredentialResolver can't access certificate, no Path or URL element specified.");
547 // Do an initial load of all the objects. If anything blows up here, whatever's
548 // been loaded should be freed during teardown of the embedded objects.
549 time_t now = time(NULL);
550 m_key.filestamp = now;
551 m_key.load(log, m_keypass.c_str());
552 for (vector<ManagedCert>::iterator i = m_certs.begin(); i != m_certs.end(); ++i) {
553 i->load(log, (i==m_certs.begin()) ? m_certpass.c_str() : NULL);
556 for (vector<ManagedCRL>::iterator j = m_crls.begin(); j != m_crls.end(); ++j) {
561 // Load it all into a credential object and then create the lock.
562 auto_ptr<Credential> credential(getCredential());
563 m_lock = RWLock::create();
564 m_credential = credential.release();
567 FilesystemCredentialResolver::~FilesystemCredentialResolver()
573 Credential* FilesystemCredentialResolver::getCredential()
575 // First, verify that the key and certificate match.
576 if (m_key.key && !m_certs.empty()) {
577 auto_ptr<XSECCryptoKey> temp(m_certs.front().certs.front()->clonePublicKey());
578 if (!SecurityHelper::matches(*m_key.key, *temp.get()))
579 throw XMLSecurityException("FilesystemCredentialResolver given mismatched key/certificate, check for consistency.");
582 // We (unfortunately) need to duplicate all the objects and put them in one set of arrays
583 // in order to create the credential wrapper.
584 FilesystemCredential* credential=NULL;
585 auto_ptr<XSECCryptoKey> xseckey(m_key.key ? m_key.key->clone() : NULL);
586 vector<XSECCryptoX509*> xseccerts;
587 vector<XSECCryptoX509CRL*> xseccrls;
589 for (vector<ManagedCert>::iterator i = m_certs.begin(); i != m_certs.end(); ++i) {
590 for (vector<XSECCryptoX509*>::const_iterator y = i->certs.begin(); y != i->certs.end(); ++y)
591 xseccerts.push_back(new OpenSSLCryptoX509(static_cast<OpenSSLCryptoX509*>(*y)->getOpenSSLX509()));
593 for (vector<ManagedCRL>::iterator j = m_crls.begin(); j != m_crls.end(); ++j) {
594 for (vector<XSECCryptoX509CRL*>::const_iterator z = j->crls.begin(); z != j->crls.end(); ++z)
595 xseccrls.push_back((*z)->clone());
597 credential = new FilesystemCredential(this, xseckey.get(), xseccerts, xseccrls);
601 for_each(xseccerts.begin(), xseccerts.end(), xmltooling::cleanup<XSECCryptoX509>());
602 for_each(xseccrls.begin(), xseccrls.end(), xmltooling::cleanup<XSECCryptoX509CRL>());
606 // At this point the copies are owned by the credential.
608 credential->initKeyInfo(m_keyinfomask);
618 Lockable* FilesystemCredentialResolver::lock()
623 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".CredentialResolver."FILESYSTEM_CREDENTIAL_RESOLVER);
627 // Check each managed resource while holding a read lock for staleness.
628 // If it comes back false, the lock is left as is, and the resource was stable.
629 // If it comes back true, the lock was elevated to a write lock, and the resource
630 // needs to be reloaded, and the credential replaced.
631 // Once a stale check comes back true, further checks leave the lock alone.
633 bool writelock = false, updated = false;
635 if (m_key.stale(log, m_lock)) {
638 m_key.load(log, m_keypass.c_str());
641 catch (exception& ex) {
642 log.crit("maintaining existing key: %s", ex.what());
646 for (vector<ManagedCert>::iterator i = m_certs.begin(); i != m_certs.end(); ++i) {
647 if (i->stale(log, writelock ? NULL : m_lock)) {
650 i->load(log, (i==m_certs.begin()) ? m_certpass.c_str() : NULL);
653 catch (exception& ex) {
654 log.crit("maintaining existing certificate(s): %s", ex.what());
659 for (vector<ManagedCRL>::iterator j = m_crls.begin(); j != m_crls.end(); ++j) {
660 if (j->stale(log, writelock ? NULL : m_lock)) {
666 catch (exception& ex) {
667 log.crit("maintaining existing CRL(s): %s", ex.what());
674 auto_ptr<Credential> credential(getCredential());
676 m_credential = credential.release();
678 catch (exception& ex) {
679 log.crit("maintaining existing credentials, error reloading: %s", ex.what());
690 const Credential* FilesystemCredentialResolver::resolve(const CredentialCriteria* criteria) const
692 return (criteria ? (criteria->matches(*m_credential) ? m_credential : NULL) : m_credential);
695 vector<const Credential*>::size_type FilesystemCredentialResolver::resolve(
696 vector<const Credential*>& results, const CredentialCriteria* criteria
699 if (!criteria || criteria->matches(*m_credential)) {
700 results.push_back(m_credential);
706 // OpenSSL password callback...
707 static int passwd_callback(char* buf, int len, int verify, void* passwd)
711 if(passwd && len > strlen(reinterpret_cast<char*>(passwd)))
713 strcpy(buf,reinterpret_cast<char*>(passwd));
720 void FilesystemCredential::attach(SSL_CTX* ctx) const
727 const char* path = m_resolver->m_key.local ? m_resolver->m_key.source.c_str() : m_resolver->m_key.backing.c_str();
729 throw XMLSecurityException("No key available, unable to attach private key to SSL context.");
731 if (!m_resolver->m_keypass.empty()) {
732 SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
733 SSL_CTX_set_default_passwd_cb_userdata(ctx, const_cast<char*>(m_resolver->m_keypass.c_str()));
736 if (m_resolver->m_key.format == "PEM") {
737 ret=SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM);
739 else if (m_resolver->m_key.format == "DER") {
740 ret=SSL_CTX_use_RSAPrivateKey_file(ctx, path, SSL_FILETYPE_ASN1);
742 else if (m_resolver->m_key.format == "PKCS12") {
743 BIO* in=BIO_new(BIO_s_file_internal());
744 if (in && BIO_read_filename(in,path)>0) {
745 PKCS12* p12 = d2i_PKCS12_bio(in, NULL);
749 PKCS12_parse(p12, const_cast<char*>(m_resolver->m_keypass.c_str()), &pkey, &x, NULL);
754 ret=SSL_CTX_use_PrivateKey(ctx, pkey);
765 throw XMLSecurityException("Unable to attach private key to SSL context.");
769 for (vector<XSECCryptoX509*>::const_iterator i=m_xseccerts.begin(); i!=m_xseccerts.end(); i++) {
770 if (i==m_xseccerts.begin()) {
771 if (SSL_CTX_use_certificate(ctx, static_cast<OpenSSLCryptoX509*>(*i)->getOpenSSLX509()) != 1) {
773 throw XMLSecurityException("Unable to attach client certificate to SSL context.");
777 // When we add certs, they don't get ref counted, so we need to duplicate them.
778 X509* dup = X509_dup(static_cast<OpenSSLCryptoX509*>(*i)->getOpenSSLX509());
779 if (SSL_CTX_add_extra_chain_cert(ctx, dup) != 1) {
782 throw XMLSecurityException("Unable to attach CA certificate to SSL context.");