diff options
author | Kevin Smith <git@kismith.co.uk> | 2012-02-22 13:31:39 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2012-02-22 14:16:18 (GMT) |
commit | fa705718be1f98185557a09cf155ed66cbc740e2 (patch) | |
tree | b73c65981c6e879df40c40c4b5436a4d4386e5a4 /Swiften | |
parent | 110eb87e848b85dd74a6f19413c775520a75ea35 (diff) | |
download | swift-contrib-fa705718be1f98185557a09cf155ed66cbc740e2.zip swift-contrib-fa705718be1f98185557a09cf155ed66cbc740e2.tar.bz2 |
Fix up for previous CAPI patch
Now connects successfully with or without TLS(with cert)
Diffstat (limited to 'Swiften')
-rw-r--r-- | Swiften/Client/CoreClient.cpp | 31 | ||||
-rw-r--r-- | Swiften/Client/CoreClient.h | 12 | ||||
-rw-r--r-- | Swiften/Session/SessionStream.cpp | 1 | ||||
-rw-r--r-- | Swiften/Session/SessionStream.h | 10 | ||||
-rw-r--r-- | Swiften/StreamStack/TLSLayer.cpp | 2 | ||||
-rw-r--r-- | Swiften/StreamStack/TLSLayer.h | 4 | ||||
-rw-r--r-- | Swiften/TLS/CAPICertificate.cpp | 151 | ||||
-rw-r--r-- | Swiften/TLS/CAPICertificate.h | 176 | ||||
-rw-r--r-- | Swiften/TLS/CertificateWithKey.h | 12 | ||||
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContext.cpp | 11 | ||||
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContext.h | 2 | ||||
-rw-r--r-- | Swiften/TLS/SConscript | 1 | ||||
-rw-r--r-- | Swiften/TLS/Schannel/SchannelContext.cpp | 27 | ||||
-rw-r--r-- | Swiften/TLS/Schannel/SchannelContext.h | 2 | ||||
-rw-r--r-- | Swiften/TLS/TLSContext.h | 4 |
15 files changed, 204 insertions, 242 deletions
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp index 36bfe35..e2a8e5a 100644 --- a/Swiften/Client/CoreClient.cpp +++ b/Swiften/Client/CoreClient.cpp @@ -120,62 +120,37 @@ void CoreClient::bindSessionToStream() { break; } session_->setUseAcks(options.useAcks); stanzaChannel_->setSession(session_); session_->onFinished.connect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); session_->onNeedCredentials.connect(boost::bind(&CoreClient::handleNeedCredentials, this)); session_->start(); } -bool CoreClient::isCAPIURI() { -#ifdef HAVE_SCHANNEL - if (!boost::iequals(certificate_.substr(0, 10), "certstore:")) { - return false; - } - - return true; - -#else - return false; -#endif -} - /** * Only called for TCP sessions. BOSH is handled inside the BOSHSessionStream. */ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection) { resetConnector(); if (!connection) { if (options.forgetPassword) { purgePassword(); } onDisconnected(disconnectRequested_ ? boost::optional<ClientError>() : boost::optional<ClientError>(ClientError::ConnectionError)); } else { assert(!connection_); connection_ = connection; assert(!sessionStream_); sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory()); - if (!certificate_.empty()) { - CertificateWithKey* cert; - -#if defined(SWIFTEN_PLATFORM_WIN32) - if (isCAPIURI()) { - cert = new CAPICertificate(certificate_); - } else { - cert = new PKCS12Certificate(certificate_, password_); - } -#else - cert = new PKCS12Certificate(certificate_, password_); -#endif - - sessionStream_->setTLSCertificate(cert); + if (certificate_ && !certificate_->isNull()) { + sessionStream_->setTLSCertificate(certificate_); } sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); bindSessionToStream(); } } void CoreClient::disconnect() { @@ -184,19 +159,19 @@ void CoreClient::disconnect() { disconnectRequested_ = true; if (session_ && !session_->isFinished()) { session_->finish(); } else if (connector_) { connector_->stop(); } } -void CoreClient::setCertificate(const std::string& certificate) { +void CoreClient::setCertificate(CertificateWithKey::ref certificate) { certificate_ = certificate; } void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) { if (options.forgetPassword) { purgePassword(); } resetSession(); diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h index 6712e03..1b875d2 100644 --- a/Swiften/Client/CoreClient.h +++ b/Swiften/Client/CoreClient.h @@ -1,26 +1,27 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2012 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <string> #include <boost/shared_ptr.hpp> #include <Swiften/Base/boost_bsignals.h> #include <Swiften/Entity/Entity.h> #include <Swiften/JID/JID.h> #include <Swiften/Client/ClientError.h> #include <Swiften/Client/ClientOptions.h> #include <Swiften/Base/SafeByteArray.h> +#include <Swiften/TLS/CertificateWithKey.h> namespace Swift { class ChainedConnector; class Message; class Presence; class Error; class IQRouter; class TLSContextFactory; class ConnectionFactory; @@ -47,19 +48,24 @@ namespace Swift { class CoreClient : public Entity { public: /** * Constructs a client for the given JID with the given password. * The given eventLoop will be used to post events to. */ CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories); ~CoreClient(); - void setCertificate(const std::string& certificate); + /** + * Set a client certificate to use for strong authentication with the server. + * Ensure that it is of the correct type for the TLS engine in use. + * This means, largely, PKCS12Certificate for OpenSSL and CAPICertificate for CAPI. + */ + void setCertificate(CertificateWithKey::ref certificate); /** * Connects the client to the server. * * After the connection is established, the client will set * initialize the stream and authenticate. */ void connect(const ClientOptions& = ClientOptions()); @@ -221,14 +227,14 @@ namespace Swift { NetworkFactories* networkFactories; ClientSessionStanzaChannel* stanzaChannel_; IQRouter* iqRouter_; ClientOptions options; boost::shared_ptr<ChainedConnector> connector_; std::vector<ConnectionFactory*> proxyConnectionFactories; boost::shared_ptr<Connection> connection_; boost::shared_ptr<SessionStream> sessionStream_; boost::shared_ptr<ClientSession> session_; - std::string certificate_; + CertificateWithKey::ref certificate_; bool disconnectRequested_; CertificateTrustChecker* certificateTrustChecker; }; } diff --git a/Swiften/Session/SessionStream.cpp b/Swiften/Session/SessionStream.cpp index 487ad8b..0d73b63 100644 --- a/Swiften/Session/SessionStream.cpp +++ b/Swiften/Session/SessionStream.cpp @@ -3,13 +3,12 @@ * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiften/Session/SessionStream.h> namespace Swift { SessionStream::~SessionStream() { - delete certificate; } }; diff --git a/Swiften/Session/SessionStream.h b/Swiften/Session/SessionStream.h index 58015b3..2ff2a56 100644 --- a/Swiften/Session/SessionStream.h +++ b/Swiften/Session/SessionStream.h @@ -1,11 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2012 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <Swiften/Base/boost_bsignals.h> #include <boost/shared_ptr.hpp> #include <boost/optional.hpp> @@ -30,19 +30,19 @@ namespace Swift { ConnectionReadError, ConnectionWriteError }; Error(Type type) : type(type) {} Type type; }; - SessionStream(): certificate(0) {} + SessionStream(): certificate() {} virtual ~SessionStream(); virtual void close() = 0; virtual bool isOpen() = 0; virtual void writeHeader(const ProtocolHeader& header) = 0; virtual void writeFooter() = 0; virtual void writeElement(boost::shared_ptr<Element>) = 0; @@ -52,19 +52,19 @@ namespace Swift { virtual void addZLibCompression() = 0; virtual bool supportsTLSEncryption() = 0; virtual void addTLSEncryption() = 0; virtual bool isTLSEncrypted() = 0; virtual void setWhitespacePingEnabled(bool enabled) = 0; virtual void resetXMPPParser() = 0; - void setTLSCertificate(CertificateWithKey* cert) { + void setTLSCertificate(CertificateWithKey::ref cert) { certificate = cert; } virtual bool hasTLSCertificate() { return certificate && !certificate->isNull(); } virtual Certificate::ref getPeerCertificate() const = 0; virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const = 0; @@ -73,17 +73,17 @@ namespace Swift { boost::signal<void (const ProtocolHeader&)> onStreamStartReceived; boost::signal<void (boost::shared_ptr<Element>)> onElementReceived; boost::signal<void (boost::shared_ptr<Error>)> onClosed; boost::signal<void ()> onTLSEncrypted; boost::signal<void (const SafeByteArray&)> onDataRead; boost::signal<void (const SafeByteArray&)> onDataWritten; protected: - CertificateWithKey * getTLSCertificate() const { + CertificateWithKey::ref getTLSCertificate() const { return certificate; } private: - CertificateWithKey * certificate; + CertificateWithKey::ref certificate; }; } diff --git a/Swiften/StreamStack/TLSLayer.cpp b/Swiften/StreamStack/TLSLayer.cpp index b7efbcb..6d416bc 100644 --- a/Swiften/StreamStack/TLSLayer.cpp +++ b/Swiften/StreamStack/TLSLayer.cpp @@ -31,19 +31,19 @@ void TLSLayer::connect() { void TLSLayer::writeData(const SafeByteArray& data) { context->handleDataFromApplication(data); } void TLSLayer::handleDataRead(const SafeByteArray& data) { context->handleDataFromNetwork(data); } -bool TLSLayer::setClientCertificate(CertificateWithKey * certificate) { +bool TLSLayer::setClientCertificate(CertificateWithKey::ref certificate) { return context->setClientCertificate(certificate); } Certificate::ref TLSLayer::getPeerCertificate() const { return context->getPeerCertificate(); } boost::shared_ptr<CertificateVerificationError> TLSLayer::getPeerCertificateVerificationError() const { return context->getPeerCertificateVerificationError(); diff --git a/Swiften/StreamStack/TLSLayer.h b/Swiften/StreamStack/TLSLayer.h index 6dc9135..5aab26a 100644 --- a/Swiften/StreamStack/TLSLayer.h +++ b/Swiften/StreamStack/TLSLayer.h @@ -3,32 +3,32 @@ * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiften/Base/boost_bsignals.h> #include <Swiften/Base/SafeByteArray.h> #include <Swiften/StreamStack/StreamLayer.h> #include <Swiften/TLS/Certificate.h> +#include <Swiften/TLS/CertificateWithKey.h> #include <Swiften/TLS/CertificateVerificationError.h> namespace Swift { class TLSContext; class TLSContextFactory; - class CertificateWithKey; class TLSLayer : public StreamLayer { public: TLSLayer(TLSContextFactory*); ~TLSLayer(); void connect(); - bool setClientCertificate(CertificateWithKey * cert); + bool setClientCertificate(CertificateWithKey::ref cert); Certificate::ref getPeerCertificate() const; boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; void writeData(const SafeByteArray& data); void handleDataRead(const SafeByteArray& data); TLSContext* getContext() const { return context; diff --git a/Swiften/TLS/CAPICertificate.cpp b/Swiften/TLS/CAPICertificate.cpp new file mode 100644 index 0000000..9a3bbc8 --- /dev/null +++ b/Swiften/TLS/CAPICertificate.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2012 Isode Limited, London, England. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ +#pragma once + +#include <Swiften/TLS/CAPICertificate.h> + +#include <boost/algorithm/string/predicate.hpp> + + +namespace Swift { +CAPICertificate::CAPICertificate(const std::string& capiUri) + : valid_(false), uri_(capiUri), certStoreHandle_(0), certStore_(), certName_() { + setUri(capiUri); +} + +CAPICertificate::~CAPICertificate() { + if (certStoreHandle_) { + CertCloseStore(certStoreHandle_, 0); + } +} + +bool CAPICertificate::isNull() const { + return uri_.empty() || !valid_; +} + +const std::string& CAPICertificate::getCertStoreName() const { + return certStore_; +} + +const std::string& CAPICertificate::getCertName() const { + return certName_; +} + +void CAPICertificate::setUri (const std::string& capiUri) { + + valid_ = false; + + /* Syntax: "certstore:" [<cert_store> ":"] <cert_id> */ + + if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) { + return; + } + + /* Substring of subject: uses "storename" */ + std::string capi_identity = capiUri.substr(10); + std::string new_certStore_name; + size_t pos = capi_identity.find_first_of (':'); + + if (pos == std::string::npos) { + /* Using the default certificate store */ + new_certStore_name = "MY"; + certName_ = capi_identity; + } + else { + new_certStore_name = capi_identity.substr(0, pos); + certName_ = capi_identity.substr(pos + 1); + } + + PCCERT_CONTEXT pCertContext = NULL; + + if (certStoreHandle_ != NULL) { + if (new_certStore_name != certStore_) { + CertCloseStore(certStoreHandle_, 0); + certStoreHandle_ = NULL; + } + } + + if (certStoreHandle_ == NULL) { + certStoreHandle_ = CertOpenSystemStore(0, certStore_.c_str()); + if (!certStoreHandle_) { + return; + } + } + + certStore_ = new_certStore_name; + + /* NB: This might have to change, depending on how we locate certificates */ + + // Find client certificate. Note that this sample just searches for a + // certificate that contains the user name somewhere in the subject name. + pCertContext = CertFindCertificateInStore(certStoreHandle_, + X509_ASN_ENCODING, + 0, // dwFindFlags + CERT_FIND_SUBJECT_STR_A, + certName_.c_str(), // *pvFindPara + NULL ); // pPrevCertContext + + if (!pCertContext) { + return; + } + + + /* Now verify that we can have access to the corresponding private key */ + + DWORD len; + CRYPT_KEY_PROV_INFO *pinfo; + HCRYPTPROV hprov; + HCRYPTKEY key; + + if (!CertGetCertificateContextProperty(pCertContext, + CERT_KEY_PROV_INFO_PROP_ID, + NULL, + &len)) { + CertFreeCertificateContext(pCertContext); + return; + } + + pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len)); + if (!pinfo) { + CertFreeCertificateContext(pCertContext); + return; + } + + if (!CertGetCertificateContextProperty(pCertContext, + CERT_KEY_PROV_INFO_PROP_ID, + pinfo, + &len)) { + CertFreeCertificateContext(pCertContext); + free(pinfo); + return; + } + + CertFreeCertificateContext(pCertContext); + + // Now verify if we have access to the private key + if (!CryptAcquireContextW(&hprov, + pinfo->pwszContainerName, + pinfo->pwszProvName, + pinfo->dwProvType, + 0)) { + free(pinfo); + return; + } + + if (!CryptGetUserKey(hprov, pinfo->dwKeySpec, &key)) { + CryptReleaseContext(hprov, 0); + free(pinfo); + return; + } + + CryptDestroyKey(key); + CryptReleaseContext(hprov, 0); + free(pinfo); + + valid_ = true; +} + +} diff --git a/Swiften/TLS/CAPICertificate.h b/Swiften/TLS/CAPICertificate.h index fcdb4c2..d9e2704 100644 --- a/Swiften/TLS/CAPICertificate.h +++ b/Swiften/TLS/CAPICertificate.h @@ -3,194 +3,40 @@ * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #pragma once #include <Swiften/Base/SafeByteArray.h> #include <Swiften/TLS/CertificateWithKey.h> -#include <boost/algorithm/string/predicate.hpp> - #define SECURITY_WIN32 +#include <Windows.h> #include <WinCrypt.h> namespace Swift { class CAPICertificate : public Swift::CertificateWithKey { public: - CAPICertificate(const std::string& capiUri) - : valid_(false), uri_(capiUri), cert_store_handle_(0), cert_store_(NULL), cert_name_(NULL) { - setUri(capiUri); - } - - virtual ~CAPICertificate() { - if (cert_store_handle_ != NULL) - { - CertCloseStore(cert_store_handle_, 0); - } - } - - virtual bool isNull() const { - return uri_.empty() || !valid_; - } - - virtual bool isPrivateKeyExportable() const { - /* We can check with CAPI, but for now the answer is "no" */ - return false; - } - - virtual const std::string& getCertStoreName() const { - return cert_store_; - } - - virtual const std::string& getCertName() const { - return cert_name_; - } - - const ByteArray& getData() const { -////Might need to throw an exception here, or really generate PKCS12 blob from CAPI data? - assert(0); - } - - void setData(const ByteArray& data) { - assert(0); - } - - const SafeByteArray& getPassword() const { -/////Can't pass NULL to createSafeByteArray! -/////Should this throw an exception instead? - return createSafeByteArray(""); - } - - protected: - void setUri (const std::string& capiUri) { - - valid_ = false; - - /* Syntax: "certstore:" [<cert_store> ":"] <cert_id> */ - - if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) { - return; - } - - /* Substring of subject: uses "storename" */ - std::string capi_identity = capiUri.substr(10); - std::string new_cert_store_name; - size_t pos = capi_identity.find_first_of (':'); - - if (pos == std::string::npos) { - /* Using the default certificate store */ - new_cert_store_name = "MY"; - cert_name_ = capi_identity; - } else { - new_cert_store_name = capi_identity.substr(0, pos); - cert_name_ = capi_identity.substr(pos + 1); - } + CAPICertificate(const std::string& capiUri); - PCCERT_CONTEXT pCertContext = NULL; + virtual ~CAPICertificate(); - if (cert_store_handle_ != NULL) - { - if (new_cert_store_name != cert_store_) { - CertCloseStore(cert_store_handle_, 0); - cert_store_handle_ = NULL; - } - } + virtual bool isNull() const; - if (cert_store_handle_ == NULL) - { - cert_store_handle_ = CertOpenSystemStore(0, cert_store_.c_str()); - if (!cert_store_handle_) - { - return; - } - } + const std::string& getCertStoreName() const; - cert_store_ = new_cert_store_name; + const std::string& getCertName() const; - /* NB: This might have to change, depending on how we locate certificates */ - - // Find client certificate. Note that this sample just searches for a - // certificate that contains the user name somewhere in the subject name. - pCertContext = CertFindCertificateInStore(cert_store_handle_, - X509_ASN_ENCODING, - 0, // dwFindFlags - CERT_FIND_SUBJECT_STR_A, - cert_name_.c_str(), // *pvFindPara - NULL ); // pPrevCertContext - - if (pCertContext == NULL) - { - return; - } - - - /* Now verify that we can have access to the corresponding private key */ - - DWORD len; - CRYPT_KEY_PROV_INFO *pinfo; - HCRYPTPROV hprov; - HCRYPTKEY key; - - if (!CertGetCertificateContextProperty(pCertContext, - CERT_KEY_PROV_INFO_PROP_ID, - NULL, - &len)) - { - CertFreeCertificateContext(pCertContext); - return; - } - - pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len)); - if (!pinfo) { - CertFreeCertificateContext(pCertContext); - return; - } - - if (!CertGetCertificateContextProperty(pCertContext, - CERT_KEY_PROV_INFO_PROP_ID, - pinfo, - &len)) - { - CertFreeCertificateContext(pCertContext); - free(pinfo); - return; - } - - CertFreeCertificateContext(pCertContext); - - // Now verify if we have access to the private key - if (!CryptAcquireContextW(&hprov, - pinfo->pwszContainerName, - pinfo->pwszProvName, - pinfo->dwProvType, - 0)) - { - free(pinfo); - return; - } - - if (!CryptGetUserKey(hprov, pinfo->dwKeySpec, &key)) - { - CryptReleaseContext(hprov, 0); - free(pinfo); - return; - } - - CryptDestroyKey(key); - CryptReleaseContext(hprov, 0); - free(pinfo); - - valid_ = true; - } + private: + void setUri (const std::string& capiUri); private: bool valid_; std::string uri_; - HCERTSTORE cert_store_handle_; + HCERTSTORE certStoreHandle_; /* Parsed components of the uri_ */ - std::string cert_store_; - std::string cert_name_; + std::string certStore_; + std::string certName_; }; } diff --git a/Swiften/TLS/CertificateWithKey.h b/Swiften/TLS/CertificateWithKey.h index 6f6ea39..1bdeb03 100644 --- a/Swiften/TLS/CertificateWithKey.h +++ b/Swiften/TLS/CertificateWithKey.h @@ -5,28 +5,18 @@ */ #pragma once #include <Swiften/Base/SafeByteArray.h> namespace Swift { class CertificateWithKey { public: + typedef boost::shared_ptr<CertificateWithKey> ref; CertificateWithKey() {} virtual ~CertificateWithKey() {} virtual bool isNull() const = 0; - virtual bool isPrivateKeyExportable() const = 0; - - virtual const std::string& getCertStoreName() const = 0; - - virtual const std::string& getCertName() const = 0; - - virtual const ByteArray& getData() const = 0; - - virtual void setData(const ByteArray& data) = 0; - - virtual const SafeByteArray& getPassword() const = 0; }; } diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp index dd3462f..8076967 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp @@ -180,40 +180,37 @@ void OpenSSLContext::sendPendingDataToApplication() { 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(CertificateWithKey * certificate) { - if (!certificate || certificate->isNull()) { - return false; - } - - if (!certificate->isPrivateKeyExportable()) { + boost::shared_ptr<PKCS12Certificate> pkcs12Certificate = boost::dynamic_pointer_cast<PKCS12Certificate>(certificate); + if (!pkcs12Certificate || pkcs12Certificate->isNull()) { 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()), pkcs12Certificate->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(pkcs12Certificate->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) { diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.h b/Swiften/TLS/OpenSSL/OpenSSLContext.h index b53e715..e98fb49 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.h +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.h @@ -16,19 +16,19 @@ namespace Swift { class CertificateWithKey; class OpenSSLContext : public TLSContext, boost::noncopyable { public: OpenSSLContext(); ~OpenSSLContext(); void connect(); - bool setClientCertificate(CertificateWithKey * cert); + bool setClientCertificate(CertificateWithKey::ref cert); void handleDataFromNetwork(const SafeByteArray&); void handleDataFromApplication(const SafeByteArray&); Certificate::ref getPeerCertificate() const; boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; virtual ByteArray getFinishMessage() const; diff --git a/Swiften/TLS/SConscript b/Swiften/TLS/SConscript index a71a446..0e95b8b 100644 --- a/Swiften/TLS/SConscript +++ b/Swiften/TLS/SConscript @@ -14,18 +14,19 @@ if myenv.get("HAVE_OPENSSL", 0) : myenv.MergeFlags(myenv["OPENSSL_FLAGS"]) objects += myenv.SwiftenObject([ "OpenSSL/OpenSSLContext.cpp", "OpenSSL/OpenSSLCertificate.cpp", "OpenSSL/OpenSSLContextFactory.cpp", ]) myenv.Append(CPPDEFINES = "HAVE_OPENSSL") elif myenv.get("HAVE_SCHANNEL", 0) : objects += myenv.StaticObject([ + "CAPICertificate.cpp", "Schannel/SchannelContext.cpp", "Schannel/SchannelCertificate.cpp", "Schannel/SchannelContextFactory.cpp", ]) myenv.Append(CPPDEFINES = "HAVE_SCHANNEL") objects += myenv.SwiftenObject(["PlatformTLSFactories.cpp"]) diff --git a/Swiften/TLS/Schannel/SchannelContext.cpp b/Swiften/TLS/Schannel/SchannelContext.cpp index 6f50b3a..ddbebcb 100644 --- a/Swiften/TLS/Schannel/SchannelContext.cpp +++ b/Swiften/TLS/Schannel/SchannelContext.cpp @@ -1,29 +1,30 @@ /* * Copyright (c) 2011 Soren Dreijer * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "Swiften/TLS/Schannel/SchannelContext.h" -#include "Swiften/TLS/Schannel/SchannelCertificate.h" +#include <Swiften/TLS/Schannel/SchannelContext.h> +#include <Swiften/TLS/Schannel/SchannelCertificate.h> +#include <Swiften/TLS/CAPICertificate.h> namespace Swift { //------------------------------------------------------------------------ SchannelContext::SchannelContext() : m_state(Start) , m_secContext(0) , m_verificationError(CertificateVerificationError::UnknownError) , m_my_cert_store(NULL) , m_cert_store_name("MY") -, m_cert_name(NULL) +, m_cert_name() { m_ctxtFlags = ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_EXTENDED_ERROR | ISC_REQ_INTEGRITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_USE_SUPPLIED_CREDS | ISC_REQ_STREAM; @@ -511,34 +512,30 @@ void SchannelContext::encryptAndSendData(const SafeByteArray& data) sendDataOnNetwork(&sendBuffer[0], outBuffers[0].cbBuffer + outBuffers[1].cbBuffer + outBuffers[2].cbBuffer); bytesSent += bytesToSend; } while (bytesSent < data.size()); } //------------------------------------------------------------------------ -bool SchannelContext::setClientCertificate(CertificateWithKey * certificate) +bool SchannelContext::setClientCertificate(CertificateWithKey::ref certificate) { - if (!certificate || certificate->isNull()) { + boost::shared_ptr<CAPICertificate> capiCertificate = boost::dynamic_pointer_cast<CAPICertificate>(certificate); + if (!capiCertificate || capiCertificate->isNull()) { return false; } - if (!certificate->isPrivateKeyExportable()) { - // We assume that the Certificate Store Name/Certificate Name - // are valid at this point - m_cert_store_name = certificate->getCertStoreName(); - m_cert_name = certificate->getCertName(); - - return true; - } - - return false; + // We assume that the Certificate Store Name/Certificate Name + // are valid at this point + m_cert_store_name = capiCertificate->getCertStoreName(); + m_cert_name = capiCertificate->getCertName(); + return true; } //------------------------------------------------------------------------ Certificate::ref SchannelContext::getPeerCertificate() const { SchannelCertificate::ref pCertificate; ScopedCertContext pServerCert; diff --git a/Swiften/TLS/Schannel/SchannelContext.h b/Swiften/TLS/Schannel/SchannelContext.h index 0cdb3d7..7726c41 100644 --- a/Swiften/TLS/Schannel/SchannelContext.h +++ b/Swiften/TLS/Schannel/SchannelContext.h @@ -31,19 +31,19 @@ namespace Swift public: SchannelContext(); ~SchannelContext(); // // TLSContext // virtual void connect(); - virtual bool setClientCertificate(CertificateWithKey * cert); + virtual bool setClientCertificate(CertificateWithKey::ref cert); virtual void handleDataFromNetwork(const SafeByteArray& data); virtual void handleDataFromApplication(const SafeByteArray& data); virtual Certificate::ref getPeerCertificate() const; virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const; virtual ByteArray getFinishMessage() const; diff --git a/Swiften/TLS/TLSContext.h b/Swiften/TLS/TLSContext.h index ada813a..9dee902 100644 --- a/Swiften/TLS/TLSContext.h +++ b/Swiften/TLS/TLSContext.h @@ -5,30 +5,30 @@ */ #pragma once #include <Swiften/Base/boost_bsignals.h> #include <boost/shared_ptr.hpp> #include <Swiften/Base/SafeByteArray.h> #include <Swiften/TLS/Certificate.h> +#include <Swiften/TLS/CertificateWithKey.h> #include <Swiften/TLS/CertificateVerificationError.h> namespace Swift { - class CertificateWithKey; class TLSContext { public: virtual ~TLSContext(); virtual void connect() = 0; - virtual bool setClientCertificate(CertificateWithKey * cert) = 0; + virtual bool setClientCertificate(CertificateWithKey::ref cert) = 0; virtual void handleDataFromNetwork(const SafeByteArray&) = 0; virtual void handleDataFromApplication(const SafeByteArray&) = 0; virtual Certificate::ref getPeerCertificate() const = 0; virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const = 0; virtual ByteArray getFinishMessage() const = 0; |