diff options
author | Alexey Melnikov <alexey.melnikov@isode.com> | 2012-02-13 17:54:23 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2012-02-22 14:08:13 (GMT) |
commit | 110eb87e848b85dd74a6f19413c775520a75ea35 (patch) | |
tree | b10236387180fca676a29f24c747c9d0fd94d8dd /Swiften/TLS/OpenSSL/OpenSSLContext.cpp | |
parent | 64fc103d0d5d1d523d00dcc5b231715160475f7e (diff) | |
download | swift-contrib-110eb87e848b85dd74a6f19413c775520a75ea35.zip swift-contrib-110eb87e848b85dd74a6f19413c775520a75ea35.tar.bz2 |
Initial implementation of using CAPI certificates with Schannel.
Introduced a new parent class for all certificates with keys
(class CertificateWithKey is the new parent for PKCS12Certificate.)
Switched to using "CertificateWithKey *" instead of "const CertificateWithKey&"
Added calling of a Windows dialog for certificate selection when Schannel
TLS implementation is used.
This compiles, but is not tested.
License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details.
Diffstat (limited to 'Swiften/TLS/OpenSSL/OpenSSLContext.cpp')
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContext.cpp | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp index 220e7f9..dd3462f 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp @@ -1,59 +1,59 @@ /* * Copyright (c) 2010 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiften/Base/Platform.h> #ifdef SWIFTEN_PLATFORM_WINDOWS #include <windows.h> #include <wincrypt.h> #endif #include <vector> #include <openssl/err.h> #include <openssl/pkcs12.h> #include <boost/smart_ptr/make_shared.hpp> #if defined(SWIFTEN_PLATFORM_MACOSX) && OPENSSL_VERSION_NUMBER < 0x00908000 #include <Security/Security.h> #endif #include <Swiften/TLS/OpenSSL/OpenSSLContext.h> #include <Swiften/TLS/OpenSSL/OpenSSLCertificate.h> -#include <Swiften/TLS/PKCS12Certificate.h> +#include <Swiften/TLS/CertificateWithKey.h> #pragma GCC diagnostic ignored "-Wold-style-cast" namespace Swift { static const int MAX_FINISHED_SIZE = 4096; static const int SSL_READ_BUFFERSIZE = 8192; void freeX509Stack(STACK_OF(X509)* stack) { sk_X509_free(stack); } OpenSSLContext::OpenSSLContext() : state_(Start), context_(0), handle_(0), readBIO_(0), writeBIO_(0) { ensureLibraryInitialized(); context_ = SSL_CTX_new(TLSv1_client_method()); // Load system certs #if defined(SWIFTEN_PLATFORM_WINDOWS) X509_STORE* store = SSL_CTX_get_cert_store(context_); HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT"); if (systemStore) { PCCERT_CONTEXT certContext = NULL; while (true) { certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext); if (!certContext) { break; } OpenSSLCertificate cert(createByteArray(certContext->pbCertEncoded, certContext->cbCertEncoded)); if (store && cert.getInternalX509()) { X509_STORE_add_cert(store, cert.getInternalX509().get()); } } } #elif !defined(SWIFTEN_PLATFORM_MACOSX) SSL_CTX_load_verify_locations(context_, NULL, "/etc/ssl/certs"); @@ -153,89 +153,93 @@ void OpenSSLContext::handleDataFromNetwork(const SafeByteArray& data) { break; case Connected: sendPendingDataToApplication(); break; case Start: assert(false); break; case Error: /*assert(false);*/ break; } } void OpenSSLContext::handleDataFromApplication(const SafeByteArray& data) { if (SSL_write(handle_, vecptr(data), data.size()) >= 0) { sendPendingDataToNetwork(); } else { state_ = Error; onError(); } } void OpenSSLContext::sendPendingDataToApplication() { SafeByteArray data; data.resize(SSL_READ_BUFFERSIZE); int ret = SSL_read(handle_, vecptr(data), data.size()); while (ret > 0) { data.resize(ret); onDataForApplication(data); data.resize(SSL_READ_BUFFERSIZE); ret = SSL_read(handle_, vecptr(data), data.size()); } if (ret < 0 && SSL_get_error(handle_, ret) != SSL_ERROR_WANT_READ) { state_ = Error; onError(); } } -bool OpenSSLContext::setClientCertificate(const PKCS12Certificate& certificate) { - if (certificate.isNull()) { +bool OpenSSLContext::setClientCertificate(CertificateWithKey * certificate) { + if (!certificate || certificate->isNull()) { + return false; + } + + if (!certificate->isPrivateKeyExportable()) { return false; } // Create a PKCS12 structure BIO* bio = BIO_new(BIO_s_mem()); - BIO_write(bio, vecptr(certificate.getData()), certificate.getData().size()); + BIO_write(bio, vecptr(certificate->getData()), certificate->getData().size()); boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free); BIO_free(bio); if (!pkcs12) { return false; } // Parse PKCS12 X509 *certPtr = 0; EVP_PKEY* privateKeyPtr = 0; STACK_OF(X509)* caCertsPtr = 0; - int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(certificate.getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr); + int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(certificate->getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr); if (result != 1) { return false; } boost::shared_ptr<X509> cert(certPtr, X509_free); boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free); boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack); // Use the key & certificates if (SSL_CTX_use_certificate(context_, cert.get()) != 1) { return false; } if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) { return false; } for (int i = 0; i < sk_X509_num(caCerts.get()); ++i) { SSL_CTX_add_extra_chain_cert(context_, sk_X509_value(caCerts.get(), i)); } return true; } Certificate::ref OpenSSLContext::getPeerCertificate() const { boost::shared_ptr<X509> x509Cert(SSL_get_peer_certificate(handle_), X509_free); if (x509Cert) { return boost::make_shared<OpenSSLCertificate>(x509Cert); } else { return Certificate::ref(); } } boost::shared_ptr<CertificateVerificationError> OpenSSLContext::getPeerCertificateVerificationError() const { int verifyResult = SSL_get_verify_result(handle_); if (verifyResult != X509_V_OK) { return boost::make_shared<CertificateVerificationError>(getVerificationErrorTypeForResult(verifyResult)); } |