summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/MainController.cpp8
-rw-r--r--Swift/QtUI/QtConnectionSettings.ui7
-rw-r--r--Swift/QtUI/QtConnectionSettingsWindow.cpp8
-rw-r--r--Swiften/Client/ClientOptions.h7
-rw-r--r--Swiften/Client/CoreClient.cpp5
-rw-r--r--Swiften/Component/CoreComponent.cpp14
-rw-r--r--Swiften/Network/BOSHConnectionPool.cpp8
-rw-r--r--Swiften/Network/BOSHConnectionPool.h6
-rw-r--r--Swiften/Network/TLSConnection.cpp4
-rw-r--r--Swiften/Network/TLSConnection.h4
-rw-r--r--Swiften/Network/TLSConnectionFactory.cpp4
-rw-r--r--Swiften/Network/TLSConnectionFactory.h4
-rw-r--r--Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp11
-rw-r--r--Swiften/Session/BOSHSessionStream.cpp7
-rw-r--r--Swiften/Session/BOSHSessionStream.h11
-rw-r--r--Swiften/Session/BasicSessionStream.cpp10
-rw-r--r--Swiften/Session/BasicSessionStream.h5
-rw-r--r--Swiften/StreamStack/TLSLayer.cpp4
-rw-r--r--Swiften/StreamStack/TLSLayer.h3
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp2
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContextFactory.h2
-rw-r--r--Swiften/TLS/Schannel/SchannelContext.cpp197
-rw-r--r--Swiften/TLS/Schannel/SchannelContext.h31
-rw-r--r--Swiften/TLS/Schannel/SchannelContextFactory.cpp10
-rw-r--r--Swiften/TLS/Schannel/SchannelContextFactory.h10
-rw-r--r--Swiften/TLS/TLSContextFactory.h3
-rw-r--r--Swiften/TLS/TLSOptions.h25
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
@@ -395,25 +395,25 @@ void MainController::handleConnected() {
client_->getDiscoManager()->setCapsNode(CLIENT_NODE);
client_->getDiscoManager()->setDiscoInfo(discoInfo);
userSearchControllerChat_ = new UserSearchController(UserSearchController::StartChat, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_, contactSuggesterWithRoster_, client_->getAvatarManager(), client_->getPresenceOracle());
userSearchControllerAdd_ = new UserSearchController(UserSearchController::AddContact, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_, contactSuggesterWithoutRoster_, client_->getAvatarManager(), client_->getPresenceOracle());
adHocManager_ = new AdHocManager(JID(boundJID_.getDomain()), uiFactory_, client_->getIQRouter(), uiEventStream_, rosterController_->getWindow());
-
+
chatsManager_->onImpromptuMUCServiceDiscovered.connect(boost::bind(&UserSearchController::setCanInitiateImpromptuMUC, userSearchControllerChat_, _1));
}
loginWindow_->setIsLoggingIn(false);
client_->requestRoster();
GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(JID(boundJID_.getDomain()), client_->getIQRouter());
discoInfoRequest->onResponse.connect(boost::bind(&MainController::handleServerDiscoInfoResponse, this, _1, _2));
discoInfoRequest->send();
client_->getVCardManager()->requestOwnVCard();
-
+
rosterController_->setJID(boundJID_);
rosterController_->setEnabled(true);
rosterController_->getWindow()->setStreamEncryptionStatus(client_->isStreamEncrypted());
profileController_->setAvailable(true);
contactEditController_->setAvailable(true);
/* Send presence later to catch all the incoming presences. */
@@ -838,16 +838,17 @@ std::string MainController::serializeClientOptions(const ClientOptions& options)
SERIALIZE_STRING(manualProxyHostname);
SERIALIZE_INT(manualProxyPort);
SERIALIZE_URL(boshURL);
SERIALIZE_URL(boshHTTPConnectProxyURL);
SERIALIZE_SAFE_STRING(boshHTTPConnectProxyAuthID);
SERIALIZE_SAFE_STRING(boshHTTPConnectProxyAuthPassword);
+ SERIALIZE_BOOL(tlsOptions.schannelTLS1_0Workaround);
return result;
}
-#define CHECK_PARSE_LENGTH if (i >= segments.size()) {return result;}
+#define CHECK_PARSE_LENGTH if (i >= segments.size()) {return result;}
#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++;
#define PARSE_STRING_RAW CHECK_PARSE_LENGTH stringVal = byteArrayToString(Base64::decode(segments[i]));i++;
#define PARSE_BOOL(option, defaultValue) PARSE_INT_RAW(defaultValue); result.option = (intVal == 1);
#define PARSE_INT(option, defaultValue) PARSE_INT_RAW(defaultValue); result.option = intVal;
#define PARSE_STRING(option) PARSE_STRING_RAW; result.option = stringVal;
@@ -885,11 +886,12 @@ ClientOptions MainController::parseClientOptions(const std::string& optionString
PARSE_STRING(manualProxyHostname);
PARSE_INT(manualProxyPort, -1);
PARSE_URL(boshURL);
PARSE_URL(boshHTTPConnectProxyURL);
PARSE_SAFE_STRING(boshHTTPConnectProxyAuthID);
PARSE_SAFE_STRING(boshHTTPConnectProxyAuthPassword);
+ PARSE_BOOL(tlsOptions.schannelTLS1_0Workaround, false);
return result;
}
}
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
@@ -133,12 +133,19 @@
<property name="text">
<string>Allow sending password over insecure connection</string>
</property>
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="manual_forceTLS1_0">
+ <property name="text">
+ <string>Limit encryption to TLS 1.0</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</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,8 +1,8 @@
/*
- * Copyright (c) 2012 Isode Limited.
+ * Copyright (c) 2012-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include "Swift/QtUI/QtConnectionSettingsWindow.h"
@@ -64,12 +64,13 @@ QtConnectionSettingsWindow::QtConnectionSettingsWindow(const ClientOptions& opti
isDefault &= options.useAcks == defaults.useAcks;
isDefault &= options.manualHostname == defaults.manualHostname;
isDefault &= options.manualPort == defaults.manualPort;
isDefault &= options.proxyType == defaults.proxyType;
isDefault &= options.manualProxyHostname == defaults.manualProxyHostname;
isDefault &= options.manualProxyPort == defaults.manualProxyPort;
+ isDefault &= options.tlsOptions.schannelTLS1_0Workaround == defaults.tlsOptions.schannelTLS1_0Workaround;
if (isDefault) {
ui.connectionMethod->setCurrentIndex(0);
}
else {
ui.connectionMethod->setCurrentIndex(1);
ui.manual_useTLS->setCurrentIndex(options.useTLS);
@@ -85,24 +86,28 @@ QtConnectionSettingsWindow::QtConnectionSettingsWindow(const ClientOptions& opti
ui.manual_proxyType->setCurrentIndex(options.proxyType);
if (!options.manualProxyHostname.empty()) {
ui.manual_manualProxy->setChecked(true);
ui.manual_manualProxyHost->setText(P2QSTRING(options.manualProxyHostname));
ui.manual_manualProxyPort->setText(P2QSTRING(boost::lexical_cast<std::string>(options.manualProxyPort)));
}
+ ui.manual_forceTLS1_0->setChecked(options.tlsOptions.schannelTLS1_0Workaround);
}
} else {
ui.connectionMethod->setCurrentIndex(2);
ui.bosh_uri->setText(P2QSTRING(options.boshURL.toString()));
if (!options.boshHTTPConnectProxyURL.isEmpty()) {
ui.bosh_manualProxy->setChecked(true);
ui.bosh_manualProxyHost->setText(P2QSTRING(options.boshHTTPConnectProxyURL.getHost()));
if (options.boshHTTPConnectProxyURL.getPort()) {
ui.bosh_manualProxyPort->setText(P2QSTRING(boost::lexical_cast<std::string>(*options.boshHTTPConnectProxyURL.getPort())));
}
}
}
+#ifndef HAVE_SCHANNEL
+ ui.manual_forceTLS1_0->hide();
+#endif
}
void QtConnectionSettingsWindow::handleProxyTypeChanged(int index) {
bool proxySettingsVisible = index != NoProxy && index != SystemProxy;
ui.manual_manualProxy->setVisible(proxySettingsVisible);
ui.manual_manualProxyHostLabel->setVisible(proxySettingsVisible);
@@ -126,12 +131,13 @@ ClientOptions QtConnectionSettingsWindow::getOptions() {
/* Not automatic */
if (ui.connectionMethod->currentIndex() == 1) {
/* Manual */
options.useTLS = static_cast<ClientOptions::UseTLS>(ui.manual_useTLS->currentIndex());
options.useStreamCompression = ui.manual_allowCompression->isChecked();
options.allowPLAINWithoutTLS = ui.manual_allowPLAINWithoutTLS->isChecked();
+ options.tlsOptions.schannelTLS1_0Workaround = ui.manual_forceTLS1_0->isChecked();
if (ui.manual_manualHost->isChecked()) {
options.manualHostname = Q2PSTRING(ui.manual_manualHostName->text());
try {
options.manualPort = boost::lexical_cast<int>(Q2PSTRING(ui.manual_manualHostPort->text()));
} catch (const boost::bad_lexical_cast&) {
options.manualPort = -1;
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
@@ -8,12 +8,14 @@
#include <boost/shared_ptr.hpp>
#include <Swiften/Base/API.h>
#include <Swiften/Base/URL.h>
#include <Swiften/Base/SafeString.h>
+#include <Swiften/TLS/TLSOptions.h>
+
namespace Swift {
class HTTPTrafficFilter;
struct SWIFTEN_API ClientOptions {
enum UseTLS {
@@ -142,8 +144,13 @@ namespace Swift {
/**
* This can be initialized with a custom HTTPTrafficFilter, which allows HTTP CONNECT
* proxy initialization to be customized.
*/
boost::shared_ptr<HTTPTrafficFilter> httpTrafficFilter;
+
+ /**
+ * Options passed to the TLS stack
+ */
+ TLSOptions tlsOptions;
};
}
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
@@ -135,13 +135,14 @@ void CoreClient::connect(const ClientOptions& o) {
networkFactories->getXMLParserFactory(),
networkFactories->getEventLoop(),
networkFactories->getDomainNameResolver(),
host,
options.boshHTTPConnectProxyURL,
options.boshHTTPConnectProxyAuthID,
- options.boshHTTPConnectProxyAuthPassword));
+ options.boshHTTPConnectProxyAuthPassword,
+ options.tlsOptions));
sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1));
sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1));
bindSessionToStream();
}
}
@@ -186,13 +187,13 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio
}
else {
assert(!connection_);
connection_ = connection;
assert(!sessionStream_);
- sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory());
+ sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), options.tlsOptions);
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));
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,25 +1,27 @@
/*
- * Copyright (c) 2010-2013 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swiften/Component/CoreComponent.h>
#include <boost/bind.hpp>
#include <iostream>
+#include <Swiften/Base/IDGenerator.h>
#include <Swiften/Component/ComponentSession.h>
+#include <Swiften/Component/ComponentSessionStanzaChannel.h>
#include <Swiften/Network/Connector.h>
#include <Swiften/Network/NetworkFactories.h>
-#include <Swiften/TLS/PKCS12Certificate.h>
-#include <Swiften/Session/BasicSessionStream.h>
#include <Swiften/Queries/IQRouter.h>
-#include <Swiften/Base/IDGenerator.h>
-#include <Swiften/Component/ComponentSessionStanzaChannel.h>
+#include <Swiften/Session/BasicSessionStream.h>
+#include <Swiften/TLS/PKCS12Certificate.h>
+#include <Swiften/TLS/TLSOptions.h>
+
namespace Swift {
CoreComponent::CoreComponent(const JID& jid, const std::string& secret, NetworkFactories* networkFactories) : networkFactories(networkFactories), jid_(jid), secret_(secret), disconnectRequested_(false) {
stanzaChannel_ = new ComponentSessionStanzaChannel();
stanzaChannel_->onMessageReceived.connect(boost::ref(onMessageReceived));
@@ -60,13 +62,13 @@ void CoreComponent::handleConnectorFinished(boost::shared_ptr<Connection> connec
}
else {
assert(!connection_);
connection_ = connection;
assert(!sessionStream_);
- sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), NULL, networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory()));
+ sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), NULL, networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), TLSOptions()));
sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1));
sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1));
session_ = ComponentSession::create(jid_, secret_, sessionStream_, networkFactories->getCryptoProvider());
stanzaChannel_->setSession(session_);
session_->onFinished.connect(boost::bind(&CoreComponent::handleSessionFinished, this, _1));
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,8 +1,8 @@
/*
- * Copyright (c) 2011 Isode Limited.
+ * Copyright (c) 2011-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swiften/Network/BOSHConnectionPool.h>
#include <climits>
@@ -14,13 +14,13 @@
#include <Swiften/Base/SafeString.h>
#include <Swiften/Network/TLSConnectionFactory.h>
#include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h>
#include <Swiften/Network/CachingDomainNameResolver.h>
namespace Swift {
-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) :
+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) :
boshURL(boshURL),
connectionFactory(connectionFactoryParameter),
xmlParserFactory(parserFactory),
timerFactory(timerFactory),
rid(initialRID),
pendingTerminate(false),
@@ -28,19 +28,19 @@ BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* r
requestLimit(2),
restartCount(0),
pendingRestart(false) {
if (!boshHTTPConnectProxyURL.isEmpty()) {
if (boshHTTPConnectProxyURL.getScheme() == "https") {
- connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory);
+ connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory, tlsOptions);
myConnectionFactories.push_back(connectionFactory);
}
connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, boshHTTPConnectProxyURL.getHost(), URL::getPortOrDefaultPort(boshHTTPConnectProxyURL), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword);
}
if (boshURL.getScheme() == "https") {
- connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory);
+ connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory, tlsOptions);
myConnectionFactories.push_back(connectionFactory);
}
resolver = new CachingDomainNameResolver(realResolver, eventLoop);
createConnection();
}
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,30 +1,32 @@
/*
- * Copyright (c) 2011 Isode Limited.
+ * Copyright (c) 2011-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#pragma once
#include <vector>
#include <Swiften/Base/API.h>
#include <Swiften/Base/SafeString.h>
#include <Swiften/Network/BOSHConnection.h>
+#include <Swiften/TLS/TLSOptions.h>
+
namespace Swift {
class HTTPConnectProxiedConnectionFactory;
class TLSConnectionFactory;
class CachingDomainNameResolver;
class EventLoop;
class SWIFTEN_API BOSHConnectionPool : public boost::bsignals::trackable {
public:
- 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);
+ 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);
~BOSHConnectionPool();
void write(const SafeByteArray& data);
void writeFooter();
void close();
void restartStream();
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
@@ -11,14 +11,14 @@
#include <Swiften/Network/HostAddressPort.h>
#include <Swiften/TLS/TLSContext.h>
#include <Swiften/TLS/TLSContextFactory.h>
namespace Swift {
-TLSConnection::TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory) : connection(connection) {
- context = tlsFactory->createTLSContext();
+TLSConnection::TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory, const TLSOptions& tlsOptions) : connection(connection) {
+ context = tlsFactory->createTLSContext(tlsOptions);
context->onDataForNetwork.connect(boost::bind(&TLSConnection::handleTLSDataForNetwork, this, _1));
context->onDataForApplication.connect(boost::bind(&TLSConnection::handleTLSDataForApplication, this, _1));
context->onConnected.connect(boost::bind(&TLSConnection::handleTLSConnectFinished, this, false));
context->onError.connect(boost::bind(&TLSConnection::handleTLSConnectFinished, this, true));
connection->onConnectFinished.connect(boost::bind(&TLSConnection::handleRawConnectFinished, this, _1));
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
@@ -10,22 +10,24 @@
#include <boost/enable_shared_from_this.hpp>
#include <Swiften/Base/boost_bsignals.h>
#include <Swiften/Base/API.h>
#include <Swiften/Base/SafeByteArray.h>
#include <Swiften/Network/Connection.h>
+#include <Swiften/TLS/TLSOptions.h>
+
namespace Swift {
class HostAddressPort;
class TLSContextFactory;
class TLSContext;
class SWIFTEN_API TLSConnection : public Connection {
public:
- TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory);
+ TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory, const TLSOptions&);
virtual ~TLSConnection();
virtual void listen() {assert(false);}
virtual void connect(const HostAddressPort& address);
virtual void disconnect();
virtual void write(const SafeByteArray& data);
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
@@ -9,20 +9,20 @@
#include <boost/shared_ptr.hpp>
#include <Swiften/Network/TLSConnection.h>
namespace Swift {
-TLSConnectionFactory::TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory) : contextFactory(contextFactory), connectionFactory(connectionFactory){
+TLSConnectionFactory::TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory, const TLSOptions& o) : contextFactory(contextFactory), connectionFactory(connectionFactory), options_(o) {
}
TLSConnectionFactory::~TLSConnectionFactory() {
}
boost::shared_ptr<Connection> TLSConnectionFactory::createConnection() {
- return boost::make_shared<TLSConnection>(connectionFactory->createConnection(), contextFactory);
+ return boost::make_shared<TLSConnection>(connectionFactory->createConnection(), contextFactory, options_);
}
}
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
@@ -8,21 +8,23 @@
#include <boost/shared_ptr.hpp>
#include <Swiften/Base/API.h>
#include <Swiften/Network/ConnectionFactory.h>
#include <Swiften/TLS/TLSContextFactory.h>
+#include <Swiften/TLS/TLSOptions.h>
namespace Swift {
class Connection;
class SWIFTEN_API TLSConnectionFactory : public ConnectionFactory {
public:
- TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory);
+ TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory, const TLSOptions&);
virtual ~TLSConnectionFactory();
virtual boost::shared_ptr<Connection> createConnection();
private:
TLSContextFactory* contextFactory;
ConnectionFactory* connectionFactory;
+ TLSOptions options_;
};
}
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
@@ -13,21 +13,22 @@
#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/lexical_cast.hpp>
#include <Swiften/Base/Algorithm.h>
-#include <Swiften/Network/Connection.h>
-#include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/EventLoop/DummyEventLoop.h>
#include <Swiften/Network/BOSHConnection.h>
#include <Swiften/Network/BOSHConnectionPool.h>
+#include <Swiften/Network/Connection.h>
+#include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Network/DummyTimerFactory.h>
#include <Swiften/Network/HostAddressPort.h>
#include <Swiften/Network/StaticDomainNameResolver.h>
-#include <Swiften/Network/DummyTimerFactory.h>
-#include <Swiften/EventLoop/DummyEventLoop.h>
#include <Swiften/Parser/PlatformXMLParserFactory.h>
+#include <Swiften/TLS/TLSOptions.h>
using namespace Swift;
typedef boost::shared_ptr<BOSHConnectionPool> PoolRef;
@@ -319,13 +320,13 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
}
private:
PoolRef createTestling() {
- BOSHConnectionPool* a = new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""));
+ BOSHConnectionPool* a = new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""), TLSOptions());
PoolRef pool(a);
//FIXME: Remko - why does the above work, but the below fail?
//PoolRef pool = boost::make_shared<BOSHConnectionPool>(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""));
pool->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleXMPPDataRead, this, _1));
pool->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataRead, this, _1));
pool->onBOSHDataWritten.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataWritten, this, _1));
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,8 +1,8 @@
/*
- * Copyright (c) 2011-2014 Isode Limited.
+ * Copyright (c) 2011-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swiften/Session/BOSHSessionStream.h>
@@ -36,23 +36,24 @@ BOSHSessionStream::BOSHSessionStream(
XMLParserFactory* xmlParserFactory,
EventLoop* eventLoop,
DomainNameResolver* resolver,
const std::string& to,
const URL& boshHTTPConnectProxyURL,
const SafeString& boshHTTPConnectProxyAuthID,
- const SafeString& boshHTTPConnectProxyAuthPassword) :
+ const SafeString& boshHTTPConnectProxyAuthPassword,
+ const TLSOptions& tlsOptions) :
available(false),
eventLoop(eventLoop),
firstHeader(true) {
boost::mt19937 random;
boost::uniform_int<unsigned long long> dist(0, (1LL<<53) - 1);
random.seed(static_cast<unsigned int>(time(NULL)));
unsigned long long initialRID = boost::variate_generator<boost::mt19937&, boost::uniform_int<unsigned long long> >(random, dist)();
- connectionPool = new BOSHConnectionPool(boshURL, resolver, connectionFactory, xmlParserFactory, tlsContextFactory, timerFactory, eventLoop, to, initialRID, boshHTTPConnectProxyURL, boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword);
+ connectionPool = new BOSHConnectionPool(boshURL, resolver, connectionFactory, xmlParserFactory, tlsContextFactory, timerFactory, eventLoop, to, initialRID, boshHTTPConnectProxyURL, boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword, tlsOptions);
connectionPool->onSessionTerminated.connect(boost::bind(&BOSHSessionStream::handlePoolSessionTerminated, this, _1));
connectionPool->onSessionStarted.connect(boost::bind(&BOSHSessionStream::handlePoolSessionStarted, this));
connectionPool->onXMPPDataRead.connect(boost::bind(&BOSHSessionStream::handlePoolXMPPDataRead, this, _1));
connectionPool->onBOSHDataRead.connect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataRead, this, _1));
connectionPool->onBOSHDataWritten.connect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataWritten, 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
@@ -6,18 +6,20 @@
#pragma once
#include <boost/shared_ptr.hpp>
#include <Swiften/Base/API.h>
-#include <Swiften/Base/SafeString.h>
#include <Swiften/Base/SafeByteArray.h>
-#include <Swiften/Network/BOSHConnectionPool.h>
-#include <Swiften/Session/SessionStream.h>
+#include <Swiften/Base/SafeString.h>
#include <Swiften/Elements/StreamType.h>
#include <Swiften/EventLoop/EventOwner.h>
+#include <Swiften/Network/BOSHConnectionPool.h>
+#include <Swiften/Session/SessionStream.h>
+#include <Swiften/TLS/TLSOptions.h>
+
namespace Swift {
class TimerFactory;
class PayloadParserFactoryCollection;
class PayloadSerializerCollection;
class StreamStack;
@@ -40,13 +42,14 @@ namespace Swift {
XMLParserFactory* xmlParserFactory,
EventLoop* eventLoop,
DomainNameResolver* resolver,
const std::string& to,
const URL& boshHTTPConnectProxyURL,
const SafeString& boshHTTPConnectProxyAuthID,
- const SafeString& boshHTTPConnectProxyAuthPassword
+ const SafeString& boshHTTPConnectProxyAuthPassword,
+ const TLSOptions& tlsOptions
);
~BOSHSessionStream();
virtual void close();
virtual bool isOpen();
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,8 +1,8 @@
/*
- * Copyright (c) 2010-2014 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swiften/Session/BasicSessionStream.h>
@@ -24,20 +24,22 @@ BasicSessionStream::BasicSessionStream(
StreamType streamType,
boost::shared_ptr<Connection> connection,
PayloadParserFactoryCollection* payloadParserFactories,
PayloadSerializerCollection* payloadSerializers,
TLSContextFactory* tlsContextFactory,
TimerFactory* timerFactory,
- XMLParserFactory* xmlParserFactory) :
+ XMLParserFactory* xmlParserFactory,
+ const TLSOptions& tlsOptions) :
available(false),
connection(connection),
tlsContextFactory(tlsContextFactory),
timerFactory(timerFactory),
compressionLayer(NULL),
tlsLayer(NULL),
- whitespacePingLayer(NULL) {
+ whitespacePingLayer(NULL),
+ tlsOptions_(tlsOptions) {
xmppLayer = new XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, streamType);
xmppLayer->onStreamStart.connect(boost::bind(&BasicSessionStream::handleStreamStartReceived, this, _1));
xmppLayer->onElement.connect(boost::bind(&BasicSessionStream::handleElementReceived, this, _1));
xmppLayer->onError.connect(boost::bind(&BasicSessionStream::handleXMPPError, this));
xmppLayer->onDataRead.connect(boost::bind(&BasicSessionStream::handleDataRead, this, _1));
xmppLayer->onWriteData.connect(boost::bind(&BasicSessionStream::handleDataWritten, this, _1));
@@ -103,13 +105,13 @@ bool BasicSessionStream::isOpen() {
bool BasicSessionStream::supportsTLSEncryption() {
return tlsContextFactory && tlsContextFactory->canCreate();
}
void BasicSessionStream::addTLSEncryption() {
assert(available);
- tlsLayer = new TLSLayer(tlsContextFactory);
+ tlsLayer = new TLSLayer(tlsContextFactory, tlsOptions_);
if (hasTLSCertificate() && !tlsLayer->setClientCertificate(getTLSCertificate())) {
onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::InvalidTLSCertificateError));
}
else {
streamStack->addLayer(tlsLayer);
tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this, _1));
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
@@ -11,12 +11,13 @@
#include <Swiften/Base/API.h>
#include <Swiften/Base/SafeByteArray.h>
#include <Swiften/Network/Connection.h>
#include <Swiften/Session/SessionStream.h>
#include <Swiften/Elements/StreamType.h>
#include <Swiften/TLS/TLSError.h>
+#include <Swiften/TLS/TLSOptions.h>
namespace Swift {
class TLSContextFactory;
class TLSLayer;
class TimerFactory;
class WhitespacePingLayer;
@@ -34,13 +35,14 @@ namespace Swift {
StreamType streamType,
boost::shared_ptr<Connection> connection,
PayloadParserFactoryCollection* payloadParserFactories,
PayloadSerializerCollection* payloadSerializers,
TLSContextFactory* tlsContextFactory,
TimerFactory* whitespacePingLayerFactory,
- XMLParserFactory* xmlParserFactory
+ XMLParserFactory* xmlParserFactory,
+ const TLSOptions& tlsOptions
);
~BasicSessionStream();
virtual void close();
virtual bool isOpen();
@@ -83,9 +85,10 @@ namespace Swift {
XMPPLayer* xmppLayer;
ConnectionLayer* connectionLayer;
CompressionLayer* compressionLayer;
TLSLayer* tlsLayer;
WhitespacePingLayer* whitespacePingLayer;
StreamStack* streamStack;
+ TLSOptions tlsOptions_;
};
}
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
@@ -10,14 +10,14 @@
#include <Swiften/TLS/TLSContextFactory.h>
#include <Swiften/TLS/TLSContext.h>
namespace Swift {
-TLSLayer::TLSLayer(TLSContextFactory* factory) {
- context = factory->createTLSContext();
+TLSLayer::TLSLayer(TLSContextFactory* factory, const TLSOptions& tlsOptions) {
+ context = factory->createTLSContext(tlsOptions);
context->onDataForNetwork.connect(boost::bind(&TLSLayer::writeDataToChildLayer, this, _1));
context->onDataForApplication.connect(boost::bind(&TLSLayer::writeDataToParentLayer, this, _1));
context->onConnected.connect(onConnected);
context->onError.connect(onError);
}
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
@@ -12,20 +12,21 @@
#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>
#include <Swiften/TLS/TLSError.h>
+#include <Swiften/TLS/TLSOptions.h>
namespace Swift {
class TLSContext;
class TLSContextFactory;
class SWIFTEN_API TLSLayer : public StreamLayer {
public:
- TLSLayer(TLSContextFactory*);
+ TLSLayer(TLSContextFactory*, const TLSOptions&);
~TLSLayer();
void connect();
bool setClientCertificate(CertificateWithKey::ref cert);
Certificate::ref getPeerCertificate() const;
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
@@ -11,13 +11,13 @@
namespace Swift {
bool OpenSSLContextFactory::canCreate() const {
return true;
}
-TLSContext* OpenSSLContextFactory::createTLSContext() {
+TLSContext* OpenSSLContextFactory::createTLSContext(const TLSOptions&) {
return new OpenSSLContext();
}
void OpenSSLContextFactory::setCheckCertificateRevocation(bool check) {
if (check) {
assert(false);
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
@@ -11,12 +11,12 @@
#include <cassert>
namespace Swift {
class OpenSSLContextFactory : public TLSContextFactory {
public:
bool canCreate() const;
- virtual TLSContext* createTLSContext();
+ virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions);
// Not supported
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
@@ -2,13 +2,13 @@
* Copyright (c) 2011 Soren Dreijer
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
/*
- * Copyright (c) 2012 Isode Limited.
+ * Copyright (c) 2012-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <boost/bind.hpp>
@@ -18,70 +18,75 @@
#include <WinHTTP.h> /* For SECURITY_FLAG_IGNORE_CERT_CN_INVALID */
namespace Swift {
//------------------------------------------------------------------------
-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) {
- m_ctxtFlags = ISC_REQ_ALLOCATE_MEMORY |
+SchannelContext::SchannelContext(bool tls1_0Workaround) : state_(Start), secContext_(0), myCertStore_(NULL), certStoreName_("MY"), certName_(), smartCardReader_(), checkCertificateRevocation_(true), tls1_0Workaround_(tls1_0Workaround) {
+ contextFlags_ = 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;
- ZeroMemory(&m_streamSizes, sizeof(m_streamSizes));
+ ZeroMemory(&streamSizes_, sizeof(streamSizes_));
}
//------------------------------------------------------------------------
SchannelContext::~SchannelContext() {
- if (m_my_cert_store) CertCloseStore(m_my_cert_store, 0);
+ if (myCertStore_) CertCloseStore(myCertStore_, 0);
}
//------------------------------------------------------------------------
void SchannelContext::determineStreamSizes() {
- QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_STREAM_SIZES, &m_streamSizes);
+ QueryContextAttributes(contextHandle_, SECPKG_ATTR_STREAM_SIZES, &streamSizes_);
}
//------------------------------------------------------------------------
void SchannelContext::connect() {
ScopedCertContext pCertContext;
- m_state = Connecting;
+ state_ = Connecting;
// If a user name is specified, then attempt to find a client
// certificate. Otherwise, just create a NULL credential.
- if (!m_cert_name.empty()) {
- if (m_my_cert_store == NULL) {
- m_my_cert_store = CertOpenSystemStore(0, m_cert_store_name.c_str());
- if (!m_my_cert_store) {
+ if (!certName_.empty()) {
+ if (myCertStore_ == NULL) {
+ myCertStore_ = CertOpenSystemStore(0, certStoreName_.c_str());
+ if (!myCertStore_) {
indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
return;
}
}
- pCertContext = findCertificateInStore( m_my_cert_store, m_cert_name );
+ pCertContext = findCertificateInStore( myCertStore_, certName_ );
if (pCertContext == NULL) {
indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
return;
}
}
// We use an empty list for client certificates
PCCERT_CONTEXT clientCerts[1] = {0};
SCHANNEL_CRED sc = {0};
sc.dwVersion = SCHANNEL_CRED_VERSION;
-/////SSL3?
- sc.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
+ if (tls1_0Workaround_) {
+ sc.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT;
+ }
+ else {
+ sc.grbitEnabledProtocols = /*SP_PROT_SSL3_CLIENT | */SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
+ }
+
sc.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
if (pCertContext) {
sc.cCreds = 1;
sc.paCred = pCertContext.GetPointer();
sc.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
@@ -100,15 +105,15 @@ void SchannelContext::connect() {
UNISP_NAME,
SECPKG_CRED_OUTBOUND,
NULL,
&sc,
NULL,
NULL,
- m_credHandle.Reset(),
+ credHandle_.Reset(),
NULL);
-
+
if (status != SEC_E_OK) {
// We failed to obtain the credentials handle
indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
return;
}
@@ -132,23 +137,23 @@ void SchannelContext::connect() {
outBufferDesc.cBuffers = 2;
outBufferDesc.pBuffers = outBuffers;
outBufferDesc.ulVersion = SECBUFFER_VERSION;
// Create the initial security context
status = InitializeSecurityContext(
- m_credHandle,
+ credHandle_,
NULL,
NULL,
- m_ctxtFlags,
+ contextFlags_,
0,
0,
NULL,
0,
- m_ctxtHandle.Reset(),
+ contextHandle_.Reset(),
&outBufferDesc,
- &m_secContext,
+ &secContext_,
NULL);
if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
// We failed to initialize the security context
handleCertError(status);
indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
@@ -161,13 +166,13 @@ void SchannelContext::connect() {
if (status == SEC_E_OK) {
status = validateServerCertificate();
if (status != SEC_E_OK) {
handleCertError(status);
}
- m_state = Connected;
+ state_ = Connected;
determineStreamSizes();
onConnected();
}
}
@@ -176,13 +181,13 @@ void SchannelContext::connect() {
SECURITY_STATUS SchannelContext::validateServerCertificate() {
SchannelCertificate::ref pServerCert = boost::dynamic_pointer_cast<SchannelCertificate>( getPeerCertificate() );
if (!pServerCert) {
return SEC_E_WRONG_PRINCIPAL;
}
- const LPSTR usage[] =
+ const LPSTR usage[] =
{
szOID_PKIX_KP_SERVER_AUTH,
szOID_SERVER_GATED_CRYPTO,
szOID_SGC_NETSCAPE
};
@@ -190,13 +195,13 @@ SECURITY_STATUS SchannelContext::validateServerCertificate() {
chainParams.cbSize = sizeof(chainParams);
chainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
chainParams.RequestedUsage.Usage.cUsageIdentifier = ARRAYSIZE(usage);
chainParams.RequestedUsage.Usage.rgpszUsageIdentifier = const_cast<LPSTR*>(usage);
DWORD chainFlags = CERT_CHAIN_CACHE_END_CERT;
- if (checkCertificateRevocation) {
+ if (checkCertificateRevocation_) {
chainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
}
ScopedCertChainContext pChainContext;
BOOL success = CertGetCertificateChain(
@@ -243,28 +248,28 @@ SECURITY_STATUS SchannelContext::validateServerCertificate() {
return S_OK;
}
//------------------------------------------------------------------------
void SchannelContext::appendNewData(const SafeByteArray& data) {
- size_t originalSize = m_receivedData.size();
- m_receivedData.resize(originalSize + data.size());
- memcpy(&m_receivedData[0] + originalSize, &data[0], data.size());
+ size_t originalSize = receivedData_.size();
+ receivedData_.resize(originalSize + data.size());
+ memcpy(&receivedData_[0] + originalSize, &data[0], data.size());
}
//------------------------------------------------------------------------
void SchannelContext::continueHandshake(const SafeByteArray& data) {
appendNewData(data);
- while (!m_receivedData.empty()) {
+ while (!receivedData_.empty()) {
SecBuffer inBuffers[2];
// Provide Schannel with the remote host's handshake data
- inBuffers[0].pvBuffer = (char*)(&m_receivedData[0]);
- inBuffers[0].cbBuffer = (unsigned long)m_receivedData.size();
+ inBuffers[0].pvBuffer = (char*)(&receivedData_[0]);
+ inBuffers[0].cbBuffer = (unsigned long)receivedData_.size();
inBuffers[0].BufferType = SECBUFFER_TOKEN;
inBuffers[1].pvBuffer = NULL;
inBuffers[1].cbBuffer = 0;
inBuffers[1].BufferType = SECBUFFER_EMPTY;
@@ -292,106 +297,106 @@ void SchannelContext::continueHandshake(const SafeByteArray& data) {
SecBufferDesc outBufferDesc = {0};
outBufferDesc.cBuffers = 2;
outBufferDesc.pBuffers = outBuffers;
outBufferDesc.ulVersion = SECBUFFER_VERSION;
SECURITY_STATUS status = InitializeSecurityContext(
- m_credHandle,
- m_ctxtHandle,
+ credHandle_,
+ contextHandle_,
NULL,
- m_ctxtFlags,
+ contextFlags_,
0,
0,
&inBufferDesc,
0,
NULL,
&outBufferDesc,
- &m_secContext,
+ &secContext_,
NULL);
if (status == SEC_E_INCOMPLETE_MESSAGE) {
// Wait for more data to arrive
break;
}
else if (status == SEC_I_CONTINUE_NEEDED) {
SecBuffer* pDataBuffer = &outBuffers[0];
SecBuffer* pExtraBuffer = &inBuffers[1];
-
+
if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) {
sendDataOnNetwork(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
}
if (pExtraBuffer->BufferType == SECBUFFER_EXTRA) {
- m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer);
+ receivedData_.erase(receivedData_.begin(), receivedData_.end() - pExtraBuffer->cbBuffer);
}
else {
- m_receivedData.clear();
+ receivedData_.clear();
}
break;
}
else if (status == SEC_E_OK) {
status = validateServerCertificate();
if (status != SEC_E_OK) {
handleCertError(status);
}
SecBuffer* pExtraBuffer = &inBuffers[1];
-
+
if (pExtraBuffer && pExtraBuffer->cbBuffer > 0) {
- m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer);
+ receivedData_.erase(receivedData_.begin(), receivedData_.end() - pExtraBuffer->cbBuffer);
}
else {
- m_receivedData.clear();
+ receivedData_.clear();
}
- m_state = Connected;
+ state_ = Connected;
determineStreamSizes();
onConnected();
- }
+ }
else {
// We failed to initialize the security context
handleCertError(status);
indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
return;
}
}
}
//------------------------------------------------------------------------
-void SchannelContext::handleCertError(SECURITY_STATUS status)
+void SchannelContext::handleCertError(SECURITY_STATUS status)
{
- if (status == SEC_E_UNTRUSTED_ROOT ||
+ if (status == SEC_E_UNTRUSTED_ROOT ||
status == CERT_E_UNTRUSTEDROOT ||
- status == CRYPT_E_ISSUER_SERIALNUMBER ||
+ status == CRYPT_E_ISSUER_SERIALNUMBER ||
status == CRYPT_E_SIGNER_NOT_FOUND ||
status == CRYPT_E_NO_TRUSTED_SIGNER) {
- m_verificationError = CertificateVerificationError::Untrusted;
+ verificationError_ = CertificateVerificationError::Untrusted;
}
- else if (status == SEC_E_CERT_EXPIRED ||
+ else if (status == SEC_E_CERT_EXPIRED ||
status == CERT_E_EXPIRED) {
- m_verificationError = CertificateVerificationError::Expired;
+ verificationError_ = CertificateVerificationError::Expired;
}
else if (status == CRYPT_E_SELF_SIGNED) {
- m_verificationError = CertificateVerificationError::SelfSigned;
+ verificationError_ = CertificateVerificationError::SelfSigned;
}
else if (status == CRYPT_E_HASH_VALUE ||
status == TRUST_E_CERT_SIGNATURE) {
- m_verificationError = CertificateVerificationError::InvalidSignature;
+ verificationError_ = CertificateVerificationError::InvalidSignature;
}
else if (status == CRYPT_E_REVOKED) {
- m_verificationError = CertificateVerificationError::Revoked;
+ verificationError_ = CertificateVerificationError::Revoked;
}
else if (status == CRYPT_E_NO_REVOCATION_CHECK ||
status == CRYPT_E_REVOCATION_OFFLINE) {
- m_verificationError = CertificateVerificationError::RevocationCheckFailed;
+ verificationError_ = CertificateVerificationError::RevocationCheckFailed;
}
else {
- m_verificationError = CertificateVerificationError::UnknownError;
+ verificationError_ = CertificateVerificationError::UnknownError;
}
}
//------------------------------------------------------------------------
void SchannelContext::sendDataOnNetwork(const void* pData, size_t dataSize) {
@@ -413,24 +418,24 @@ void SchannelContext::forwardDataToApplication(const void* pData, size_t dataSiz
}
//------------------------------------------------------------------------
void SchannelContext::handleDataFromApplication(const SafeByteArray& data) {
// Don't attempt to send data until we're fully connected
- if (m_state == Connecting) {
+ if (state_ == Connecting) {
return;
}
// Encrypt the data
encryptAndSendData(data);
}
//------------------------------------------------------------------------
void SchannelContext::handleDataFromNetwork(const SafeByteArray& data) {
- switch (m_state) {
+ switch (state_) {
case Connecting:
{
// We're still establishing the connection, so continue the handshake
continueHandshake(data);
}
break;
@@ -447,64 +452,64 @@ void SchannelContext::handleDataFromNetwork(const SafeByteArray& data) {
}
}
//------------------------------------------------------------------------
void SchannelContext::indicateError(boost::shared_ptr<TLSError> error) {
- m_state = Error;
- m_receivedData.clear();
+ state_ = Error;
+ receivedData_.clear();
onError(error);
}
//------------------------------------------------------------------------
void SchannelContext::decryptAndProcessData(const SafeByteArray& data) {
SecBuffer inBuffers[4] = {0};
appendNewData(data);
-
- while (!m_receivedData.empty()) {
+
+ while (!receivedData_.empty()) {
//
- // MSDN:
- // When using the Schannel SSP with contexts that are not connection oriented, on input,
- // the structure must contain four SecBuffer structures. Exactly one buffer must be of type
- // SECBUFFER_DATA and contain an encrypted message, which is decrypted in place. The remaining
- // buffers are used for output and must be of type SECBUFFER_EMPTY. For connection-oriented
- // contexts, a SECBUFFER_DATA type buffer must be supplied, as noted for nonconnection-oriented
- // contexts. Additionally, a second SECBUFFER_TOKEN type buffer that contains a security token
+ // MSDN:
+ // When using the Schannel SSP with contexts that are not connection oriented, on input,
+ // the structure must contain four SecBuffer structures. Exactly one buffer must be of type
+ // SECBUFFER_DATA and contain an encrypted message, which is decrypted in place. The remaining
+ // buffers are used for output and must be of type SECBUFFER_EMPTY. For connection-oriented
+ // contexts, a SECBUFFER_DATA type buffer must be supplied, as noted for nonconnection-oriented
+ // contexts. Additionally, a second SECBUFFER_TOKEN type buffer that contains a security token
// must also be supplied.
//
- inBuffers[0].pvBuffer = (char*)(&m_receivedData[0]);
- inBuffers[0].cbBuffer = (unsigned long)m_receivedData.size();
+ inBuffers[0].pvBuffer = (char*)(&receivedData_[0]);
+ inBuffers[0].cbBuffer = (unsigned long)receivedData_.size();
inBuffers[0].BufferType = SECBUFFER_DATA;
inBuffers[1].BufferType = SECBUFFER_EMPTY;
inBuffers[2].BufferType = SECBUFFER_EMPTY;
inBuffers[3].BufferType = SECBUFFER_EMPTY;
SecBufferDesc inBufferDesc = {0};
inBufferDesc.cBuffers = 4;
inBufferDesc.pBuffers = inBuffers;
inBufferDesc.ulVersion = SECBUFFER_VERSION;
- size_t inData = m_receivedData.size();
- SECURITY_STATUS status = DecryptMessage(m_ctxtHandle, &inBufferDesc, 0, NULL);
+ size_t inData = receivedData_.size();
+ SECURITY_STATUS status = DecryptMessage(contextHandle_, &inBufferDesc, 0, NULL);
if (status == SEC_E_INCOMPLETE_MESSAGE) {
// Wait for more data to arrive
break;
- }
+ }
else if (status == SEC_I_RENEGOTIATE) {
// TODO: Handle renegotiation scenarios
indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
break;
- }
+ }
else if (status == SEC_I_CONTEXT_EXPIRED) {
indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
break;
- }
+ }
else if (status != SEC_E_OK) {
indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
break;
}
SecBuffer* pDataBuffer = NULL;
@@ -521,73 +526,73 @@ void SchannelContext::decryptAndProcessData(const SafeByteArray& data) {
if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) {
forwardDataToApplication(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
}
// If there is extra data left over from the decryption operation, we call DecryptMessage() again
if (pExtraBuffer) {
- m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer);
- }
+ receivedData_.erase(receivedData_.begin(), receivedData_.end() - pExtraBuffer->cbBuffer);
+ }
else {
// We're done
- m_receivedData.erase(m_receivedData.begin(), m_receivedData.begin() + inData);
+ receivedData_.erase(receivedData_.begin(), receivedData_.begin() + inData);
}
}
}
//------------------------------------------------------------------------
void SchannelContext::encryptAndSendData(const SafeByteArray& data) {
- if (m_streamSizes.cbMaximumMessage == 0) {
+ if (streamSizes_.cbMaximumMessage == 0) {
return;
}
SecBuffer outBuffers[4] = {0};
// Calculate the largest required size of the send buffer
- size_t messageBufferSize = (data.size() > m_streamSizes.cbMaximumMessage)
- ? m_streamSizes.cbMaximumMessage
+ size_t messageBufferSize = (data.size() > streamSizes_.cbMaximumMessage)
+ ? streamSizes_.cbMaximumMessage
: data.size();
// Allocate a packet for the encrypted data
SafeByteArray sendBuffer;
- sendBuffer.resize(m_streamSizes.cbHeader + messageBufferSize + m_streamSizes.cbTrailer);
+ sendBuffer.resize(streamSizes_.cbHeader + messageBufferSize + streamSizes_.cbTrailer);
size_t bytesSent = 0;
do {
size_t bytesLeftToSend = data.size() - bytesSent;
// Calculate how much of the send buffer we'll be using for this chunk
- size_t bytesToSend = (bytesLeftToSend > m_streamSizes.cbMaximumMessage)
- ? m_streamSizes.cbMaximumMessage
+ size_t bytesToSend = (bytesLeftToSend > streamSizes_.cbMaximumMessage)
+ ? streamSizes_.cbMaximumMessage
: bytesLeftToSend;
-
+
// Copy the plain text data into the send buffer
- memcpy(&sendBuffer[0] + m_streamSizes.cbHeader, &data[0] + bytesSent, bytesToSend);
+ memcpy(&sendBuffer[0] + streamSizes_.cbHeader, &data[0] + bytesSent, bytesToSend);
outBuffers[0].pvBuffer = &sendBuffer[0];
- outBuffers[0].cbBuffer = m_streamSizes.cbHeader;
+ outBuffers[0].cbBuffer = streamSizes_.cbHeader;
outBuffers[0].BufferType = SECBUFFER_STREAM_HEADER;
- outBuffers[1].pvBuffer = &sendBuffer[0] + m_streamSizes.cbHeader;
+ outBuffers[1].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader;
outBuffers[1].cbBuffer = (unsigned long)bytesToSend;
outBuffers[1].BufferType = SECBUFFER_DATA;
- outBuffers[2].pvBuffer = &sendBuffer[0] + m_streamSizes.cbHeader + bytesToSend;
- outBuffers[2].cbBuffer = m_streamSizes.cbTrailer;
+ outBuffers[2].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader + bytesToSend;
+ outBuffers[2].cbBuffer = streamSizes_.cbTrailer;
outBuffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
outBuffers[3].pvBuffer = 0;
outBuffers[3].cbBuffer = 0;
outBuffers[3].BufferType = SECBUFFER_EMPTY;
SecBufferDesc outBufferDesc = {0};
outBufferDesc.cBuffers = 4;
outBufferDesc.pBuffers = outBuffers;
outBufferDesc.ulVersion = SECBUFFER_VERSION;
- SECURITY_STATUS status = EncryptMessage(m_ctxtHandle, 0, &outBufferDesc, 0);
+ SECURITY_STATUS status = EncryptMessage(contextHandle_, 0, &outBufferDesc, 0);
if (status != SEC_E_OK) {
indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
return;
}
sendDataOnNetwork(&sendBuffer[0], outBuffers[0].cbBuffer + outBuffers[1].cbBuffer + outBuffers[2].cbBuffer);
@@ -601,20 +606,20 @@ void SchannelContext::encryptAndSendData(const SafeByteArray& data) {
bool SchannelContext::setClientCertificate(CertificateWithKey::ref certificate) {
boost::shared_ptr<CAPICertificate> capiCertificate = boost::dynamic_pointer_cast<CAPICertificate>(certificate);
if (!capiCertificate || capiCertificate->isNull()) {
return false;
}
- userCertificate = capiCertificate;
+ userCertificate_ = capiCertificate;
// 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();
+ certStoreName_ = capiCertificate->getCertStoreName();
+ certName_ = capiCertificate->getCertName();
////At the moment this is only useful for logging:
- m_smartcard_reader = capiCertificate->getSmartCardReaderName();
+ smartCardReader_ = capiCertificate->getSmartCardReaderName();
capiCertificate->onCertificateCardRemoved.connect(boost::bind(&SchannelContext::handleCertificateCardRemoved, this));
return true;
}
@@ -627,13 +632,13 @@ void SchannelContext::handleCertificateCardRemoved() {
std::vector<Certificate::ref> SchannelContext::getPeerCertificateChain() const {
std::vector<Certificate::ref> certificateChain;
ScopedCertContext pServerCert;
ScopedCertContext pIssuerCert;
ScopedCertContext pCurrentCert;
- SECURITY_STATUS status = QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset());
+ SECURITY_STATUS status = QueryContextAttributes(contextHandle_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset());
if (status != SEC_E_OK) {
return certificateChain;
}
certificateChain.push_back(boost::make_shared<SchannelCertificate>(pServerCert));
@@ -652,28 +657,28 @@ std::vector<Certificate::ref> SchannelContext::getPeerCertificateChain() const {
return certificateChain;
}
//------------------------------------------------------------------------
CertificateVerificationError::ref SchannelContext::getPeerCertificateVerificationError() const {
- return m_verificationError ? boost::make_shared<CertificateVerificationError>(*m_verificationError) : CertificateVerificationError::ref();
+ return verificationError_ ? boost::make_shared<CertificateVerificationError>(*verificationError_) : CertificateVerificationError::ref();
}
//------------------------------------------------------------------------
ByteArray SchannelContext::getFinishMessage() const {
SecPkgContext_Bindings bindings;
- int ret = QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_UNIQUE_BINDINGS, &bindings);
+ int ret = QueryContextAttributes(contextHandle_, SECPKG_ATTR_UNIQUE_BINDINGS, &bindings);
if (ret == SEC_E_OK) {
return createByteArray(((unsigned char*) bindings.Bindings) + bindings.Bindings->dwApplicationDataOffset + 11 /* tls-unique:*/, bindings.Bindings->cbApplicationDataLength - 11);
}
return ByteArray();
}
//------------------------------------------------------------------------
void SchannelContext::setCheckCertificateRevocation(bool b) {
- checkCertificateRevocation = b;
+ checkCertificateRevocation_ = b;
}
}
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
@@ -34,13 +34,13 @@ namespace Swift
class SchannelContext : public TLSContext, boost::noncopyable
{
public:
typedef boost::shared_ptr<SchannelContext> sp_t;
public:
- SchannelContext();
+ SchannelContext(bool tls1_0Workaround);
~SchannelContext();
//
// TLSContext
//
@@ -83,26 +83,27 @@ namespace Swift
Connecting,
Connected,
Error
};
- SchannelState m_state;
- boost::optional<CertificateVerificationError> m_verificationError;
+ SchannelState state_;
+ boost::optional<CertificateVerificationError> verificationError_;
- ULONG m_secContext;
- ScopedCredHandle m_credHandle;
- ScopedCtxtHandle m_ctxtHandle;
- DWORD m_ctxtFlags;
- SecPkgContext_StreamSizes m_streamSizes;
+ ULONG secContext_;
+ ScopedCredHandle credHandle_;
+ ScopedCtxtHandle contextHandle_;
+ DWORD contextFlags_;
+ SecPkgContext_StreamSizes streamSizes_;
- std::vector<char> m_receivedData;
+ std::vector<char> receivedData_;
- HCERTSTORE m_my_cert_store;
- std::string m_cert_store_name;
- std::string m_cert_name;
+ HCERTSTORE myCertStore_;
+ std::string certStoreName_;
+ std::string certName_;
////Not needed, most likely
- std::string m_smartcard_reader; //Can be empty string for non SmartCard certificates
- boost::shared_ptr<CAPICertificate> userCertificate;
- bool checkCertificateRevocation;
+ std::string smartCardReader_; //Can be empty string for non SmartCard certificates
+ boost::shared_ptr<CAPICertificate> userCertificate_;
+ bool checkCertificateRevocation_;
+ bool tls1_0Workaround_;
};
}
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
@@ -1,26 +1,32 @@
/*
* Copyright (c) 2011 Soren Dreijer
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include "Swiften/TLS/Schannel/SchannelContextFactory.h"
#include "Swiften/TLS/Schannel/SchannelContext.h"
namespace Swift {
SchannelContextFactory::SchannelContextFactory() : checkCertificateRevocation(true) {
}
bool SchannelContextFactory::canCreate() const {
return true;
}
-TLSContext* SchannelContextFactory::createTLSContext() {
- SchannelContext* context = new SchannelContext();
+TLSContext* SchannelContextFactory::createTLSContext(const TLSOptions& tlsOptions) {
+ SchannelContext* context = new SchannelContext(tlsOptions.schannelTLS1_0Workaround);
context->setCheckCertificateRevocation(checkCertificateRevocation);
return context;
}
void SchannelContextFactory::setCheckCertificateRevocation(bool b) {
checkCertificateRevocation = b;
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
@@ -1,23 +1,29 @@
/*
* Copyright (c) 2011 Soren Dreijer
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#pragma once
-#include "Swiften/TLS/TLSContextFactory.h"
+#include <Swiften/TLS/TLSContextFactory.h>
namespace Swift {
class SchannelContextFactory : public TLSContextFactory {
public:
SchannelContextFactory();
bool canCreate() const;
- virtual TLSContext* createTLSContext();
+ virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions);
virtual void setCheckCertificateRevocation(bool b);
public:
bool checkCertificateRevocation;
};
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
@@ -4,20 +4,21 @@
* See the COPYING file for more information.
*/
#pragma once
#include <Swiften/Base/API.h>
+#include <Swiften/TLS/TLSOptions.h>
namespace Swift {
class TLSContext;
class SWIFTEN_API TLSContextFactory {
public:
virtual ~TLSContextFactory();
virtual bool canCreate() const = 0;
- virtual TLSContext* createTLSContext() = 0;
+ virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions) = 0;
virtual void setCheckCertificateRevocation(bool b) = 0;
};
}
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 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+namespace Swift {
+
+ struct TLSOptions {
+ TLSOptions() : schannelTLS1_0Workaround(false) {
+
+ }
+
+ /**
+ * A bug in the Windows SChannel TLS stack, combined with
+ * overly-restrictive server stacks means it's sometimes necessary to
+ * not use TLS>1.0. This option has no effect unless compiled on
+ * Windows against SChannel (OpenSSL users are unaffected).
+ */
+ bool schannelTLS1_0Workaround;
+
+ };
+}