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/Client/CoreClient.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/Client/CoreClient.cpp')
| -rw-r--r-- | Swiften/Client/CoreClient.cpp | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp index de12fb7..36bfe35 100644 --- a/Swiften/Client/CoreClient.cpp +++ b/Swiften/Client/CoreClient.cpp @@ -94,89 +94,114 @@ void CoreClient::connect(const std::string& host) { networkFactories->getDomainNameResolver(), host, options.boshHTTPConnectProxyURL, options.boshHTTPConnectProxyAuthID, options.boshHTTPConnectProxyAuthPassword)); sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); bindSessionToStream(); } } void CoreClient::bindSessionToStream() { session_ = ClientSession::create(jid_, sessionStream_); session_->setCertificateTrustChecker(certificateTrustChecker); session_->setUseStreamCompression(options.useStreamCompression); session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS); switch(options.useTLS) { case ClientOptions::UseTLSWhenAvailable: session_->setUseTLS(ClientSession::UseTLSWhenAvailable); break; case ClientOptions::NeverUseTLS: session_->setUseTLS(ClientSession::NeverUseTLS); break; case ClientOptions::RequireTLS: session_->setUseTLS(ClientSession::RequireTLS); 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()) { - sessionStream_->setTLSCertificate(PKCS12Certificate(certificate_, password_)); + 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); } sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); bindSessionToStream(); } } void CoreClient::disconnect() { // FIXME: We should be able to do without this boolean. We just have to make sure we can tell the difference between // connector finishing without a connection due to an error or because of a disconnect. disconnectRequested_ = true; if (session_ && !session_->isFinished()) { session_->finish(); } else if (connector_) { connector_->stop(); } } void CoreClient::setCertificate(const std::string& certificate) { certificate_ = certificate; } void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) { if (options.forgetPassword) { purgePassword(); } resetSession(); boost::optional<ClientError> actualError; if (error) { ClientError clientError; if (boost::shared_ptr<ClientSession::Error> actualError = boost::dynamic_pointer_cast<ClientSession::Error>(error)) { switch(actualError->type) { |
Swift