diff options
| author | Kevin Smith <git@kismith.co.uk> | 2014-08-27 14:16:15 (GMT) |
|---|---|---|
| committer | Kevin Smith <kevin.smith@isode.com> | 2015-06-10 20:29:05 (GMT) |
| commit | b2093a372874aefb4f56f66a70a96f78d6cbbaec (patch) | |
| tree | ab779a4cc7950339d2c2cb0261ae6a08df84c645 | |
| parent | b6b0695643f932827add43b9de0e09ed74eb6799 (diff) | |
| download | swift-b2093a372874aefb4f56f66a70a96f78d6cbbaec.zip swift-b2093a372874aefb4f56f66a70a96f78d6cbbaec.tar.bz2 | |
Add ability to limit SChannel to TLS 1.0
Some servers have very restrictive TLS stacks that respond badly
to a bug in the SChannel TLS implementation, meaning that TLS
has to be limited to 1.0.
Add ClientOptions.tlsOptions. This is a method of passing options into
the TLS stack. It's currently
only used for the TLS 1.0 workaround in SChannel, but we might reasonably
expose other options in the future, such as limiting cypher suites.
Disables use of SSLv3 for SChannel
Also updates the coding style in SchannelContext a bit.
Test-Information:
Compiles on both OS X and Windows(SChannel). OS X doesn't show the new
option. Windows shows it, and remembers it between logins. Not tested
against a server requiring 1.0 only, but a previous hack with the
same approach was tested.
Change-Id: I1e7854d43811fd173f21f98d4dc3915fc7a4b322
27 files changed, 248 insertions, 162 deletions
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 328d837..c6b6dfc 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp | |||
| @@ -398,7 +398,7 @@ void MainController::handleConnected() { | |||
| 398 | userSearchControllerChat_ = new UserSearchController(UserSearchController::StartChat, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_, contactSuggesterWithRoster_, client_->getAvatarManager(), client_->getPresenceOracle()); | 398 | userSearchControllerChat_ = new UserSearchController(UserSearchController::StartChat, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_, contactSuggesterWithRoster_, client_->getAvatarManager(), client_->getPresenceOracle()); |
| 399 | userSearchControllerAdd_ = new UserSearchController(UserSearchController::AddContact, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_, contactSuggesterWithoutRoster_, client_->getAvatarManager(), client_->getPresenceOracle()); | 399 | userSearchControllerAdd_ = new UserSearchController(UserSearchController::AddContact, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_, contactSuggesterWithoutRoster_, client_->getAvatarManager(), client_->getPresenceOracle()); |
| 400 | adHocManager_ = new AdHocManager(JID(boundJID_.getDomain()), uiFactory_, client_->getIQRouter(), uiEventStream_, rosterController_->getWindow()); | 400 | adHocManager_ = new AdHocManager(JID(boundJID_.getDomain()), uiFactory_, client_->getIQRouter(), uiEventStream_, rosterController_->getWindow()); |
| 401 | 401 | ||
| 402 | chatsManager_->onImpromptuMUCServiceDiscovered.connect(boost::bind(&UserSearchController::setCanInitiateImpromptuMUC, userSearchControllerChat_, _1)); | 402 | chatsManager_->onImpromptuMUCServiceDiscovered.connect(boost::bind(&UserSearchController::setCanInitiateImpromptuMUC, userSearchControllerChat_, _1)); |
| 403 | } | 403 | } |
| 404 | loginWindow_->setIsLoggingIn(false); | 404 | loginWindow_->setIsLoggingIn(false); |
| @@ -410,7 +410,7 @@ void MainController::handleConnected() { | |||
| 410 | discoInfoRequest->send(); | 410 | discoInfoRequest->send(); |
| 411 | 411 | ||
| 412 | client_->getVCardManager()->requestOwnVCard(); | 412 | client_->getVCardManager()->requestOwnVCard(); |
| 413 | 413 | ||
| 414 | rosterController_->setJID(boundJID_); | 414 | rosterController_->setJID(boundJID_); |
| 415 | rosterController_->setEnabled(true); | 415 | rosterController_->setEnabled(true); |
| 416 | rosterController_->getWindow()->setStreamEncryptionStatus(client_->isStreamEncrypted()); | 416 | rosterController_->getWindow()->setStreamEncryptionStatus(client_->isStreamEncrypted()); |
| @@ -841,10 +841,11 @@ std::string MainController::serializeClientOptions(const ClientOptions& options) | |||
| 841 | SERIALIZE_URL(boshHTTPConnectProxyURL); | 841 | SERIALIZE_URL(boshHTTPConnectProxyURL); |
| 842 | SERIALIZE_SAFE_STRING(boshHTTPConnectProxyAuthID); | 842 | SERIALIZE_SAFE_STRING(boshHTTPConnectProxyAuthID); |
| 843 | SERIALIZE_SAFE_STRING(boshHTTPConnectProxyAuthPassword); | 843 | SERIALIZE_SAFE_STRING(boshHTTPConnectProxyAuthPassword); |
| 844 | SERIALIZE_BOOL(tlsOptions.schannelTLS1_0Workaround); | ||
| 844 | return result; | 845 | return result; |
| 845 | } | 846 | } |
| 846 | 847 | ||
| 847 | #define CHECK_PARSE_LENGTH if (i >= segments.size()) {return result;} | 848 | #define CHECK_PARSE_LENGTH if (i >= segments.size()) {return result;} |
| 848 | #define PARSE_INT_RAW(defaultValue) CHECK_PARSE_LENGTH intVal = defaultValue; try {intVal = boost::lexical_cast<int>(segments[i]);} catch(const boost::bad_lexical_cast&) {};i++; | 849 | #define PARSE_INT_RAW(defaultValue) CHECK_PARSE_LENGTH intVal = defaultValue; try {intVal = boost::lexical_cast<int>(segments[i]);} catch(const boost::bad_lexical_cast&) {};i++; |
| 849 | #define PARSE_STRING_RAW CHECK_PARSE_LENGTH stringVal = byteArrayToString(Base64::decode(segments[i]));i++; | 850 | #define PARSE_STRING_RAW CHECK_PARSE_LENGTH stringVal = byteArrayToString(Base64::decode(segments[i]));i++; |
| 850 | 851 | ||
| @@ -888,6 +889,7 @@ ClientOptions MainController::parseClientOptions(const std::string& optionString | |||
| 888 | PARSE_URL(boshHTTPConnectProxyURL); | 889 | PARSE_URL(boshHTTPConnectProxyURL); |
| 889 | PARSE_SAFE_STRING(boshHTTPConnectProxyAuthID); | 890 | PARSE_SAFE_STRING(boshHTTPConnectProxyAuthID); |
| 890 | PARSE_SAFE_STRING(boshHTTPConnectProxyAuthPassword); | 891 | PARSE_SAFE_STRING(boshHTTPConnectProxyAuthPassword); |
| 892 | PARSE_BOOL(tlsOptions.schannelTLS1_0Workaround, false); | ||
| 891 | 893 | ||
| 892 | return result; | 894 | return result; |
| 893 | } | 895 | } |
diff --git a/Swift/QtUI/QtConnectionSettings.ui b/Swift/QtUI/QtConnectionSettings.ui index 2dc46d1..cce60fe 100644 --- a/Swift/QtUI/QtConnectionSettings.ui +++ b/Swift/QtUI/QtConnectionSettings.ui | |||
| @@ -136,6 +136,13 @@ | |||
| 136 | </widget> | 136 | </widget> |
| 137 | </item> | 137 | </item> |
| 138 | <item> | 138 | <item> |
| 139 | <widget class="QCheckBox" name="manual_forceTLS1_0"> | ||
| 140 | <property name="text"> | ||
| 141 | <string>Limit encryption to TLS 1.0</string> | ||
| 142 | </property> | ||
| 143 | </widget> | ||
| 144 | </item> | ||
| 145 | <item> | ||
| 139 | <spacer name="verticalSpacer_2"> | 146 | <spacer name="verticalSpacer_2"> |
| 140 | <property name="orientation"> | 147 | <property name="orientation"> |
| 141 | <enum>Qt::Vertical</enum> | 148 | <enum>Qt::Vertical</enum> |
diff --git a/Swift/QtUI/QtConnectionSettingsWindow.cpp b/Swift/QtUI/QtConnectionSettingsWindow.cpp index a3598fa..7b5003a 100644 --- a/Swift/QtUI/QtConnectionSettingsWindow.cpp +++ b/Swift/QtUI/QtConnectionSettingsWindow.cpp | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012 Isode Limited. | 2 | * Copyright (c) 2012-2015 Isode Limited. |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * See the COPYING file for more information. | 4 | * See the COPYING file for more information. |
| 5 | */ | 5 | */ |
| @@ -67,6 +67,7 @@ QtConnectionSettingsWindow::QtConnectionSettingsWindow(const ClientOptions& opti | |||
| 67 | isDefault &= options.proxyType == defaults.proxyType; | 67 | isDefault &= options.proxyType == defaults.proxyType; |
| 68 | isDefault &= options.manualProxyHostname == defaults.manualProxyHostname; | 68 | isDefault &= options.manualProxyHostname == defaults.manualProxyHostname; |
| 69 | isDefault &= options.manualProxyPort == defaults.manualProxyPort; | 69 | isDefault &= options.manualProxyPort == defaults.manualProxyPort; |
| 70 | isDefault &= options.tlsOptions.schannelTLS1_0Workaround == defaults.tlsOptions.schannelTLS1_0Workaround; | ||
| 70 | if (isDefault) { | 71 | if (isDefault) { |
| 71 | ui.connectionMethod->setCurrentIndex(0); | 72 | ui.connectionMethod->setCurrentIndex(0); |
| 72 | } | 73 | } |
| @@ -88,6 +89,7 @@ QtConnectionSettingsWindow::QtConnectionSettingsWindow(const ClientOptions& opti | |||
| 88 | ui.manual_manualProxyHost->setText(P2QSTRING(options.manualProxyHostname)); | 89 | ui.manual_manualProxyHost->setText(P2QSTRING(options.manualProxyHostname)); |
| 89 | ui.manual_manualProxyPort->setText(P2QSTRING(boost::lexical_cast<std::string>(options.manualProxyPort))); | 90 | ui.manual_manualProxyPort->setText(P2QSTRING(boost::lexical_cast<std::string>(options.manualProxyPort))); |
| 90 | } | 91 | } |
| 92 | ui.manual_forceTLS1_0->setChecked(options.tlsOptions.schannelTLS1_0Workaround); | ||
| 91 | } | 93 | } |
| 92 | } else { | 94 | } else { |
| 93 | ui.connectionMethod->setCurrentIndex(2); | 95 | ui.connectionMethod->setCurrentIndex(2); |
| @@ -100,6 +102,9 @@ QtConnectionSettingsWindow::QtConnectionSettingsWindow(const ClientOptions& opti | |||
| 100 | } | 102 | } |
| 101 | } | 103 | } |
| 102 | } | 104 | } |
| 105 | #ifndef HAVE_SCHANNEL | ||
| 106 | ui.manual_forceTLS1_0->hide(); | ||
| 107 | #endif | ||
| 103 | } | 108 | } |
| 104 | 109 | ||
| 105 | void QtConnectionSettingsWindow::handleProxyTypeChanged(int index) { | 110 | void QtConnectionSettingsWindow::handleProxyTypeChanged(int index) { |
| @@ -129,6 +134,7 @@ ClientOptions QtConnectionSettingsWindow::getOptions() { | |||
| 129 | options.useTLS = static_cast<ClientOptions::UseTLS>(ui.manual_useTLS->currentIndex()); | 134 | options.useTLS = static_cast<ClientOptions::UseTLS>(ui.manual_useTLS->currentIndex()); |
| 130 | options.useStreamCompression = ui.manual_allowCompression->isChecked(); | 135 | options.useStreamCompression = ui.manual_allowCompression->isChecked(); |
| 131 | options.allowPLAINWithoutTLS = ui.manual_allowPLAINWithoutTLS->isChecked(); | 136 | options.allowPLAINWithoutTLS = ui.manual_allowPLAINWithoutTLS->isChecked(); |
| 137 | options.tlsOptions.schannelTLS1_0Workaround = ui.manual_forceTLS1_0->isChecked(); | ||
| 132 | if (ui.manual_manualHost->isChecked()) { | 138 | if (ui.manual_manualHost->isChecked()) { |
| 133 | options.manualHostname = Q2PSTRING(ui.manual_manualHostName->text()); | 139 | options.manualHostname = Q2PSTRING(ui.manual_manualHostName->text()); |
| 134 | try { | 140 | try { |
diff --git a/Swiften/Client/ClientOptions.h b/Swiften/Client/ClientOptions.h index 4aac609..25393e4 100644 --- a/Swiften/Client/ClientOptions.h +++ b/Swiften/Client/ClientOptions.h | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #include <Swiften/Base/API.h> | 11 | #include <Swiften/Base/API.h> |
| 12 | #include <Swiften/Base/URL.h> | 12 | #include <Swiften/Base/URL.h> |
| 13 | #include <Swiften/Base/SafeString.h> | 13 | #include <Swiften/Base/SafeString.h> |
| 14 | #include <Swiften/TLS/TLSOptions.h> | ||
| 15 | |||
| 14 | 16 | ||
| 15 | namespace Swift { | 17 | namespace Swift { |
| 16 | class HTTPTrafficFilter; | 18 | class HTTPTrafficFilter; |
| @@ -145,5 +147,10 @@ namespace Swift { | |||
| 145 | * proxy initialization to be customized. | 147 | * proxy initialization to be customized. |
| 146 | */ | 148 | */ |
| 147 | boost::shared_ptr<HTTPTrafficFilter> httpTrafficFilter; | 149 | boost::shared_ptr<HTTPTrafficFilter> httpTrafficFilter; |
| 150 | |||
| 151 | /** | ||
| 152 | * Options passed to the TLS stack | ||
| 153 | */ | ||
| 154 | TLSOptions tlsOptions; | ||
| 148 | }; | 155 | }; |
| 149 | } | 156 | } |
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp index 842488d..c91e5c5 100644 --- a/Swiften/Client/CoreClient.cpp +++ b/Swiften/Client/CoreClient.cpp | |||
| @@ -138,7 +138,8 @@ void CoreClient::connect(const ClientOptions& o) { | |||
| 138 | host, | 138 | host, |
| 139 | options.boshHTTPConnectProxyURL, | 139 | options.boshHTTPConnectProxyURL, |
| 140 | options.boshHTTPConnectProxyAuthID, | 140 | options.boshHTTPConnectProxyAuthID, |
| 141 | options.boshHTTPConnectProxyAuthPassword)); | 141 | options.boshHTTPConnectProxyAuthPassword, |
| 142 | options.tlsOptions)); | ||
| 142 | sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); | 143 | sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); |
| 143 | sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); | 144 | sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); |
| 144 | bindSessionToStream(); | 145 | bindSessionToStream(); |
| @@ -189,7 +190,7 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio | |||
| 189 | connection_ = connection; | 190 | connection_ = connection; |
| 190 | 191 | ||
| 191 | assert(!sessionStream_); | 192 | assert(!sessionStream_); |
| 192 | sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory()); | 193 | sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), options.tlsOptions); |
| 193 | if (certificate_ && !certificate_->isNull()) { | 194 | if (certificate_ && !certificate_->isNull()) { |
| 194 | sessionStream_->setTLSCertificate(certificate_); | 195 | sessionStream_->setTLSCertificate(certificate_); |
| 195 | } | 196 | } |
diff --git a/Swiften/Component/CoreComponent.cpp b/Swiften/Component/CoreComponent.cpp index 23b7759..358b0c6 100644 --- a/Swiften/Component/CoreComponent.cpp +++ b/Swiften/Component/CoreComponent.cpp | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2010-2013 Isode Limited. | 2 | * Copyright (c) 2010-2015 Isode Limited. |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * See the COPYING file for more information. | 4 | * See the COPYING file for more information. |
| 5 | */ | 5 | */ |
| @@ -9,14 +9,16 @@ | |||
| 9 | #include <boost/bind.hpp> | 9 | #include <boost/bind.hpp> |
| 10 | #include <iostream> | 10 | #include <iostream> |
| 11 | 11 | ||
| 12 | #include <Swiften/Base/IDGenerator.h> | ||
| 12 | #include <Swiften/Component/ComponentSession.h> | 13 | #include <Swiften/Component/ComponentSession.h> |
| 14 | #include <Swiften/Component/ComponentSessionStanzaChannel.h> | ||
| 13 | #include <Swiften/Network/Connector.h> | 15 | #include <Swiften/Network/Connector.h> |
| 14 | #include <Swiften/Network/NetworkFactories.h> | 16 | #include <Swiften/Network/NetworkFactories.h> |
| 15 | #include <Swiften/TLS/PKCS12Certificate.h> | ||
| 16 | #include <Swiften/Session/BasicSessionStream.h> | ||
| 17 | #include <Swiften/Queries/IQRouter.h> | 17 | #include <Swiften/Queries/IQRouter.h> |
| 18 | #include <Swiften/Base/IDGenerator.h> | 18 | #include <Swiften/Session/BasicSessionStream.h> |
| 19 | #include <Swiften/Component/ComponentSessionStanzaChannel.h> | 19 | #include <Swiften/TLS/PKCS12Certificate.h> |
| 20 | #include <Swiften/TLS/TLSOptions.h> | ||
| 21 | |||
| 20 | 22 | ||
| 21 | namespace Swift { | 23 | namespace Swift { |
| 22 | 24 | ||
| @@ -63,7 +65,7 @@ void CoreComponent::handleConnectorFinished(boost::shared_ptr<Connection> connec | |||
| 63 | connection_ = connection; | 65 | connection_ = connection; |
| 64 | 66 | ||
| 65 | assert(!sessionStream_); | 67 | assert(!sessionStream_); |
| 66 | sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), NULL, networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory())); | 68 | sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), NULL, networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), TLSOptions())); |
| 67 | sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1)); | 69 | sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1)); |
| 68 | sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); | 70 | sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); |
| 69 | 71 | ||
diff --git a/Swiften/Network/BOSHConnectionPool.cpp b/Swiften/Network/BOSHConnectionPool.cpp index 56f7d12..c037b34 100644 --- a/Swiften/Network/BOSHConnectionPool.cpp +++ b/Swiften/Network/BOSHConnectionPool.cpp | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2011 Isode Limited. | 2 | * Copyright (c) 2011-2015 Isode Limited. |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * See the COPYING file for more information. | 4 | * See the COPYING file for more information. |
| 5 | */ | 5 | */ |
| @@ -17,7 +17,7 @@ | |||
| 17 | #include <Swiften/Network/CachingDomainNameResolver.h> | 17 | #include <Swiften/Network/CachingDomainNameResolver.h> |
| 18 | 18 | ||
| 19 | namespace Swift { | 19 | namespace Swift { |
| 20 | BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* realResolver, ConnectionFactory* connectionFactoryParameter, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword) : | 20 | BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* realResolver, ConnectionFactory* connectionFactoryParameter, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword, const TLSOptions& tlsOptions) : |
| 21 | boshURL(boshURL), | 21 | boshURL(boshURL), |
| 22 | connectionFactory(connectionFactoryParameter), | 22 | connectionFactory(connectionFactoryParameter), |
| 23 | xmlParserFactory(parserFactory), | 23 | xmlParserFactory(parserFactory), |
| @@ -31,13 +31,13 @@ BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* r | |||
| 31 | 31 | ||
| 32 | if (!boshHTTPConnectProxyURL.isEmpty()) { | 32 | if (!boshHTTPConnectProxyURL.isEmpty()) { |
| 33 | if (boshHTTPConnectProxyURL.getScheme() == "https") { | 33 | if (boshHTTPConnectProxyURL.getScheme() == "https") { |
| 34 | connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory); | 34 | connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory, tlsOptions); |
| 35 | myConnectionFactories.push_back(connectionFactory); | 35 | myConnectionFactories.push_back(connectionFactory); |
| 36 | } | 36 | } |
| 37 | connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, boshHTTPConnectProxyURL.getHost(), URL::getPortOrDefaultPort(boshHTTPConnectProxyURL), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword); | 37 | connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, boshHTTPConnectProxyURL.getHost(), URL::getPortOrDefaultPort(boshHTTPConnectProxyURL), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword); |
| 38 | } | 38 | } |
| 39 | if (boshURL.getScheme() == "https") { | 39 | if (boshURL.getScheme() == "https") { |
| 40 | connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory); | 40 | connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory, tlsOptions); |
| 41 | myConnectionFactories.push_back(connectionFactory); | 41 | myConnectionFactories.push_back(connectionFactory); |
| 42 | } | 42 | } |
| 43 | resolver = new CachingDomainNameResolver(realResolver, eventLoop); | 43 | resolver = new CachingDomainNameResolver(realResolver, eventLoop); |
diff --git a/Swiften/Network/BOSHConnectionPool.h b/Swiften/Network/BOSHConnectionPool.h index 570ba4b..d845a3d 100644 --- a/Swiften/Network/BOSHConnectionPool.h +++ b/Swiften/Network/BOSHConnectionPool.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2011 Isode Limited. | 2 | * Copyright (c) 2011-2015 Isode Limited. |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * See the COPYING file for more information. | 4 | * See the COPYING file for more information. |
| 5 | */ | 5 | */ |
| @@ -12,6 +12,8 @@ | |||
| 12 | #include <Swiften/Base/API.h> | 12 | #include <Swiften/Base/API.h> |
| 13 | #include <Swiften/Base/SafeString.h> | 13 | #include <Swiften/Base/SafeString.h> |
| 14 | #include <Swiften/Network/BOSHConnection.h> | 14 | #include <Swiften/Network/BOSHConnection.h> |
| 15 | #include <Swiften/TLS/TLSOptions.h> | ||
| 16 | |||
| 15 | 17 | ||
| 16 | namespace Swift { | 18 | namespace Swift { |
| 17 | class HTTPConnectProxiedConnectionFactory; | 19 | class HTTPConnectProxiedConnectionFactory; |
| @@ -21,7 +23,7 @@ namespace Swift { | |||
| 21 | 23 | ||
| 22 | class SWIFTEN_API BOSHConnectionPool : public boost::bsignals::trackable { | 24 | class SWIFTEN_API BOSHConnectionPool : public boost::bsignals::trackable { |
| 23 | public: | 25 | public: |
| 24 | BOSHConnectionPool(const URL& boshURL, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword); | 26 | BOSHConnectionPool(const URL& boshURL, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword, const TLSOptions& tlsOptions); |
| 25 | ~BOSHConnectionPool(); | 27 | ~BOSHConnectionPool(); |
| 26 | void write(const SafeByteArray& data); | 28 | void write(const SafeByteArray& data); |
| 27 | void writeFooter(); | 29 | void writeFooter(); |
diff --git a/Swiften/Network/TLSConnection.cpp b/Swiften/Network/TLSConnection.cpp index f0b6fa4..149548a 100644 --- a/Swiften/Network/TLSConnection.cpp +++ b/Swiften/Network/TLSConnection.cpp | |||
| @@ -14,8 +14,8 @@ | |||
| 14 | 14 | ||
| 15 | namespace Swift { | 15 | namespace Swift { |
| 16 | 16 | ||
| 17 | TLSConnection::TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory) : connection(connection) { | 17 | TLSConnection::TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory, const TLSOptions& tlsOptions) : connection(connection) { |
| 18 | context = tlsFactory->createTLSContext(); | 18 | context = tlsFactory->createTLSContext(tlsOptions); |
| 19 | context->onDataForNetwork.connect(boost::bind(&TLSConnection::handleTLSDataForNetwork, this, _1)); | 19 | context->onDataForNetwork.connect(boost::bind(&TLSConnection::handleTLSDataForNetwork, this, _1)); |
| 20 | context->onDataForApplication.connect(boost::bind(&TLSConnection::handleTLSDataForApplication, this, _1)); | 20 | context->onDataForApplication.connect(boost::bind(&TLSConnection::handleTLSDataForApplication, this, _1)); |
| 21 | context->onConnected.connect(boost::bind(&TLSConnection::handleTLSConnectFinished, this, false)); | 21 | context->onConnected.connect(boost::bind(&TLSConnection::handleTLSConnectFinished, this, false)); |
diff --git a/Swiften/Network/TLSConnection.h b/Swiften/Network/TLSConnection.h index ebf2e43..96525ad 100644 --- a/Swiften/Network/TLSConnection.h +++ b/Swiften/Network/TLSConnection.h | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | #include <Swiften/Base/API.h> | 13 | #include <Swiften/Base/API.h> |
| 14 | #include <Swiften/Base/SafeByteArray.h> | 14 | #include <Swiften/Base/SafeByteArray.h> |
| 15 | #include <Swiften/Network/Connection.h> | 15 | #include <Swiften/Network/Connection.h> |
| 16 | #include <Swiften/TLS/TLSOptions.h> | ||
| 17 | |||
| 16 | 18 | ||
| 17 | namespace Swift { | 19 | namespace Swift { |
| 18 | class HostAddressPort; | 20 | class HostAddressPort; |
| @@ -22,7 +24,7 @@ namespace Swift { | |||
| 22 | class SWIFTEN_API TLSConnection : public Connection { | 24 | class SWIFTEN_API TLSConnection : public Connection { |
| 23 | public: | 25 | public: |
| 24 | 26 | ||
| 25 | TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory); | 27 | TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory, const TLSOptions&); |
| 26 | virtual ~TLSConnection(); | 28 | virtual ~TLSConnection(); |
| 27 | 29 | ||
| 28 | virtual void listen() {assert(false);} | 30 | virtual void listen() {assert(false);} |
diff --git a/Swiften/Network/TLSConnectionFactory.cpp b/Swiften/Network/TLSConnectionFactory.cpp index ac0ab8e..cc20b2d 100644 --- a/Swiften/Network/TLSConnectionFactory.cpp +++ b/Swiften/Network/TLSConnectionFactory.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | namespace Swift { | 13 | namespace Swift { |
| 14 | 14 | ||
| 15 | TLSConnectionFactory::TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory) : contextFactory(contextFactory), connectionFactory(connectionFactory){ | 15 | TLSConnectionFactory::TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory, const TLSOptions& o) : contextFactory(contextFactory), connectionFactory(connectionFactory), options_(o) { |
| 16 | 16 | ||
| 17 | } | 17 | } |
| 18 | 18 | ||
| @@ -22,7 +22,7 @@ TLSConnectionFactory::~TLSConnectionFactory() { | |||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | boost::shared_ptr<Connection> TLSConnectionFactory::createConnection() { | 24 | boost::shared_ptr<Connection> TLSConnectionFactory::createConnection() { |
| 25 | return boost::make_shared<TLSConnection>(connectionFactory->createConnection(), contextFactory); | 25 | return boost::make_shared<TLSConnection>(connectionFactory->createConnection(), contextFactory, options_); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | } | 28 | } |
diff --git a/Swiften/Network/TLSConnectionFactory.h b/Swiften/Network/TLSConnectionFactory.h index 3dfee06..0c67014 100644 --- a/Swiften/Network/TLSConnectionFactory.h +++ b/Swiften/Network/TLSConnectionFactory.h | |||
| @@ -11,18 +11,20 @@ | |||
| 11 | #include <Swiften/Base/API.h> | 11 | #include <Swiften/Base/API.h> |
| 12 | #include <Swiften/Network/ConnectionFactory.h> | 12 | #include <Swiften/Network/ConnectionFactory.h> |
| 13 | #include <Swiften/TLS/TLSContextFactory.h> | 13 | #include <Swiften/TLS/TLSContextFactory.h> |
| 14 | #include <Swiften/TLS/TLSOptions.h> | ||
| 14 | 15 | ||
| 15 | namespace Swift { | 16 | namespace Swift { |
| 16 | class Connection; | 17 | class Connection; |
| 17 | 18 | ||
| 18 | class SWIFTEN_API TLSConnectionFactory : public ConnectionFactory { | 19 | class SWIFTEN_API TLSConnectionFactory : public ConnectionFactory { |
| 19 | public: | 20 | public: |
| 20 | TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory); | 21 | TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory, const TLSOptions&); |
| 21 | virtual ~TLSConnectionFactory(); | 22 | virtual ~TLSConnectionFactory(); |
| 22 | 23 | ||
| 23 | virtual boost::shared_ptr<Connection> createConnection(); | 24 | virtual boost::shared_ptr<Connection> createConnection(); |
| 24 | private: | 25 | private: |
| 25 | TLSContextFactory* contextFactory; | 26 | TLSContextFactory* contextFactory; |
| 26 | ConnectionFactory* connectionFactory; | 27 | ConnectionFactory* connectionFactory; |
| 28 | TLSOptions options_; | ||
| 27 | }; | 29 | }; |
| 28 | } | 30 | } |
diff --git a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp index e5ac121..e687517 100644 --- a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp +++ b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp | |||
| @@ -16,15 +16,16 @@ | |||
| 16 | #include <boost/lexical_cast.hpp> | 16 | #include <boost/lexical_cast.hpp> |
| 17 | 17 | ||
| 18 | #include <Swiften/Base/Algorithm.h> | 18 | #include <Swiften/Base/Algorithm.h> |
| 19 | #include <Swiften/Network/Connection.h> | 19 | #include <Swiften/EventLoop/DummyEventLoop.h> |
| 20 | #include <Swiften/Network/ConnectionFactory.h> | ||
| 21 | #include <Swiften/Network/BOSHConnection.h> | 20 | #include <Swiften/Network/BOSHConnection.h> |
| 22 | #include <Swiften/Network/BOSHConnectionPool.h> | 21 | #include <Swiften/Network/BOSHConnectionPool.h> |
| 22 | #include <Swiften/Network/Connection.h> | ||
| 23 | #include <Swiften/Network/ConnectionFactory.h> | ||
| 24 | #include <Swiften/Network/DummyTimerFactory.h> | ||
| 23 | #include <Swiften/Network/HostAddressPort.h> | 25 | #include <Swiften/Network/HostAddressPort.h> |
| 24 | #include <Swiften/Network/StaticDomainNameResolver.h> | 26 | #include <Swiften/Network/StaticDomainNameResolver.h> |
| 25 | #include <Swiften/Network/DummyTimerFactory.h> | ||
| 26 | #include <Swiften/EventLoop/DummyEventLoop.h> | ||
| 27 | #include <Swiften/Parser/PlatformXMLParserFactory.h> | 27 | #include <Swiften/Parser/PlatformXMLParserFactory.h> |
| 28 | #include <Swiften/TLS/TLSOptions.h> | ||
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | 31 | ||
| @@ -322,7 +323,7 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture { | |||
| 322 | private: | 323 | private: |
| 323 | 324 | ||
| 324 | PoolRef createTestling() { | 325 | PoolRef createTestling() { |
| 325 | BOSHConnectionPool* a = new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString("")); | 326 | BOSHConnectionPool* a = new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""), TLSOptions()); |
| 326 | PoolRef pool(a); | 327 | PoolRef pool(a); |
| 327 | //FIXME: Remko - why does the above work, but the below fail? | 328 | //FIXME: Remko - why does the above work, but the below fail? |
| 328 | //PoolRef pool = boost::make_shared<BOSHConnectionPool>(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString("")); | 329 | //PoolRef pool = boost::make_shared<BOSHConnectionPool>(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString("")); |
diff --git a/Swiften/Session/BOSHSessionStream.cpp b/Swiften/Session/BOSHSessionStream.cpp index eac493e..62942b9 100644 --- a/Swiften/Session/BOSHSessionStream.cpp +++ b/Swiften/Session/BOSHSessionStream.cpp | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2011-2014 Isode Limited. | 2 | * Copyright (c) 2011-2015 Isode Limited. |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * See the COPYING file for more information. | 4 | * See the COPYING file for more information. |
| 5 | */ | 5 | */ |
| @@ -39,7 +39,8 @@ BOSHSessionStream::BOSHSessionStream( | |||
| 39 | const std::string& to, | 39 | const std::string& to, |
| 40 | const URL& boshHTTPConnectProxyURL, | 40 | const URL& boshHTTPConnectProxyURL, |
| 41 | const SafeString& boshHTTPConnectProxyAuthID, | 41 | const SafeString& boshHTTPConnectProxyAuthID, |
| 42 | const SafeString& boshHTTPConnectProxyAuthPassword) : | 42 | const SafeString& boshHTTPConnectProxyAuthPassword, |
| 43 | const TLSOptions& tlsOptions) : | ||
| 43 | available(false), | 44 | available(false), |
| 44 | eventLoop(eventLoop), | 45 | eventLoop(eventLoop), |
| 45 | firstHeader(true) { | 46 | firstHeader(true) { |
| @@ -49,7 +50,7 @@ BOSHSessionStream::BOSHSessionStream( | |||
| 49 | random.seed(static_cast<unsigned int>(time(NULL))); | 50 | random.seed(static_cast<unsigned int>(time(NULL))); |
| 50 | unsigned long long initialRID = boost::variate_generator<boost::mt19937&, boost::uniform_int<unsigned long long> >(random, dist)(); | 51 | unsigned long long initialRID = boost::variate_generator<boost::mt19937&, boost::uniform_int<unsigned long long> >(random, dist)(); |
| 51 | 52 | ||
| 52 | connectionPool = new BOSHConnectionPool(boshURL, resolver, connectionFactory, xmlParserFactory, tlsContextFactory, timerFactory, eventLoop, to, initialRID, boshHTTPConnectProxyURL, boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword); | 53 | connectionPool = new BOSHConnectionPool(boshURL, resolver, connectionFactory, xmlParserFactory, tlsContextFactory, timerFactory, eventLoop, to, initialRID, boshHTTPConnectProxyURL, boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword, tlsOptions); |
| 53 | connectionPool->onSessionTerminated.connect(boost::bind(&BOSHSessionStream::handlePoolSessionTerminated, this, _1)); | 54 | connectionPool->onSessionTerminated.connect(boost::bind(&BOSHSessionStream::handlePoolSessionTerminated, this, _1)); |
| 54 | connectionPool->onSessionStarted.connect(boost::bind(&BOSHSessionStream::handlePoolSessionStarted, this)); | 55 | connectionPool->onSessionStarted.connect(boost::bind(&BOSHSessionStream::handlePoolSessionStarted, this)); |
| 55 | connectionPool->onXMPPDataRead.connect(boost::bind(&BOSHSessionStream::handlePoolXMPPDataRead, this, _1)); | 56 | connectionPool->onXMPPDataRead.connect(boost::bind(&BOSHSessionStream::handlePoolXMPPDataRead, this, _1)); |
diff --git a/Swiften/Session/BOSHSessionStream.h b/Swiften/Session/BOSHSessionStream.h index e97436c..436b941 100644 --- a/Swiften/Session/BOSHSessionStream.h +++ b/Swiften/Session/BOSHSessionStream.h | |||
| @@ -9,12 +9,14 @@ | |||
| 9 | #include <boost/shared_ptr.hpp> | 9 | #include <boost/shared_ptr.hpp> |
| 10 | 10 | ||
| 11 | #include <Swiften/Base/API.h> | 11 | #include <Swiften/Base/API.h> |
| 12 | #include <Swiften/Base/SafeString.h> | ||
| 13 | #include <Swiften/Base/SafeByteArray.h> | 12 | #include <Swiften/Base/SafeByteArray.h> |
| 14 | #include <Swiften/Network/BOSHConnectionPool.h> | 13 | #include <Swiften/Base/SafeString.h> |
| 15 | #include <Swiften/Session/SessionStream.h> | ||
| 16 | #include <Swiften/Elements/StreamType.h> | 14 | #include <Swiften/Elements/StreamType.h> |
| 17 | #include <Swiften/EventLoop/EventOwner.h> | 15 | #include <Swiften/EventLoop/EventOwner.h> |
| 16 | #include <Swiften/Network/BOSHConnectionPool.h> | ||
| 17 | #include <Swiften/Session/SessionStream.h> | ||
| 18 | #include <Swiften/TLS/TLSOptions.h> | ||
| 19 | |||
| 18 | 20 | ||
| 19 | namespace Swift { | 21 | namespace Swift { |
| 20 | class TimerFactory; | 22 | class TimerFactory; |
| @@ -43,7 +45,8 @@ namespace Swift { | |||
| 43 | const std::string& to, | 45 | const std::string& to, |
| 44 | const URL& boshHTTPConnectProxyURL, | 46 | const URL& boshHTTPConnectProxyURL, |
| 45 | const SafeString& boshHTTPConnectProxyAuthID, | 47 | const SafeString& boshHTTPConnectProxyAuthID, |
| 46 | const SafeString& boshHTTPConnectProxyAuthPassword | 48 | const SafeString& boshHTTPConnectProxyAuthPassword, |
| 49 | const TLSOptions& tlsOptions | ||
| 47 | ); | 50 | ); |
| 48 | ~BOSHSessionStream(); | 51 | ~BOSHSessionStream(); |
| 49 | 52 | ||
diff --git a/Swiften/Session/BasicSessionStream.cpp b/Swiften/Session/BasicSessionStream.cpp index 274d218..43f1c48 100644 --- a/Swiften/Session/BasicSessionStream.cpp +++ b/Swiften/Session/BasicSessionStream.cpp | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2010-2014 Isode Limited. | 2 | * Copyright (c) 2010-2015 Isode Limited. |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * See the COPYING file for more information. | 4 | * See the COPYING file for more information. |
| 5 | */ | 5 | */ |
| @@ -27,14 +27,16 @@ BasicSessionStream::BasicSessionStream( | |||
| 27 | PayloadSerializerCollection* payloadSerializers, | 27 | PayloadSerializerCollection* payloadSerializers, |
| 28 | TLSContextFactory* tlsContextFactory, | 28 | TLSContextFactory* tlsContextFactory, |
| 29 | TimerFactory* timerFactory, | 29 | TimerFactory* timerFactory, |
| 30 | XMLParserFactory* xmlParserFactory) : | 30 | XMLParserFactory* xmlParserFactory, |
| 31 | const TLSOptions& tlsOptions) : | ||
| 31 | available(false), | 32 | available(false), |
| 32 | connection(connection), | 33 | connection(connection), |
| 33 | tlsContextFactory(tlsContextFactory), | 34 | tlsContextFactory(tlsContextFactory), |
| 34 | timerFactory(timerFactory), | 35 | timerFactory(timerFactory), |
| 35 | compressionLayer(NULL), | 36 | compressionLayer(NULL), |
| 36 | tlsLayer(NULL), | 37 | tlsLayer(NULL), |
| 37 | whitespacePingLayer(NULL) { | 38 | whitespacePingLayer(NULL), |
| 39 | tlsOptions_(tlsOptions) { | ||
| 38 | xmppLayer = new XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, streamType); | 40 | xmppLayer = new XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, streamType); |
| 39 | xmppLayer->onStreamStart.connect(boost::bind(&BasicSessionStream::handleStreamStartReceived, this, _1)); | 41 | xmppLayer->onStreamStart.connect(boost::bind(&BasicSessionStream::handleStreamStartReceived, this, _1)); |
| 40 | xmppLayer->onElement.connect(boost::bind(&BasicSessionStream::handleElementReceived, this, _1)); | 42 | xmppLayer->onElement.connect(boost::bind(&BasicSessionStream::handleElementReceived, this, _1)); |
| @@ -106,7 +108,7 @@ bool BasicSessionStream::supportsTLSEncryption() { | |||
| 106 | 108 | ||
| 107 | void BasicSessionStream::addTLSEncryption() { | 109 | void BasicSessionStream::addTLSEncryption() { |
| 108 | assert(available); | 110 | assert(available); |
| 109 | tlsLayer = new TLSLayer(tlsContextFactory); | 111 | tlsLayer = new TLSLayer(tlsContextFactory, tlsOptions_); |
| 110 | if (hasTLSCertificate() && !tlsLayer->setClientCertificate(getTLSCertificate())) { | 112 | if (hasTLSCertificate() && !tlsLayer->setClientCertificate(getTLSCertificate())) { |
| 111 | onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::InvalidTLSCertificateError)); | 113 | onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::InvalidTLSCertificateError)); |
| 112 | } | 114 | } |
diff --git a/Swiften/Session/BasicSessionStream.h b/Swiften/Session/BasicSessionStream.h index 7832e42..811374a 100644 --- a/Swiften/Session/BasicSessionStream.h +++ b/Swiften/Session/BasicSessionStream.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <Swiften/Session/SessionStream.h> | 14 | #include <Swiften/Session/SessionStream.h> |
| 15 | #include <Swiften/Elements/StreamType.h> | 15 | #include <Swiften/Elements/StreamType.h> |
| 16 | #include <Swiften/TLS/TLSError.h> | 16 | #include <Swiften/TLS/TLSError.h> |
| 17 | #include <Swiften/TLS/TLSOptions.h> | ||
| 17 | 18 | ||
| 18 | namespace Swift { | 19 | namespace Swift { |
| 19 | class TLSContextFactory; | 20 | class TLSContextFactory; |
| @@ -37,7 +38,8 @@ namespace Swift { | |||
| 37 | PayloadSerializerCollection* payloadSerializers, | 38 | PayloadSerializerCollection* payloadSerializers, |
| 38 | TLSContextFactory* tlsContextFactory, | 39 | TLSContextFactory* tlsContextFactory, |
| 39 | TimerFactory* whitespacePingLayerFactory, | 40 | TimerFactory* whitespacePingLayerFactory, |
| 40 | XMLParserFactory* xmlParserFactory | 41 | XMLParserFactory* xmlParserFactory, |
| 42 | const TLSOptions& tlsOptions | ||
| 41 | ); | 43 | ); |
| 42 | ~BasicSessionStream(); | 44 | ~BasicSessionStream(); |
| 43 | 45 | ||
| @@ -86,6 +88,7 @@ namespace Swift { | |||
| 86 | TLSLayer* tlsLayer; | 88 | TLSLayer* tlsLayer; |
| 87 | WhitespacePingLayer* whitespacePingLayer; | 89 | WhitespacePingLayer* whitespacePingLayer; |
| 88 | StreamStack* streamStack; | 90 | StreamStack* streamStack; |
| 91 | TLSOptions tlsOptions_; | ||
| 89 | }; | 92 | }; |
| 90 | 93 | ||
| 91 | } | 94 | } |
diff --git a/Swiften/StreamStack/TLSLayer.cpp b/Swiften/StreamStack/TLSLayer.cpp index aebf4a2..15c4101 100644 --- a/Swiften/StreamStack/TLSLayer.cpp +++ b/Swiften/StreamStack/TLSLayer.cpp | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | 13 | ||
| 14 | namespace Swift { | 14 | namespace Swift { |
| 15 | 15 | ||
| 16 | TLSLayer::TLSLayer(TLSContextFactory* factory) { | 16 | TLSLayer::TLSLayer(TLSContextFactory* factory, const TLSOptions& tlsOptions) { |
| 17 | context = factory->createTLSContext(); | 17 | context = factory->createTLSContext(tlsOptions); |
| 18 | context->onDataForNetwork.connect(boost::bind(&TLSLayer::writeDataToChildLayer, this, _1)); | 18 | context->onDataForNetwork.connect(boost::bind(&TLSLayer::writeDataToChildLayer, this, _1)); |
| 19 | context->onDataForApplication.connect(boost::bind(&TLSLayer::writeDataToParentLayer, this, _1)); | 19 | context->onDataForApplication.connect(boost::bind(&TLSLayer::writeDataToParentLayer, this, _1)); |
| 20 | context->onConnected.connect(onConnected); | 20 | context->onConnected.connect(onConnected); |
diff --git a/Swiften/StreamStack/TLSLayer.h b/Swiften/StreamStack/TLSLayer.h index 089512d..87d69a9 100644 --- a/Swiften/StreamStack/TLSLayer.h +++ b/Swiften/StreamStack/TLSLayer.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <Swiften/TLS/CertificateWithKey.h> | 15 | #include <Swiften/TLS/CertificateWithKey.h> |
| 16 | #include <Swiften/TLS/CertificateVerificationError.h> | 16 | #include <Swiften/TLS/CertificateVerificationError.h> |
| 17 | #include <Swiften/TLS/TLSError.h> | 17 | #include <Swiften/TLS/TLSError.h> |
| 18 | #include <Swiften/TLS/TLSOptions.h> | ||
| 18 | 19 | ||
| 19 | namespace Swift { | 20 | namespace Swift { |
| 20 | class TLSContext; | 21 | class TLSContext; |
| @@ -22,7 +23,7 @@ namespace Swift { | |||
| 22 | 23 | ||
| 23 | class SWIFTEN_API TLSLayer : public StreamLayer { | 24 | class SWIFTEN_API TLSLayer : public StreamLayer { |
| 24 | public: | 25 | public: |
| 25 | TLSLayer(TLSContextFactory*); | 26 | TLSLayer(TLSContextFactory*, const TLSOptions&); |
| 26 | ~TLSLayer(); | 27 | ~TLSLayer(); |
| 27 | 28 | ||
| 28 | void connect(); | 29 | void connect(); |
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp index 5fbc913..50f6731 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp | |||
| @@ -14,7 +14,7 @@ bool OpenSSLContextFactory::canCreate() const { | |||
| 14 | return true; | 14 | return true; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | TLSContext* OpenSSLContextFactory::createTLSContext() { | 17 | TLSContext* OpenSSLContextFactory::createTLSContext(const TLSOptions&) { |
| 18 | return new OpenSSLContext(); | 18 | return new OpenSSLContext(); |
| 19 | } | 19 | } |
| 20 | 20 | ||
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h index 8e689b5..bf7f08a 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h +++ b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h | |||
| @@ -14,7 +14,7 @@ namespace Swift { | |||
| 14 | class OpenSSLContextFactory : public TLSContextFactory { | 14 | class OpenSSLContextFactory : public TLSContextFactory { |
| 15 | public: | 15 | public: |
| 16 | bool canCreate() const; | 16 | bool canCreate() const; |
| 17 | virtual TLSContext* createTLSContext(); | 17 | virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions); |
| 18 | 18 | ||
| 19 | // Not supported | 19 | // Not supported |
| 20 | virtual void setCheckCertificateRevocation(bool b); | 20 | virtual void setCheckCertificateRevocation(bool b); |
diff --git a/Swiften/TLS/Schannel/SchannelContext.cpp b/Swiften/TLS/Schannel/SchannelContext.cpp index 86b8c18..5f230ec 100644 --- a/Swiften/TLS/Schannel/SchannelContext.cpp +++ b/Swiften/TLS/Schannel/SchannelContext.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | /* | 7 | /* |
| 8 | * Copyright (c) 2012 Isode Limited. | 8 | * Copyright (c) 2012-2015 Isode Limited. |
| 9 | * All rights reserved. | 9 | * All rights reserved. |
| 10 | * See the COPYING file for more information. | 10 | * See the COPYING file for more information. |
| 11 | */ | 11 | */ |
| @@ -21,8 +21,8 @@ namespace Swift { | |||
| 21 | 21 | ||
| 22 | //------------------------------------------------------------------------ | 22 | //------------------------------------------------------------------------ |
| 23 | 23 | ||
| 24 | SchannelContext::SchannelContext() : m_state(Start), m_secContext(0), m_my_cert_store(NULL), m_cert_store_name("MY"), m_cert_name(), m_smartcard_reader(), checkCertificateRevocation(true) { | 24 | SchannelContext::SchannelContext(bool tls1_0Workaround) : state_(Start), secContext_(0), myCertStore_(NULL), certStoreName_("MY"), certName_(), smartCardReader_(), checkCertificateRevocation_(true), tls1_0Workaround_(tls1_0Workaround) { |
| 25 | m_ctxtFlags = ISC_REQ_ALLOCATE_MEMORY | | 25 | contextFlags_ = ISC_REQ_ALLOCATE_MEMORY | |
| 26 | ISC_REQ_CONFIDENTIALITY | | 26 | ISC_REQ_CONFIDENTIALITY | |
| 27 | ISC_REQ_EXTENDED_ERROR | | 27 | ISC_REQ_EXTENDED_ERROR | |
| 28 | ISC_REQ_INTEGRITY | | 28 | ISC_REQ_INTEGRITY | |
| @@ -31,19 +31,19 @@ SchannelContext::SchannelContext() : m_state(Start), m_secContext(0), m_my_cert_ | |||
| 31 | ISC_REQ_USE_SUPPLIED_CREDS | | 31 | ISC_REQ_USE_SUPPLIED_CREDS | |
| 32 | ISC_REQ_STREAM; | 32 | ISC_REQ_STREAM; |
| 33 | 33 | ||
| 34 | ZeroMemory(&m_streamSizes, sizeof(m_streamSizes)); | 34 | ZeroMemory(&streamSizes_, sizeof(streamSizes_)); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | //------------------------------------------------------------------------ | 37 | //------------------------------------------------------------------------ |
| 38 | 38 | ||
| 39 | SchannelContext::~SchannelContext() { | 39 | SchannelContext::~SchannelContext() { |
| 40 | if (m_my_cert_store) CertCloseStore(m_my_cert_store, 0); | 40 | if (myCertStore_) CertCloseStore(myCertStore_, 0); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | //------------------------------------------------------------------------ | 43 | //------------------------------------------------------------------------ |
| 44 | 44 | ||
| 45 | void SchannelContext::determineStreamSizes() { | 45 | void SchannelContext::determineStreamSizes() { |
| 46 | QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_STREAM_SIZES, &m_streamSizes); | 46 | QueryContextAttributes(contextHandle_, SECPKG_ATTR_STREAM_SIZES, &streamSizes_); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | //------------------------------------------------------------------------ | 49 | //------------------------------------------------------------------------ |
| @@ -51,20 +51,20 @@ void SchannelContext::determineStreamSizes() { | |||
| 51 | void SchannelContext::connect() { | 51 | void SchannelContext::connect() { |
| 52 | ScopedCertContext pCertContext; | 52 | ScopedCertContext pCertContext; |
| 53 | 53 | ||
| 54 | m_state = Connecting; | 54 | state_ = Connecting; |
| 55 | 55 | ||
| 56 | // If a user name is specified, then attempt to find a client | 56 | // If a user name is specified, then attempt to find a client |
| 57 | // certificate. Otherwise, just create a NULL credential. | 57 | // certificate. Otherwise, just create a NULL credential. |
| 58 | if (!m_cert_name.empty()) { | 58 | if (!certName_.empty()) { |
| 59 | if (m_my_cert_store == NULL) { | 59 | if (myCertStore_ == NULL) { |
| 60 | m_my_cert_store = CertOpenSystemStore(0, m_cert_store_name.c_str()); | 60 | myCertStore_ = CertOpenSystemStore(0, certStoreName_.c_str()); |
| 61 | if (!m_my_cert_store) { | 61 | if (!myCertStore_) { |
| 62 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); | 62 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); |
| 63 | return; | 63 | return; |
| 64 | } | 64 | } |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | pCertContext = findCertificateInStore( m_my_cert_store, m_cert_name ); | 67 | pCertContext = findCertificateInStore( myCertStore_, certName_ ); |
| 68 | if (pCertContext == NULL) { | 68 | if (pCertContext == NULL) { |
| 69 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); | 69 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); |
| 70 | return; | 70 | return; |
| @@ -77,8 +77,13 @@ void SchannelContext::connect() { | |||
| 77 | SCHANNEL_CRED sc = {0}; | 77 | SCHANNEL_CRED sc = {0}; |
| 78 | sc.dwVersion = SCHANNEL_CRED_VERSION; | 78 | sc.dwVersion = SCHANNEL_CRED_VERSION; |
| 79 | 79 | ||
| 80 | /////SSL3? | 80 | if (tls1_0Workaround_) { |
| 81 | sc.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; | 81 | sc.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT; |
| 82 | } | ||
| 83 | else { | ||
| 84 | sc.grbitEnabledProtocols = /*SP_PROT_SSL3_CLIENT | */SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; | ||
| 85 | } | ||
| 86 | |||
| 82 | sc.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; | 87 | sc.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; |
| 83 | 88 | ||
| 84 | if (pCertContext) { | 89 | if (pCertContext) { |
| @@ -103,9 +108,9 @@ void SchannelContext::connect() { | |||
| 103 | &sc, | 108 | &sc, |
| 104 | NULL, | 109 | NULL, |
| 105 | NULL, | 110 | NULL, |
| 106 | m_credHandle.Reset(), | 111 | credHandle_.Reset(), |
| 107 | NULL); | 112 | NULL); |
| 108 | 113 | ||
| 109 | if (status != SEC_E_OK) { | 114 | if (status != SEC_E_OK) { |
| 110 | // We failed to obtain the credentials handle | 115 | // We failed to obtain the credentials handle |
| 111 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); | 116 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); |
| @@ -135,17 +140,17 @@ void SchannelContext::connect() { | |||
| 135 | 140 | ||
| 136 | // Create the initial security context | 141 | // Create the initial security context |
| 137 | status = InitializeSecurityContext( | 142 | status = InitializeSecurityContext( |
| 138 | m_credHandle, | 143 | credHandle_, |
| 139 | NULL, | 144 | NULL, |
| 140 | NULL, | 145 | NULL, |
| 141 | m_ctxtFlags, | 146 | contextFlags_, |
| 142 | 0, | 147 | 0, |
| 143 | 0, | 148 | 0, |
| 144 | NULL, | 149 | NULL, |
| 145 | 0, | 150 | 0, |
| 146 | m_ctxtHandle.Reset(), | 151 | contextHandle_.Reset(), |
| 147 | &outBufferDesc, | 152 | &outBufferDesc, |
| 148 | &m_secContext, | 153 | &secContext_, |
| 149 | NULL); | 154 | NULL); |
| 150 | 155 | ||
| 151 | if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { | 156 | if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { |
| @@ -164,7 +169,7 @@ void SchannelContext::connect() { | |||
| 164 | handleCertError(status); | 169 | handleCertError(status); |
| 165 | } | 170 | } |
| 166 | 171 | ||
| 167 | m_state = Connected; | 172 | state_ = Connected; |
| 168 | determineStreamSizes(); | 173 | determineStreamSizes(); |
| 169 | 174 | ||
| 170 | onConnected(); | 175 | onConnected(); |
| @@ -179,7 +184,7 @@ SECURITY_STATUS SchannelContext::validateServerCertificate() { | |||
| 179 | return SEC_E_WRONG_PRINCIPAL; | 184 | return SEC_E_WRONG_PRINCIPAL; |
| 180 | } | 185 | } |
| 181 | 186 | ||
| 182 | const LPSTR usage[] = | 187 | const LPSTR usage[] = |
| 183 | { | 188 | { |
| 184 | szOID_PKIX_KP_SERVER_AUTH, | 189 | szOID_PKIX_KP_SERVER_AUTH, |
| 185 | szOID_SERVER_GATED_CRYPTO, | 190 | szOID_SERVER_GATED_CRYPTO, |
| @@ -193,7 +198,7 @@ SECURITY_STATUS SchannelContext::validateServerCertificate() { | |||
| 193 | chainParams.RequestedUsage.Usage.rgpszUsageIdentifier = const_cast<LPSTR*>(usage); | 198 | chainParams.RequestedUsage.Usage.rgpszUsageIdentifier = const_cast<LPSTR*>(usage); |
| 194 | 199 | ||
| 195 | DWORD chainFlags = CERT_CHAIN_CACHE_END_CERT; | 200 | DWORD chainFlags = CERT_CHAIN_CACHE_END_CERT; |
| 196 | if (checkCertificateRevocation) { | 201 | if (checkCertificateRevocation_) { |
| 197 | chainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; | 202 | chainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; |
| 198 | } | 203 | } |
| 199 | 204 | ||
| @@ -246,9 +251,9 @@ SECURITY_STATUS SchannelContext::validateServerCertificate() { | |||
| 246 | //------------------------------------------------------------------------ | 251 | //------------------------------------------------------------------------ |
| 247 | 252 | ||
| 248 | void SchannelContext::appendNewData(const SafeByteArray& data) { | 253 | void SchannelContext::appendNewData(const SafeByteArray& data) { |
| 249 | size_t originalSize = m_receivedData.size(); | 254 | size_t originalSize = receivedData_.size(); |
| 250 | m_receivedData.resize(originalSize + data.size()); | 255 | receivedData_.resize(originalSize + data.size()); |
| 251 | memcpy(&m_receivedData[0] + originalSize, &data[0], data.size()); | 256 | memcpy(&receivedData_[0] + originalSize, &data[0], data.size()); |
| 252 | } | 257 | } |
| 253 | 258 | ||
| 254 | //------------------------------------------------------------------------ | 259 | //------------------------------------------------------------------------ |
| @@ -256,12 +261,12 @@ void SchannelContext::appendNewData(const SafeByteArray& data) { | |||
| 256 | void SchannelContext::continueHandshake(const SafeByteArray& data) { | 261 | void SchannelContext::continueHandshake(const SafeByteArray& data) { |
| 257 | appendNewData(data); | 262 | appendNewData(data); |
| 258 | 263 | ||
| 259 | while (!m_receivedData.empty()) { | 264 | while (!receivedData_.empty()) { |
| 260 | SecBuffer inBuffers[2]; | 265 | SecBuffer inBuffers[2]; |
| 261 | 266 | ||
| 262 | // Provide Schannel with the remote host's handshake data | 267 | // Provide Schannel with the remote host's handshake data |
| 263 | inBuffers[0].pvBuffer = (char*)(&m_receivedData[0]); | 268 | inBuffers[0].pvBuffer = (char*)(&receivedData_[0]); |
| 264 | inBuffers[0].cbBuffer = (unsigned long)m_receivedData.size(); | 269 | inBuffers[0].cbBuffer = (unsigned long)receivedData_.size(); |
| 265 | inBuffers[0].BufferType = SECBUFFER_TOKEN; | 270 | inBuffers[0].BufferType = SECBUFFER_TOKEN; |
| 266 | 271 | ||
| 267 | inBuffers[1].pvBuffer = NULL; | 272 | inBuffers[1].pvBuffer = NULL; |
| @@ -295,17 +300,17 @@ void SchannelContext::continueHandshake(const SafeByteArray& data) { | |||
| 295 | outBufferDesc.ulVersion = SECBUFFER_VERSION; | 300 | outBufferDesc.ulVersion = SECBUFFER_VERSION; |
| 296 | 301 | ||
| 297 | SECURITY_STATUS status = InitializeSecurityContext( | 302 | SECURITY_STATUS status = InitializeSecurityContext( |
| 298 | m_credHandle, | 303 | credHandle_, |
| 299 | m_ctxtHandle, | 304 | contextHandle_, |
| 300 | NULL, | 305 | NULL, |
| 301 | m_ctxtFlags, | 306 | contextFlags_, |
| 302 | 0, | 307 | 0, |
| 303 | 0, | 308 | 0, |
| 304 | &inBufferDesc, | 309 | &inBufferDesc, |
| 305 | 0, | 310 | 0, |
| 306 | NULL, | 311 | NULL, |
| 307 | &outBufferDesc, | 312 | &outBufferDesc, |
| 308 | &m_secContext, | 313 | &secContext_, |
| 309 | NULL); | 314 | NULL); |
| 310 | 315 | ||
| 311 | if (status == SEC_E_INCOMPLETE_MESSAGE) { | 316 | if (status == SEC_E_INCOMPLETE_MESSAGE) { |
| @@ -315,16 +320,16 @@ void SchannelContext::continueHandshake(const SafeByteArray& data) { | |||
| 315 | else if (status == SEC_I_CONTINUE_NEEDED) { | 320 | else if (status == SEC_I_CONTINUE_NEEDED) { |
| 316 | SecBuffer* pDataBuffer = &outBuffers[0]; | 321 | SecBuffer* pDataBuffer = &outBuffers[0]; |
| 317 | SecBuffer* pExtraBuffer = &inBuffers[1]; | 322 | SecBuffer* pExtraBuffer = &inBuffers[1]; |
| 318 | 323 | ||
| 319 | if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) { | 324 | if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) { |
| 320 | sendDataOnNetwork(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer); | 325 | sendDataOnNetwork(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer); |
| 321 | } | 326 | } |
| 322 | 327 | ||
| 323 | if (pExtraBuffer->BufferType == SECBUFFER_EXTRA) { | 328 | if (pExtraBuffer->BufferType == SECBUFFER_EXTRA) { |
| 324 | m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer); | 329 | receivedData_.erase(receivedData_.begin(), receivedData_.end() - pExtraBuffer->cbBuffer); |
| 325 | } | 330 | } |
| 326 | else { | 331 | else { |
| 327 | m_receivedData.clear(); | 332 | receivedData_.clear(); |
| 328 | } | 333 | } |
| 329 | 334 | ||
| 330 | break; | 335 | break; |
| @@ -336,19 +341,19 @@ void SchannelContext::continueHandshake(const SafeByteArray& data) { | |||
| 336 | } | 341 | } |
| 337 | 342 | ||
| 338 | SecBuffer* pExtraBuffer = &inBuffers[1]; | 343 | SecBuffer* pExtraBuffer = &inBuffers[1]; |
| 339 | 344 | ||
| 340 | if (pExtraBuffer && pExtraBuffer->cbBuffer > 0) { | 345 | if (pExtraBuffer && pExtraBuffer->cbBuffer > 0) { |
| 341 | m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer); | 346 | receivedData_.erase(receivedData_.begin(), receivedData_.end() - pExtraBuffer->cbBuffer); |
| 342 | } | 347 | } |
| 343 | else { | 348 | else { |
| 344 | m_receivedData.clear(); | 349 | receivedData_.clear(); |
| 345 | } | 350 | } |
| 346 | 351 | ||
| 347 | m_state = Connected; | 352 | state_ = Connected; |
| 348 | determineStreamSizes(); | 353 | determineStreamSizes(); |
| 349 | 354 | ||
| 350 | onConnected(); | 355 | onConnected(); |
| 351 | } | 356 | } |
| 352 | else { | 357 | else { |
| 353 | // We failed to initialize the security context | 358 | // We failed to initialize the security context |
| 354 | handleCertError(status); | 359 | handleCertError(status); |
| @@ -360,35 +365,35 @@ void SchannelContext::continueHandshake(const SafeByteArray& data) { | |||
| 360 | 365 | ||
| 361 | //------------------------------------------------------------------------ | 366 | //------------------------------------------------------------------------ |
| 362 | 367 | ||
| 363 | void SchannelContext::handleCertError(SECURITY_STATUS status) | 368 | void SchannelContext::handleCertError(SECURITY_STATUS status) |
| 364 | { | 369 | { |
| 365 | if (status == SEC_E_UNTRUSTED_ROOT || | 370 | if (status == SEC_E_UNTRUSTED_ROOT || |
| 366 | status == CERT_E_UNTRUSTEDROOT || | 371 | status == CERT_E_UNTRUSTEDROOT || |
| 367 | status == CRYPT_E_ISSUER_SERIALNUMBER || | 372 | status == CRYPT_E_ISSUER_SERIALNUMBER || |
| 368 | status == CRYPT_E_SIGNER_NOT_FOUND || | 373 | status == CRYPT_E_SIGNER_NOT_FOUND || |
| 369 | status == CRYPT_E_NO_TRUSTED_SIGNER) { | 374 | status == CRYPT_E_NO_TRUSTED_SIGNER) { |
| 370 | m_verificationError = CertificateVerificationError::Untrusted; | 375 | verificationError_ = CertificateVerificationError::Untrusted; |
| 371 | } | 376 | } |
| 372 | else if (status == SEC_E_CERT_EXPIRED || | 377 | else if (status == SEC_E_CERT_EXPIRED || |
| 373 | status == CERT_E_EXPIRED) { | 378 | status == CERT_E_EXPIRED) { |
| 374 | m_verificationError = CertificateVerificationError::Expired; | 379 | verificationError_ = CertificateVerificationError::Expired; |
| 375 | } | 380 | } |
| 376 | else if (status == CRYPT_E_SELF_SIGNED) { | 381 | else if (status == CRYPT_E_SELF_SIGNED) { |
| 377 | m_verificationError = CertificateVerificationError::SelfSigned; | 382 | verificationError_ = CertificateVerificationError::SelfSigned; |
| 378 | } | 383 | } |
| 379 | else if (status == CRYPT_E_HASH_VALUE || | 384 | else if (status == CRYPT_E_HASH_VALUE || |
| 380 | status == TRUST_E_CERT_SIGNATURE) { | 385 | status == TRUST_E_CERT_SIGNATURE) { |
| 381 | m_verificationError = CertificateVerificationError::InvalidSignature; | 386 | verificationError_ = CertificateVerificationError::InvalidSignature; |
| 382 | } | 387 | } |
| 383 | else if (status == CRYPT_E_REVOKED) { | 388 | else if (status == CRYPT_E_REVOKED) { |
| 384 | m_verificationError = CertificateVerificationError::Revoked; | 389 | verificationError_ = CertificateVerificationError::Revoked; |
| 385 | } | 390 | } |
| 386 | else if (status == CRYPT_E_NO_REVOCATION_CHECK || | 391 | else if (status == CRYPT_E_NO_REVOCATION_CHECK || |
| 387 | status == CRYPT_E_REVOCATION_OFFLINE) { | 392 | status == CRYPT_E_REVOCATION_OFFLINE) { |
| 388 | m_verificationError = CertificateVerificationError::RevocationCheckFailed; | 393 | verificationError_ = CertificateVerificationError::RevocationCheckFailed; |
| 389 | } | 394 | } |
| 390 | else { | 395 | else { |
| 391 | m_verificationError = CertificateVerificationError::UnknownError; | 396 | verificationError_ = CertificateVerificationError::UnknownError; |
| 392 | } | 397 | } |
| 393 | } | 398 | } |
| 394 | 399 | ||
| @@ -416,7 +421,7 @@ void SchannelContext::forwardDataToApplication(const void* pData, size_t dataSiz | |||
| 416 | 421 | ||
| 417 | void SchannelContext::handleDataFromApplication(const SafeByteArray& data) { | 422 | void SchannelContext::handleDataFromApplication(const SafeByteArray& data) { |
| 418 | // Don't attempt to send data until we're fully connected | 423 | // Don't attempt to send data until we're fully connected |
| 419 | if (m_state == Connecting) { | 424 | if (state_ == Connecting) { |
| 420 | return; | 425 | return; |
| 421 | } | 426 | } |
| 422 | 427 | ||
| @@ -427,7 +432,7 @@ void SchannelContext::handleDataFromApplication(const SafeByteArray& data) { | |||
| 427 | //------------------------------------------------------------------------ | 432 | //------------------------------------------------------------------------ |
| 428 | 433 | ||
| 429 | void SchannelContext::handleDataFromNetwork(const SafeByteArray& data) { | 434 | void SchannelContext::handleDataFromNetwork(const SafeByteArray& data) { |
| 430 | switch (m_state) { | 435 | switch (state_) { |
| 431 | case Connecting: | 436 | case Connecting: |
| 432 | { | 437 | { |
| 433 | // We're still establishing the connection, so continue the handshake | 438 | // We're still establishing the connection, so continue the handshake |
| @@ -450,8 +455,8 @@ void SchannelContext::handleDataFromNetwork(const SafeByteArray& data) { | |||
| 450 | //------------------------------------------------------------------------ | 455 | //------------------------------------------------------------------------ |
| 451 | 456 | ||
| 452 | void SchannelContext::indicateError(boost::shared_ptr<TLSError> error) { | 457 | void SchannelContext::indicateError(boost::shared_ptr<TLSError> error) { |
| 453 | m_state = Error; | 458 | state_ = Error; |
| 454 | m_receivedData.clear(); | 459 | receivedData_.clear(); |
| 455 | onError(error); | 460 | onError(error); |
| 456 | } | 461 | } |
| 457 | 462 | ||
| @@ -461,20 +466,20 @@ void SchannelContext::decryptAndProcessData(const SafeByteArray& data) { | |||
| 461 | SecBuffer inBuffers[4] = {0}; | 466 | SecBuffer inBuffers[4] = {0}; |
| 462 | 467 | ||
| 463 | appendNewData(data); | 468 | appendNewData(data); |
| 464 | 469 | ||
| 465 | while (!m_receivedData.empty()) { | 470 | while (!receivedData_.empty()) { |
| 466 | // | 471 | // |
| 467 | // MSDN: | 472 | // MSDN: |
| 468 | // When using the Schannel SSP with contexts that are not connection oriented, on input, | 473 | // When using the Schannel SSP with contexts that are not connection oriented, on input, |
| 469 | // the structure must contain four SecBuffer structures. Exactly one buffer must be of type | 474 | // the structure must contain four SecBuffer structures. Exactly one buffer must be of type |
| 470 | // SECBUFFER_DATA and contain an encrypted message, which is decrypted in place. The remaining | 475 | // SECBUFFER_DATA and contain an encrypted message, which is decrypted in place. The remaining |
| 471 | // buffers are used for output and must be of type SECBUFFER_EMPTY. For connection-oriented | 476 | // buffers are used for output and must be of type SECBUFFER_EMPTY. For connection-oriented |
| 472 | // contexts, a SECBUFFER_DATA type buffer must be supplied, as noted for nonconnection-oriented | 477 | // contexts, a SECBUFFER_DATA type buffer must be supplied, as noted for nonconnection-oriented |
| 473 | // contexts. Additionally, a second SECBUFFER_TOKEN type buffer that contains a security token | 478 | // contexts. Additionally, a second SECBUFFER_TOKEN type buffer that contains a security token |
| 474 | // must also be supplied. | 479 | // must also be supplied. |
| 475 | // | 480 | // |
| 476 | inBuffers[0].pvBuffer = (char*)(&m_receivedData[0]); | 481 | inBuffers[0].pvBuffer = (char*)(&receivedData_[0]); |
| 477 | inBuffers[0].cbBuffer = (unsigned long)m_receivedData.size(); | 482 | inBuffers[0].cbBuffer = (unsigned long)receivedData_.size(); |
| 478 | inBuffers[0].BufferType = SECBUFFER_DATA; | 483 | inBuffers[0].BufferType = SECBUFFER_DATA; |
| 479 | 484 | ||
| 480 | inBuffers[1].BufferType = SECBUFFER_EMPTY; | 485 | inBuffers[1].BufferType = SECBUFFER_EMPTY; |
| @@ -486,22 +491,22 @@ void SchannelContext::decryptAndProcessData(const SafeByteArray& data) { | |||
| 486 | inBufferDesc.pBuffers = inBuffers; | 491 | inBufferDesc.pBuffers = inBuffers; |
| 487 | inBufferDesc.ulVersion = SECBUFFER_VERSION; | 492 | inBufferDesc.ulVersion = SECBUFFER_VERSION; |
| 488 | 493 | ||
| 489 | size_t inData = m_receivedData.size(); | 494 | size_t inData = receivedData_.size(); |
| 490 | SECURITY_STATUS status = DecryptMessage(m_ctxtHandle, &inBufferDesc, 0, NULL); | 495 | SECURITY_STATUS status = DecryptMessage(contextHandle_, &inBufferDesc, 0, NULL); |
| 491 | 496 | ||
| 492 | if (status == SEC_E_INCOMPLETE_MESSAGE) { | 497 | if (status == SEC_E_INCOMPLETE_MESSAGE) { |
| 493 | // Wait for more data to arrive | 498 | // Wait for more data to arrive |
| 494 | break; | 499 | break; |
| 495 | } | 500 | } |
| 496 | else if (status == SEC_I_RENEGOTIATE) { | 501 | else if (status == SEC_I_RENEGOTIATE) { |
| 497 | // TODO: Handle renegotiation scenarios | 502 | // TODO: Handle renegotiation scenarios |
| 498 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); | 503 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); |
| 499 | break; | 504 | break; |
| 500 | } | 505 | } |
| 501 | else if (status == SEC_I_CONTEXT_EXPIRED) { | 506 | else if (status == SEC_I_CONTEXT_EXPIRED) { |
| 502 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); | 507 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); |
| 503 | break; | 508 | break; |
| 504 | } | 509 | } |
| 505 | else if (status != SEC_E_OK) { | 510 | else if (status != SEC_E_OK) { |
| 506 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); | 511 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); |
| 507 | break; | 512 | break; |
| @@ -524,11 +529,11 @@ void SchannelContext::decryptAndProcessData(const SafeByteArray& data) { | |||
| 524 | 529 | ||
| 525 | // If there is extra data left over from the decryption operation, we call DecryptMessage() again | 530 | // If there is extra data left over from the decryption operation, we call DecryptMessage() again |
| 526 | if (pExtraBuffer) { | 531 | if (pExtraBuffer) { |
| 527 | m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer); | 532 | receivedData_.erase(receivedData_.begin(), receivedData_.end() - pExtraBuffer->cbBuffer); |
| 528 | } | 533 | } |
| 529 | else { | 534 | else { |
| 530 | // We're done | 535 | // We're done |
| 531 | m_receivedData.erase(m_receivedData.begin(), m_receivedData.begin() + inData); | 536 | receivedData_.erase(receivedData_.begin(), receivedData_.begin() + inData); |
| 532 | } | 537 | } |
| 533 | } | 538 | } |
| 534 | } | 539 | } |
| @@ -536,43 +541,43 @@ void SchannelContext::decryptAndProcessData(const SafeByteArray& data) { | |||
| 536 | //------------------------------------------------------------------------ | 541 | //------------------------------------------------------------------------ |
| 537 | 542 | ||
| 538 | void SchannelContext::encryptAndSendData(const SafeByteArray& data) { | 543 | void SchannelContext::encryptAndSendData(const SafeByteArray& data) { |
| 539 | if (m_streamSizes.cbMaximumMessage == 0) { | 544 | if (streamSizes_.cbMaximumMessage == 0) { |
| 540 | return; | 545 | return; |
| 541 | } | 546 | } |
| 542 | 547 | ||
| 543 | SecBuffer outBuffers[4] = {0}; | 548 | SecBuffer outBuffers[4] = {0}; |
| 544 | 549 | ||
| 545 | // Calculate the largest required size of the send buffer | 550 | // Calculate the largest required size of the send buffer |
| 546 | size_t messageBufferSize = (data.size() > m_streamSizes.cbMaximumMessage) | 551 | size_t messageBufferSize = (data.size() > streamSizes_.cbMaximumMessage) |
| 547 | ? m_streamSizes.cbMaximumMessage | 552 | ? streamSizes_.cbMaximumMessage |
| 548 | : data.size(); | 553 | : data.size(); |
| 549 | 554 | ||
| 550 | // Allocate a packet for the encrypted data | 555 | // Allocate a packet for the encrypted data |
| 551 | SafeByteArray sendBuffer; | 556 | SafeByteArray sendBuffer; |
| 552 | sendBuffer.resize(m_streamSizes.cbHeader + messageBufferSize + m_streamSizes.cbTrailer); | 557 | sendBuffer.resize(streamSizes_.cbHeader + messageBufferSize + streamSizes_.cbTrailer); |
| 553 | 558 | ||
| 554 | size_t bytesSent = 0; | 559 | size_t bytesSent = 0; |
| 555 | do { | 560 | do { |
| 556 | size_t bytesLeftToSend = data.size() - bytesSent; | 561 | size_t bytesLeftToSend = data.size() - bytesSent; |
| 557 | 562 | ||
| 558 | // Calculate how much of the send buffer we'll be using for this chunk | 563 | // Calculate how much of the send buffer we'll be using for this chunk |
| 559 | size_t bytesToSend = (bytesLeftToSend > m_streamSizes.cbMaximumMessage) | 564 | size_t bytesToSend = (bytesLeftToSend > streamSizes_.cbMaximumMessage) |
| 560 | ? m_streamSizes.cbMaximumMessage | 565 | ? streamSizes_.cbMaximumMessage |
| 561 | : bytesLeftToSend; | 566 | : bytesLeftToSend; |
| 562 | 567 | ||
| 563 | // Copy the plain text data into the send buffer | 568 | // Copy the plain text data into the send buffer |
| 564 | memcpy(&sendBuffer[0] + m_streamSizes.cbHeader, &data[0] + bytesSent, bytesToSend); | 569 | memcpy(&sendBuffer[0] + streamSizes_.cbHeader, &data[0] + bytesSent, bytesToSend); |
| 565 | 570 | ||
| 566 | outBuffers[0].pvBuffer = &sendBuffer[0]; | 571 | outBuffers[0].pvBuffer = &sendBuffer[0]; |
| 567 | outBuffers[0].cbBuffer = m_streamSizes.cbHeader; | 572 | outBuffers[0].cbBuffer = streamSizes_.cbHeader; |
| 568 | outBuffers[0].BufferType = SECBUFFER_STREAM_HEADER; | 573 | outBuffers[0].BufferType = SECBUFFER_STREAM_HEADER; |
| 569 | 574 | ||
| 570 | outBuffers[1].pvBuffer = &sendBuffer[0] + m_streamSizes.cbHeader; | 575 | outBuffers[1].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader; |
| 571 | outBuffers[1].cbBuffer = (unsigned long)bytesToSend; | 576 | outBuffers[1].cbBuffer = (unsigned long)bytesToSend; |
| 572 | outBuffers[1].BufferType = SECBUFFER_DATA; | 577 | outBuffers[1].BufferType = SECBUFFER_DATA; |
| 573 | 578 | ||
| 574 | outBuffers[2].pvBuffer = &sendBuffer[0] + m_streamSizes.cbHeader + bytesToSend; | 579 | outBuffers[2].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader + bytesToSend; |
| 575 | outBuffers[2].cbBuffer = m_streamSizes.cbTrailer; | 580 | outBuffers[2].cbBuffer = streamSizes_.cbTrailer; |
| 576 | outBuffers[2].BufferType = SECBUFFER_STREAM_TRAILER; | 581 | outBuffers[2].BufferType = SECBUFFER_STREAM_TRAILER; |
| 577 | 582 | ||
| 578 | outBuffers[3].pvBuffer = 0; | 583 | outBuffers[3].pvBuffer = 0; |
| @@ -584,7 +589,7 @@ void SchannelContext::encryptAndSendData(const SafeByteArray& data) { | |||
| 584 | outBufferDesc.pBuffers = outBuffers; | 589 | outBufferDesc.pBuffers = outBuffers; |
| 585 | outBufferDesc.ulVersion = SECBUFFER_VERSION; | 590 | outBufferDesc.ulVersion = SECBUFFER_VERSION; |
| 586 | 591 | ||
| 587 | SECURITY_STATUS status = EncryptMessage(m_ctxtHandle, 0, &outBufferDesc, 0); | 592 | SECURITY_STATUS status = EncryptMessage(contextHandle_, 0, &outBufferDesc, 0); |
| 588 | if (status != SEC_E_OK) { | 593 | if (status != SEC_E_OK) { |
| 589 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); | 594 | indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); |
| 590 | return; | 595 | return; |
| @@ -604,14 +609,14 @@ bool SchannelContext::setClientCertificate(CertificateWithKey::ref certificate) | |||
| 604 | return false; | 609 | return false; |
| 605 | } | 610 | } |
| 606 | 611 | ||
| 607 | userCertificate = capiCertificate; | 612 | userCertificate_ = capiCertificate; |
| 608 | 613 | ||
| 609 | // We assume that the Certificate Store Name/Certificate Name | 614 | // We assume that the Certificate Store Name/Certificate Name |
| 610 | // are valid at this point | 615 | // are valid at this point |
| 611 | m_cert_store_name = capiCertificate->getCertStoreName(); | 616 | certStoreName_ = capiCertificate->getCertStoreName(); |
| 612 | m_cert_name = capiCertificate->getCertName(); | 617 | certName_ = capiCertificate->getCertName(); |
| 613 | ////At the moment this is only useful for logging: | 618 | ////At the moment this is only useful for logging: |
| 614 | m_smartcard_reader = capiCertificate->getSmartCardReaderName(); | 619 | smartCardReader_ = capiCertificate->getSmartCardReaderName(); |
| 615 | 620 | ||
| 616 | capiCertificate->onCertificateCardRemoved.connect(boost::bind(&SchannelContext::handleCertificateCardRemoved, this)); | 621 | capiCertificate->onCertificateCardRemoved.connect(boost::bind(&SchannelContext::handleCertificateCardRemoved, this)); |
| 617 | 622 | ||
| @@ -630,7 +635,7 @@ std::vector<Certificate::ref> SchannelContext::getPeerCertificateChain() const { | |||
| 630 | ScopedCertContext pServerCert; | 635 | ScopedCertContext pServerCert; |
| 631 | ScopedCertContext pIssuerCert; | 636 | ScopedCertContext pIssuerCert; |
| 632 | ScopedCertContext pCurrentCert; | 637 | ScopedCertContext pCurrentCert; |
| 633 | SECURITY_STATUS status = QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset()); | 638 | SECURITY_STATUS status = QueryContextAttributes(contextHandle_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset()); |
| 634 | 639 | ||
| 635 | if (status != SEC_E_OK) { | 640 | if (status != SEC_E_OK) { |
| 636 | return certificateChain; | 641 | return certificateChain; |
| @@ -655,14 +660,14 @@ std::vector<Certificate::ref> SchannelContext::getPeerCertificateChain() const { | |||
| 655 | //------------------------------------------------------------------------ | 660 | //------------------------------------------------------------------------ |
| 656 | 661 | ||
| 657 | CertificateVerificationError::ref SchannelContext::getPeerCertificateVerificationError() const { | 662 | CertificateVerificationError::ref SchannelContext::getPeerCertificateVerificationError() const { |
| 658 | return m_verificationError ? boost::make_shared<CertificateVerificationError>(*m_verificationError) : CertificateVerificationError::ref(); | 663 | return verificationError_ ? boost::make_shared<CertificateVerificationError>(*verificationError_) : CertificateVerificationError::ref(); |
| 659 | } | 664 | } |
| 660 | 665 | ||
| 661 | //------------------------------------------------------------------------ | 666 | //------------------------------------------------------------------------ |
| 662 | 667 | ||
| 663 | ByteArray SchannelContext::getFinishMessage() const { | 668 | ByteArray SchannelContext::getFinishMessage() const { |
| 664 | SecPkgContext_Bindings bindings; | 669 | SecPkgContext_Bindings bindings; |
| 665 | int ret = QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_UNIQUE_BINDINGS, &bindings); | 670 | int ret = QueryContextAttributes(contextHandle_, SECPKG_ATTR_UNIQUE_BINDINGS, &bindings); |
| 666 | if (ret == SEC_E_OK) { | 671 | if (ret == SEC_E_OK) { |
| 667 | return createByteArray(((unsigned char*) bindings.Bindings) + bindings.Bindings->dwApplicationDataOffset + 11 /* tls-unique:*/, bindings.Bindings->cbApplicationDataLength - 11); | 672 | return createByteArray(((unsigned char*) bindings.Bindings) + bindings.Bindings->dwApplicationDataOffset + 11 /* tls-unique:*/, bindings.Bindings->cbApplicationDataLength - 11); |
| 668 | } | 673 | } |
| @@ -672,7 +677,7 @@ ByteArray SchannelContext::getFinishMessage() const { | |||
| 672 | //------------------------------------------------------------------------ | 677 | //------------------------------------------------------------------------ |
| 673 | 678 | ||
| 674 | void SchannelContext::setCheckCertificateRevocation(bool b) { | 679 | void SchannelContext::setCheckCertificateRevocation(bool b) { |
| 675 | checkCertificateRevocation = b; | 680 | checkCertificateRevocation_ = b; |
| 676 | } | 681 | } |
| 677 | 682 | ||
| 678 | 683 | ||
diff --git a/Swiften/TLS/Schannel/SchannelContext.h b/Swiften/TLS/Schannel/SchannelContext.h index 3a068f2..19cc473 100644 --- a/Swiften/TLS/Schannel/SchannelContext.h +++ b/Swiften/TLS/Schannel/SchannelContext.h | |||
| @@ -37,7 +37,7 @@ namespace Swift | |||
| 37 | typedef boost::shared_ptr<SchannelContext> sp_t; | 37 | typedef boost::shared_ptr<SchannelContext> sp_t; |
| 38 | 38 | ||
| 39 | public: | 39 | public: |
| 40 | SchannelContext(); | 40 | SchannelContext(bool tls1_0Workaround); |
| 41 | 41 | ||
| 42 | ~SchannelContext(); | 42 | ~SchannelContext(); |
| 43 | 43 | ||
| @@ -86,23 +86,24 @@ namespace Swift | |||
| 86 | 86 | ||
| 87 | }; | 87 | }; |
| 88 | 88 | ||
| 89 | SchannelState m_state; | 89 | SchannelState state_; |
| 90 | boost::optional<CertificateVerificationError> m_verificationError; | 90 | boost::optional<CertificateVerificationError> verificationError_; |
| 91 | 91 | ||
| 92 | ULONG m_secContext; | 92 | ULONG secContext_; |
| 93 | ScopedCredHandle m_credHandle; | 93 | ScopedCredHandle credHandle_; |
| 94 | ScopedCtxtHandle m_ctxtHandle; | 94 | ScopedCtxtHandle contextHandle_; |
| 95 | DWORD m_ctxtFlags; | 95 | DWORD contextFlags_; |
| 96 | SecPkgContext_StreamSizes m_streamSizes; | 96 | SecPkgContext_StreamSizes streamSizes_; |
| 97 | 97 | ||
| 98 | std::vector<char> m_receivedData; | 98 | std::vector<char> receivedData_; |
| 99 | 99 | ||
| 100 | HCERTSTORE m_my_cert_store; | 100 | HCERTSTORE myCertStore_; |
| 101 | std::string m_cert_store_name; | 101 | std::string certStoreName_; |
| 102 | std::string m_cert_name; | 102 | std::string certName_; |
| 103 | ////Not needed, most likely | 103 | ////Not needed, most likely |
| 104 | std::string m_smartcard_reader; //Can be empty string for non SmartCard certificates | 104 | std::string smartCardReader_; //Can be empty string for non SmartCard certificates |
| 105 | boost::shared_ptr<CAPICertificate> userCertificate; | 105 | boost::shared_ptr<CAPICertificate> userCertificate_; |
| 106 | bool checkCertificateRevocation; | 106 | bool checkCertificateRevocation_; |
| 107 | bool tls1_0Workaround_; | ||
| 107 | }; | 108 | }; |
| 108 | } | 109 | } |
diff --git a/Swiften/TLS/Schannel/SchannelContextFactory.cpp b/Swiften/TLS/Schannel/SchannelContextFactory.cpp index 8b0044c..6e83b0d 100644 --- a/Swiften/TLS/Schannel/SchannelContextFactory.cpp +++ b/Swiften/TLS/Schannel/SchannelContextFactory.cpp | |||
| @@ -4,6 +4,12 @@ | |||
| 4 | * See Documentation/Licenses/BSD-simplified.txt for more information. | 4 | * See Documentation/Licenses/BSD-simplified.txt for more information. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | /* | ||
| 8 | * Copyright (c) 2015 Isode Limited. | ||
| 9 | * All rights reserved. | ||
| 10 | * See the COPYING file for more information. | ||
| 11 | */ | ||
| 12 | |||
| 7 | #include "Swiften/TLS/Schannel/SchannelContextFactory.h" | 13 | #include "Swiften/TLS/Schannel/SchannelContextFactory.h" |
| 8 | #include "Swiften/TLS/Schannel/SchannelContext.h" | 14 | #include "Swiften/TLS/Schannel/SchannelContext.h" |
| 9 | 15 | ||
| @@ -16,8 +22,8 @@ bool SchannelContextFactory::canCreate() const { | |||
| 16 | return true; | 22 | return true; |
| 17 | } | 23 | } |
| 18 | 24 | ||
| 19 | TLSContext* SchannelContextFactory::createTLSContext() { | 25 | TLSContext* SchannelContextFactory::createTLSContext(const TLSOptions& tlsOptions) { |
| 20 | SchannelContext* context = new SchannelContext(); | 26 | SchannelContext* context = new SchannelContext(tlsOptions.schannelTLS1_0Workaround); |
| 21 | context->setCheckCertificateRevocation(checkCertificateRevocation); | 27 | context->setCheckCertificateRevocation(checkCertificateRevocation); |
| 22 | return context; | 28 | return context; |
| 23 | } | 29 | } |
diff --git a/Swiften/TLS/Schannel/SchannelContextFactory.h b/Swiften/TLS/Schannel/SchannelContextFactory.h index 9dc835c..789d15f 100644 --- a/Swiften/TLS/Schannel/SchannelContextFactory.h +++ b/Swiften/TLS/Schannel/SchannelContextFactory.h | |||
| @@ -4,9 +4,15 @@ | |||
| 4 | * See Documentation/Licenses/BSD-simplified.txt for more information. | 4 | * See Documentation/Licenses/BSD-simplified.txt for more information. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | /* | ||
| 8 | * Copyright (c) 2015 Isode Limited. | ||
| 9 | * All rights reserved. | ||
| 10 | * See the COPYING file for more information. | ||
| 11 | */ | ||
| 12 | |||
| 7 | #pragma once | 13 | #pragma once |
| 8 | 14 | ||
| 9 | #include "Swiften/TLS/TLSContextFactory.h" | 15 | #include <Swiften/TLS/TLSContextFactory.h> |
| 10 | 16 | ||
| 11 | namespace Swift { | 17 | namespace Swift { |
| 12 | class SchannelContextFactory : public TLSContextFactory { | 18 | class SchannelContextFactory : public TLSContextFactory { |
| @@ -14,7 +20,7 @@ namespace Swift { | |||
| 14 | SchannelContextFactory(); | 20 | SchannelContextFactory(); |
| 15 | 21 | ||
| 16 | bool canCreate() const; | 22 | bool canCreate() const; |
| 17 | virtual TLSContext* createTLSContext(); | 23 | virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions); |
| 18 | 24 | ||
| 19 | virtual void setCheckCertificateRevocation(bool b); | 25 | virtual void setCheckCertificateRevocation(bool b); |
| 20 | 26 | ||
diff --git a/Swiften/TLS/TLSContextFactory.h b/Swiften/TLS/TLSContextFactory.h index 10c5577..90da4a1 100644 --- a/Swiften/TLS/TLSContextFactory.h +++ b/Swiften/TLS/TLSContextFactory.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #pragma once | 7 | #pragma once |
| 8 | 8 | ||
| 9 | #include <Swiften/Base/API.h> | 9 | #include <Swiften/Base/API.h> |
| 10 | #include <Swiften/TLS/TLSOptions.h> | ||
| 10 | 11 | ||
| 11 | namespace Swift { | 12 | namespace Swift { |
| 12 | class TLSContext; | 13 | class TLSContext; |
| @@ -17,7 +18,7 @@ namespace Swift { | |||
| 17 | 18 | ||
| 18 | virtual bool canCreate() const = 0; | 19 | virtual bool canCreate() const = 0; |
| 19 | 20 | ||
| 20 | virtual TLSContext* createTLSContext() = 0; | 21 | virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions) = 0; |
| 21 | virtual void setCheckCertificateRevocation(bool b) = 0; | 22 | virtual void setCheckCertificateRevocation(bool b) = 0; |
| 22 | }; | 23 | }; |
| 23 | } | 24 | } |
diff --git a/Swiften/TLS/TLSOptions.h b/Swiften/TLS/TLSOptions.h new file mode 100644 index 0000000..ca84829 --- /dev/null +++ b/Swiften/TLS/TLSOptions.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Isode Limited. | ||
| 3 | * All rights reserved. | ||
| 4 | * See the COPYING file for more information. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #pragma once | ||
| 8 | |||
| 9 | namespace Swift { | ||
| 10 | |||
| 11 | struct TLSOptions { | ||
| 12 | TLSOptions() : schannelTLS1_0Workaround(false) { | ||
| 13 | |||
| 14 | } | ||
| 15 | |||
| 16 | /** | ||
| 17 | * A bug in the Windows SChannel TLS stack, combined with | ||
| 18 | * overly-restrictive server stacks means it's sometimes necessary to | ||
| 19 | * not use TLS>1.0. This option has no effect unless compiled on | ||
| 20 | * Windows against SChannel (OpenSSL users are unaffected). | ||
| 21 | */ | ||
| 22 | bool schannelTLS1_0Workaround; | ||
| 23 | |||
| 24 | }; | ||
| 25 | } | ||
Swift