summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swiften/Client/CoreClient.cpp39
-rw-r--r--Swiften/Network/BOSHConnection.cpp104
-rw-r--r--Swiften/Network/BOSHConnection.h58
-rw-r--r--Swiften/Network/BOSHConnectionPool.cpp58
-rw-r--r--Swiften/Network/BOSHConnectionPool.h18
-rw-r--r--Swiften/Network/BoostConnection.h9
-rw-r--r--Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp23
-rw-r--r--Swiften/Network/UnitTest/BOSHConnectionTest.cpp5
-rw-r--r--Swiften/QA/TLSTest/CertificateErrorTest.cpp3
-rw-r--r--Swiften/Session/BOSHSessionStream.cpp13
-rw-r--r--Swiften/Session/BOSHSessionStream.h1
-rw-r--r--Swiften/StreamStack/DummyStreamLayer.h30
-rw-r--r--Swiften/StreamStack/LowLayer.h3
13 files changed, 286 insertions, 78 deletions
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index af64577..6fc491c 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -124,25 +124,30 @@ void CoreClient::connect(const ClientOptions& o) {
/* Autodiscovery of which proxy works is largely ok with a TCP session, because this is a one-off. With BOSH
* it would be quite painful given that potentially every stanza could be sent on a new connection.
*/
- //sessionStream_ = boost::make_shared<BOSHSessionStream>(boost::make_shared<BOSHConnectionFactory>(options.boshURL, networkFactories->getConnectionFactory(), networkFactories->getXMLParserFactory(), networkFactories->getTLSContextFactory()), getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), networkFactories->getEventLoop(), host, options.boshHTTPConnectProxyURL, options.boshHTTPConnectProxyAuthID, options.boshHTTPConnectProxyAuthPassword);
- sessionStream_ = boost::shared_ptr<BOSHSessionStream>(new BOSHSessionStream(
- options.boshURL,
- getPayloadParserFactories(),
- getPayloadSerializers(),
- networkFactories->getConnectionFactory(),
- networkFactories->getTLSContextFactory(),
- networkFactories->getTimerFactory(),
- networkFactories->getXMLParserFactory(),
- networkFactories->getEventLoop(),
- networkFactories->getDomainNameResolver(),
- host,
- options.boshHTTPConnectProxyURL,
- options.boshHTTPConnectProxyAuthID,
- options.boshHTTPConnectProxyAuthPassword,
- options.tlsOptions,
- options.httpTrafficFilter));
+ boost::shared_ptr<BOSHSessionStream> boshSessionStream_ = boost::shared_ptr<BOSHSessionStream>(new BOSHSessionStream(
+ options.boshURL,
+ getPayloadParserFactories(),
+ getPayloadSerializers(),
+ networkFactories->getConnectionFactory(),
+ networkFactories->getTLSContextFactory(),
+ networkFactories->getTimerFactory(),
+ networkFactories->getXMLParserFactory(),
+ networkFactories->getEventLoop(),
+ networkFactories->getDomainNameResolver(),
+ host,
+ options.boshHTTPConnectProxyURL,
+ options.boshHTTPConnectProxyAuthID,
+ options.boshHTTPConnectProxyAuthPassword,
+ options.tlsOptions,
+ options.httpTrafficFilter));
+ sessionStream_ = boshSessionStream_;
sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1));
sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1));
+ if (certificate_ && !certificate_->isNull()) {
+ SWIFT_LOG(debug) << "set certificate" << std::endl;
+ sessionStream_->setTLSCertificate(certificate_);
+ }
+ boshSessionStream_->open();
bindSessionToStream();
}
diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp
index 298b015..9a836cb 100644
--- a/Swiften/Network/BOSHConnection.cpp
+++ b/Swiften/Network/BOSHConnection.cpp
@@ -24,10 +24,14 @@
#include <Swiften/Base/String.h>
#include <Swiften/Network/HostAddressPort.h>
#include <Swiften/Parser/BOSHBodyExtractor.h>
+#include <Swiften/StreamStack/DummyStreamLayer.h>
+#include <Swiften/StreamStack/TLSLayer.h>
+#include <Swiften/TLS/TLSContext.h>
+#include <Swiften/TLS/TLSOptions.h>
namespace Swift {
-BOSHConnection::BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory)
+BOSHConnection::BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory, TLSContextFactory* tlsContextFactory, const TLSOptions& tlsOptions)
: boshURL_(boshURL),
connector_(connector),
parserFactory_(parserFactory),
@@ -37,6 +41,12 @@ BOSHConnection::BOSHConnection(const URL& boshURL, Connector::ref connector, XML
pending_(false),
connectionReady_(false)
{
+ if (boshURL_.getScheme() == "https") {
+ tlsLayer_ = boost::make_shared<TLSLayer>(tlsContextFactory, tlsOptions);
+ // The following dummyLayer_ is needed as the TLSLayer will pass the decrypted data to its parent layer.
+ // The dummyLayer_ will serve as the parent layer.
+ dummyLayer_ = boost::make_shared<DummyStreamLayer>(tlsLayer_.get());
+ }
}
BOSHConnection::~BOSHConnection() {
@@ -61,6 +71,39 @@ void BOSHConnection::cancelConnector() {
}
}
+void BOSHConnection::handleTLSConnected() {
+ SWIFT_LOG(debug) << std::endl;
+ onConnectFinished(false);
+}
+
+void BOSHConnection::handleTLSApplicationDataRead(const SafeByteArray& data) {
+ SWIFT_LOG(debug) << std::endl;
+ handleDataRead(boost::make_shared<SafeByteArray>(data));
+}
+
+void BOSHConnection::handleTLSNetowrkDataWriteRequest(const SafeByteArray& data) {
+ SWIFT_LOG(debug) << std::endl;
+ connection_->write(data);
+}
+
+void BOSHConnection::handleRawDataRead(boost::shared_ptr<SafeByteArray> data) {
+ SWIFT_LOG(debug) << std::endl;
+ tlsLayer_->handleDataRead(*data.get());
+}
+
+void BOSHConnection::handleTLSError(boost::shared_ptr<TLSError> error) {
+
+}
+
+void BOSHConnection::writeData(const SafeByteArray& data) {
+ if (tlsLayer_) {
+ tlsLayer_->writeData(data);
+ }
+ else {
+ connection_->write(data);
+ }
+}
+
void BOSHConnection::disconnect() {
if (connection_) {
connection_->disconnect();
@@ -76,6 +119,40 @@ void BOSHConnection::restartStream() {
write(createSafeByteArray(""), true, false);
}
+bool BOSHConnection::setClientCertificate(CertificateWithKey::ref cert) {
+ if (tlsLayer_) {
+ SWIFT_LOG(debug) << "set client certificate" << std::endl;
+ return tlsLayer_->setClientCertificate(cert);
+ }
+ else {
+ return false;
+ }
+}
+
+Certificate::ref BOSHConnection::getPeerCertificate() const {
+ Certificate::ref peerCertificate;
+ if (tlsLayer_) {
+ peerCertificate = tlsLayer_->getPeerCertificate();
+ }
+ return peerCertificate;
+}
+
+std::vector<Certificate::ref> BOSHConnection::getPeerCertificateChain() const {
+ std::vector<Certificate::ref> peerCertificateChain;
+ if (tlsLayer_) {
+ peerCertificateChain = tlsLayer_->getPeerCertificateChain();
+ }
+ return peerCertificateChain;
+}
+
+CertificateVerificationError::ref BOSHConnection::getPeerCertificateVerificationError() const {
+ CertificateVerificationError::ref verificationError;
+ if (tlsLayer_) {
+ verificationError = tlsLayer_->getPeerCertificateVerificationError();
+ }
+ return verificationError;
+}
+
void BOSHConnection::terminateStream() {
write(createSafeByteArray(""), false, true);
}
@@ -129,7 +206,7 @@ void BOSHConnection::write(const SafeByteArray& data, bool streamRestart, bool t
SafeByteArray safeHeader = createHTTPRequest(data, streamRestart, terminate, rid_, sid_, boshURL_).first;
onBOSHDataWritten(safeHeader);
- connection_->write(safeHeader);
+ writeData(safeHeader);
pending_ = true;
SWIFT_LOG(debug) << "write data: " << safeByteArrayToString(safeHeader) << std::endl;
@@ -140,10 +217,25 @@ void BOSHConnection::handleConnectFinished(Connection::ref connection) {
connectionReady_ = !!connection;
if (connectionReady_) {
connection_ = connection;
- connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
- connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+ if (tlsLayer_) {
+ connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleRawDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+
+ tlsLayer_->getContext()->onDataForNetwork.connect(boost::bind(&BOSHConnection::handleTLSNetowrkDataWriteRequest, shared_from_this(), _1));
+ tlsLayer_->getContext()->onDataForApplication.connect(boost::bind(&BOSHConnection::handleTLSApplicationDataRead, shared_from_this(), _1));
+ tlsLayer_->onConnected.connect(boost::bind(&BOSHConnection::handleTLSConnected, shared_from_this()));
+ tlsLayer_->onError.connect(boost::bind(&BOSHConnection::handleTLSError, shared_from_this(), _1));
+ tlsLayer_->connect();
+ }
+ else {
+ connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
+ }
+ }
+
+ if (!connectionReady_ || !tlsLayer_) {
+ onConnectFinished(!connectionReady_);
}
- onConnectFinished(!connectionReady_);
}
void BOSHConnection::startStream(const std::string& to, unsigned long long rid) {
@@ -180,7 +272,7 @@ void BOSHConnection::startStream(const std::string& to, unsigned long long rid)
waitingForStartResponse_ = true;
SafeByteArray safeHeader = createSafeByteArray(header.str());
onBOSHDataWritten(safeHeader);
- connection_->write(safeHeader);
+ writeData(safeHeader);
SWIFT_LOG(debug) << "write stream header: " << safeByteArrayToString(safeHeader) << std::endl;
}
diff --git a/Swiften/Network/BOSHConnection.h b/Swiften/Network/BOSHConnection.h
index 65d179a..da43e71 100644
--- a/Swiften/Network/BOSHConnection.h
+++ b/Swiften/Network/BOSHConnection.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2011 Isode Limited.
+ * Copyright (c) 2011-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -16,13 +16,14 @@
#include <boost/enable_shared_from_this.hpp>
#include <Swiften/Base/API.h>
+#include <Swiften/Base/Error.h>
+#include <Swiften/Base/String.h>
+#include <Swiften/Base/URL.h>
#include <Swiften/Network/Connection.h>
#include <Swiften/Network/Connector.h>
#include <Swiften/Network/HostAddressPort.h>
-#include <Swiften/Base/String.h>
-#include <Swiften/Base/URL.h>
-#include <Swiften/Base/Error.h>
#include <Swiften/Session/SessionStream.h>
+#include <Swiften/TLS/TLSError.h>
namespace boost {
class thread;
@@ -36,27 +37,31 @@ class BOSHConnectionTest;
namespace Swift {
class XMLParserFactory;
class TLSContextFactory;
+ class TLSLayer;
+ struct TLSOptions;
+ class HighLayer;
- class SWIFTEN_API BOSHError : public SessionStream::SessionStreamError {
- public:
- enum Type {BadRequest, HostGone, HostUnknown, ImproperAddressing,
- InternalServerError, ItemNotFound, OtherRequest, PolicyViolation,
- RemoteConnectionFailed, RemoteStreamError, SeeOtherURI, SystemShutdown, UndefinedCondition,
- NoError};
- BOSHError(Type type) : SessionStream::SessionStreamError(SessionStream::SessionStreamError::ConnectionReadError), type(type) {}
- Type getType() {return type;}
- typedef boost::shared_ptr<BOSHError> ref;
- private:
- Type type;
-
- };
+ class SWIFTEN_API BOSHError : public SessionStream::SessionStreamError {
+ public:
+ enum Type {
+ BadRequest, HostGone, HostUnknown, ImproperAddressing,
+ InternalServerError, ItemNotFound, OtherRequest, PolicyViolation,
+ RemoteConnectionFailed, RemoteStreamError, SeeOtherURI, SystemShutdown, UndefinedCondition,
+ NoError};
+ BOSHError(Type type) : SessionStream::SessionStreamError(SessionStream::SessionStreamError::ConnectionReadError), type(type) {}
+ Type getType() {return type;}
+ typedef boost::shared_ptr<BOSHError> ref;
+
+ private:
+ Type type;
+ };
class SWIFTEN_API BOSHConnection : public boost::enable_shared_from_this<BOSHConnection> {
public:
typedef boost::shared_ptr<BOSHConnection> ref;
- static ref create(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory) {
- return ref(new BOSHConnection(boshURL, connector, parserFactory));
+ static ref create(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory, TLSContextFactory* tlsContextFactory, const TLSOptions& tlsOptions) {
+ return ref(new BOSHConnection(boshURL, connector, parserFactory, tlsContextFactory, tlsOptions));
}
virtual ~BOSHConnection();
virtual void connect();
@@ -71,6 +76,10 @@ namespace Swift {
bool isReadyToSend();
void restartStream();
+ bool setClientCertificate(CertificateWithKey::ref cert);
+ Certificate::ref getPeerCertificate() const;
+ std::vector<Certificate::ref> getPeerCertificateChain() const;
+ CertificateVerificationError::ref getPeerCertificateVerificationError() const;
boost::signal<void (bool /* error */)> onConnectFinished;
boost::signal<void (bool /* error */)> onDisconnected;
@@ -84,7 +93,7 @@ namespace Swift {
private:
friend class ::BOSHConnectionTest;
- BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory);
+ BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory, TLSContextFactory* tlsContextFactory, const TLSOptions& tlsOptions);
static std::pair<SafeByteArray, size_t> createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, unsigned long long rid, const std::string& sid, const URL& boshURL);
void handleConnectFinished(Connection::ref);
@@ -94,10 +103,19 @@ namespace Swift {
BOSHError::Type parseTerminationCondition(const std::string& text);
void cancelConnector();
+ void handleTLSConnected();
+ void handleTLSApplicationDataRead(const SafeByteArray& data);
+ void handleTLSNetowrkDataWriteRequest(const SafeByteArray& data);
+ void handleRawDataRead(boost::shared_ptr<SafeByteArray> data);
+ void handleTLSError(boost::shared_ptr<TLSError> error);
+ void writeData(const SafeByteArray& data);
+
URL boshURL_;
Connector::ref connector_;
XMLParserFactory* parserFactory_;
boost::shared_ptr<Connection> connection_;
+ boost::shared_ptr<HighLayer> dummyLayer_;
+ boost::shared_ptr<TLSLayer> tlsLayer_;
std::string sid_;
bool waitingForStartResponse_;
unsigned long long rid_;
diff --git a/Swiften/Network/BOSHConnectionPool.cpp b/Swiften/Network/BOSHConnectionPool.cpp
index c23e2de..57c1bcc 100644
--- a/Swiften/Network/BOSHConnectionPool.cpp
+++ b/Swiften/Network/BOSHConnectionPool.cpp
@@ -10,11 +10,11 @@
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
+#include <Swiften/Base/Log.h>
#include <Swiften/Base/SafeString.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Network/CachingDomainNameResolver.h>
#include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h>
-#include <Swiften/Network/TLSConnectionFactory.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, const TLSOptions& tlsOptions, boost::shared_ptr<HTTPTrafficFilter> trafficFilter) :
@@ -27,21 +27,14 @@ BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* r
to(to),
requestLimit(2),
restartCount(0),
- pendingRestart(false) {
+ pendingRestart(false),
+ tlsContextFactory_(tlsFactory),
+ tlsOptions_(tlsOptions) {
if (!boshHTTPConnectProxyURL.isEmpty()) {
- if (boshHTTPConnectProxyURL.getScheme() == "https") {
- connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory, tlsOptions);
- myConnectionFactories.push_back(connectionFactory);
- }
connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, boshHTTPConnectProxyURL.getHost(), URL::getPortOrDefaultPort(boshHTTPConnectProxyURL), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword, trafficFilter);
}
- if (boshURL.getScheme() == "https") {
- connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory, tlsOptions);
- myConnectionFactories.push_back(connectionFactory);
- }
resolver = new CachingDomainNameResolver(realResolver, eventLoop);
- createConnection();
}
BOSHConnectionPool::~BOSHConnectionPool() {
@@ -83,11 +76,39 @@ void BOSHConnectionPool::restartStream() {
}
}
+void BOSHConnectionPool::setTLSCertificate(CertificateWithKey::ref certWithKey) {
+ clientCertificate = certWithKey;
+}
+
+bool BOSHConnectionPool::isTLSEncrypted() const {
+ return !pinnedCertificateChain_.empty();
+}
+
+Certificate::ref BOSHConnectionPool::getPeerCertificate() const {
+ Certificate::ref peerCertificate;
+ if (!pinnedCertificateChain_.empty()) {
+ peerCertificate = pinnedCertificateChain_[0];
+ }
+ return peerCertificate;
+}
+
+std::vector<Certificate::ref> BOSHConnectionPool::getPeerCertificateChain() const {
+ return pinnedCertificateChain_;
+}
+
+boost::shared_ptr<CertificateVerificationError> BOSHConnectionPool::getPeerCertificateVerificationError() const {
+ return lastVerificationError_;
+}
+
void BOSHConnectionPool::writeFooter() {
pendingTerminate = true;
tryToSendQueuedData();
}
+void BOSHConnectionPool::open() {
+ createConnection();
+}
+
void BOSHConnectionPool::close() {
if (!sid.empty()) {
writeFooter();
@@ -117,6 +138,13 @@ void BOSHConnectionPool::handleConnectFinished(bool error, BOSHConnection::ref c
*/
}
else {
+ if (connection->getPeerCertificate() && pinnedCertificateChain_.empty()) {
+ pinnedCertificateChain_ = connection->getPeerCertificateChain();
+ }
+ if (!pinnedCertificateChain_.empty()) {
+ lastVerificationError_ = connection->getPeerCertificateVerificationError();
+ }
+
if (sid.empty()) {
connection->startStream(to, rid);
}
@@ -226,7 +254,7 @@ void BOSHConnectionPool::handleConnectionDisconnected(bool/* error*/, BOSHConnec
boost::shared_ptr<BOSHConnection> BOSHConnectionPool::createConnection() {
Connector::ref connector = Connector::create(boshURL.getHost(), URL::getPortOrDefaultPort(boshURL), boost::optional<std::string>(), resolver, connectionFactory, timerFactory);
- BOSHConnection::ref connection = BOSHConnection::create(boshURL, connector, xmlParserFactory);
+ BOSHConnection::ref connection = BOSHConnection::create(boshURL, connector, xmlParserFactory, tlsContextFactory_, tlsOptions_);
connection->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPool::handleDataRead, this, _1));
connection->onSessionStarted.connect(boost::bind(&BOSHConnectionPool::handleSessionStarted, this, _1, _2));
connection->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPool::handleBOSHDataRead, this, _1));
@@ -235,6 +263,12 @@ boost::shared_ptr<BOSHConnection> BOSHConnectionPool::createConnection() {
connection->onConnectFinished.connect(boost::bind(&BOSHConnectionPool::handleConnectFinished, this, _1, connection));
connection->onSessionTerminated.connect(boost::bind(&BOSHConnectionPool::handleSessionTerminated, this, _1));
connection->onHTTPError.connect(boost::bind(&BOSHConnectionPool::handleHTTPError, this, _1));
+
+ if (boshURL.getScheme() == "https") {
+ bool success = connection->setClientCertificate(clientCertificate);
+ SWIFT_LOG(debug) << "setClientCertificate, success: " << success << std::endl;
+ }
+
connection->connect();
connections.push_back(connection);
return connection;
diff --git a/Swiften/Network/BOSHConnectionPool.h b/Swiften/Network/BOSHConnectionPool.h
index eaef56c..df116ff 100644
--- a/Swiften/Network/BOSHConnectionPool.h
+++ b/Swiften/Network/BOSHConnectionPool.h
@@ -12,6 +12,7 @@
#include <Swiften/Base/API.h>
#include <Swiften/Base/SafeString.h>
#include <Swiften/Network/BOSHConnection.h>
+#include <Swiften/TLS/CertificateWithKey.h>
#include <Swiften/TLS/TLSOptions.h>
namespace Swift {
@@ -19,17 +20,27 @@ namespace Swift {
class EventLoop;
class HTTPConnectProxiedConnectionFactory;
class HTTPTrafficFilter;
- class TLSConnectionFactory;
+ class TLSContextFactory;
+ 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, const TLSOptions& tlsOptions, boost::shared_ptr<HTTPTrafficFilter> trafficFilter = boost::shared_ptr<HTTPTrafficFilter>());
~BOSHConnectionPool();
+
+ void open();
void write(const SafeByteArray& data);
void writeFooter();
void close();
void restartStream();
+ void setTLSCertificate(CertificateWithKey::ref certWithKey);
+ bool isTLSEncrypted() const;
+ Certificate::ref getPeerCertificate() const;
+ std::vector<Certificate::ref> getPeerCertificateChain() const;
+ boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const;
+
boost::signal<void (BOSHError::ref)> onSessionTerminated;
boost::signal<void ()> onSessionStarted;
boost::signal<void (const SafeByteArray&)> onXMPPDataRead;
@@ -68,5 +79,10 @@ namespace Swift {
bool pendingRestart;
std::vector<ConnectionFactory*> myConnectionFactories;
CachingDomainNameResolver* resolver;
+ CertificateWithKey::ref clientCertificate;
+ TLSContextFactory* tlsContextFactory_;
+ TLSOptions tlsOptions_;
+ std::vector<boost::shared_ptr<Certificate> > pinnedCertificateChain_;
+ boost::shared_ptr<CertificateVerificationError> lastVerificationError_;
};
}
diff --git a/Swiften/Network/BoostConnection.h b/Swiften/Network/BoostConnection.h
index 83a8f01..8e89263 100644
--- a/Swiften/Network/BoostConnection.h
+++ b/Swiften/Network/BoostConnection.h
@@ -15,6 +15,9 @@
#include <Swiften/Base/SafeByteArray.h>
#include <Swiften/EventLoop/EventOwner.h>
#include <Swiften/Network/Connection.h>
+#include <Swiften/TLS/Certificate.h>
+#include <Swiften/TLS/CertificateVerificationError.h>
+#include <Swiften/TLS/CertificateWithKey.h>
namespace boost {
class thread;
@@ -47,6 +50,12 @@ namespace Swift {
HostAddressPort getLocalAddress() const;
+ bool setClientCertificate(CertificateWithKey::ref cert);
+
+ Certificate::ref getPeerCertificate() const;
+ std::vector<Certificate::ref> getPeerCertificateChain() const;
+ boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const;
+
private:
BoostConnection(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop);
diff --git a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
index e687517..83ad548 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
@@ -1,20 +1,20 @@
/*
- * Copyright (c) 2011 Isode Limited.
+ * Copyright (c) 2011-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
+#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/optional.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
#include <QA/Checker/IO.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
-#include <boost/optional.hpp>
-#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/EventLoop/DummyEventLoop.h>
#include <Swiften/Network/BOSHConnection.h>
@@ -27,8 +27,6 @@
#include <Swiften/Parser/PlatformXMLParserFactory.h>
#include <Swiften/TLS/TLSOptions.h>
-
-
using namespace Swift;
typedef boost::shared_ptr<BOSHConnectionPool> PoolRef;
@@ -323,10 +321,9 @@ 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(""), 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(""));
+ // make_shared is limited to 9 arguments; instead new is used here.
+ PoolRef pool = PoolRef(new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""), TLSOptions()));
+ pool->open();
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/Network/UnitTest/BOSHConnectionTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
index c8bf1f0..349c282 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
@@ -24,6 +24,7 @@
#include <Swiften/Network/HostAddressPort.h>
#include <Swiften/Network/StaticDomainNameResolver.h>
#include <Swiften/Parser/PlatformXMLParserFactory.h>
+#include <Swiften/TLS/TLSOptions.h>
using namespace Swift;
@@ -47,6 +48,7 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
connectionFactory = new MockConnectionFactory(eventLoop);
resolver = new StaticDomainNameResolver(eventLoop);
timerFactory = new DummyTimerFactory();
+ tlsContextFactory = NULL;
connectFinished = false;
disconnected = false;
disconnectedError = false;
@@ -193,7 +195,7 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
BOSHConnection::ref createTestling() {
resolver->addAddress("wonderland.lit", HostAddress("127.0.0.1"));
Connector::ref connector = Connector::create("wonderland.lit", 5280, boost::optional<std::string>(), resolver, connectionFactory, timerFactory);
- BOSHConnection::ref c = BOSHConnection::create(URL("http", "wonderland.lit", 5280, "/http-bind"), connector, &parserFactory);
+ BOSHConnection::ref c = BOSHConnection::create(URL("http", "wonderland.lit", 5280, "/http-bind"), connector, &parserFactory, tlsContextFactory, TLSOptions());
c->onConnectFinished.connect(boost::bind(&BOSHConnectionTest::handleConnectFinished, this, _1));
c->onDisconnected.connect(boost::bind(&BOSHConnectionTest::handleDisconnected, this, _1));
c->onXMPPDataRead.connect(boost::bind(&BOSHConnectionTest::handleDataRead, this, _1));
@@ -294,6 +296,7 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
PlatformXMLParserFactory parserFactory;
StaticDomainNameResolver* resolver;
TimerFactory* timerFactory;
+ TLSContextFactory* tlsContextFactory;
std::string sid;
};
diff --git a/Swiften/QA/TLSTest/CertificateErrorTest.cpp b/Swiften/QA/TLSTest/CertificateErrorTest.cpp
index d7c2c55..e69af0b 100644
--- a/Swiften/QA/TLSTest/CertificateErrorTest.cpp
+++ b/Swiften/QA/TLSTest/CertificateErrorTest.cpp
@@ -48,7 +48,6 @@ class CertificateErrorTest : public CppUnit::TestFixture {
public:
void setUp() {
- SWIFT_LOG(debug) << std::endl << std::endl;
eventLoop_ = new DummyEventLoop();
boostIOServiceThread_ = new BoostIOServiceThread();
boostIOService_ = boost::make_shared<boost::asio::io_service>();
@@ -96,7 +95,6 @@ class CertificateErrorTest : public CppUnit::TestFixture {
}
void connectToServer(boost::shared_ptr<TLSConnection> connection, const std::string& hostname, int port) {
- Log::setLogLevel(Log::debug);
connection->onConnectFinished.connect(boost::bind(&CertificateErrorTest::handleConnectFinished, this, _1));
HostAddress address = resolveName(hostname);
@@ -141,7 +139,6 @@ class CertificateErrorTest : public CppUnit::TestFixture {
}
void testTLS_O_MaticCertificateFromUnknownCA() {
- Log::setLogLevel(Log::debug);
boost::shared_ptr<TLSConnection> connection = boost::dynamic_pointer_cast<TLSConnection>(tlsConnectionFactory_->createConnection());
TLSContext* context = connection->getTLSContext();
diff --git a/Swiften/Session/BOSHSessionStream.cpp b/Swiften/Session/BOSHSessionStream.cpp
index 99af71d..7fb8b31 100644
--- a/Swiften/Session/BOSHSessionStream.cpp
+++ b/Swiften/Session/BOSHSessionStream.cpp
@@ -83,6 +83,11 @@ BOSHSessionStream::~BOSHSessionStream() {
xmppLayer = NULL;
}
+void BOSHSessionStream::open() {
+ connectionPool->setTLSCertificate(getTLSCertificate());
+ connectionPool->open();
+}
+
void BOSHSessionStream::handlePoolXMPPDataRead(const SafeByteArray& data) {
xmppLayer->handleDataRead(data);
}
@@ -118,19 +123,19 @@ void BOSHSessionStream::addTLSEncryption() {
}
bool BOSHSessionStream::isTLSEncrypted() {
- return false;
+ return connectionPool->isTLSEncrypted();
}
Certificate::ref BOSHSessionStream::getPeerCertificate() const {
- return Certificate::ref();
+ return connectionPool->getPeerCertificate();
}
std::vector<Certificate::ref> BOSHSessionStream::getPeerCertificateChain() const {
- return std::vector<Certificate::ref>();
+ return connectionPool->getPeerCertificateChain();
}
boost::shared_ptr<CertificateVerificationError> BOSHSessionStream::getPeerCertificateVerificationError() const {
- return boost::shared_ptr<CertificateVerificationError>();
+ return connectionPool->getPeerCertificateVerificationError();
}
ByteArray BOSHSessionStream::getTLSFinishMessage() const {
diff --git a/Swiften/Session/BOSHSessionStream.h b/Swiften/Session/BOSHSessionStream.h
index 191a6f4..66e41ea 100644
--- a/Swiften/Session/BOSHSessionStream.h
+++ b/Swiften/Session/BOSHSessionStream.h
@@ -51,6 +51,7 @@ namespace Swift {
);
virtual ~BOSHSessionStream();
+ void open();
virtual void close();
virtual bool isOpen();
diff --git a/Swiften/StreamStack/DummyStreamLayer.h b/Swiften/StreamStack/DummyStreamLayer.h
new file mode 100644
index 0000000..b06c8aa
--- /dev/null
+++ b/Swiften/StreamStack/DummyStreamLayer.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <Swiften/StreamStack/HighLayer.h>
+#include <Swiften/StreamStack/LowLayer.h>
+
+namespace Swift {
+ /**
+ * The \ref DummyStreamLayer can be used to use a \ref LowLayer on its own, without a functioning parent layer.
+ * The \ref DummyStreamLayer will serve as the parent layer to the \ref LowLayer and is called when the \ref LowLayer
+ * wants to write data to its parent layer.
+ */
+ class SWIFTEN_API DummyStreamLayer : public HighLayer {
+ public:
+ DummyStreamLayer(LowLayer* lowLayer) {
+ setChildLayer(lowLayer);
+ lowLayer->setParentLayer(this);
+ }
+
+ virtual void handleDataRead(const SafeByteArray& /* data */) {
+
+ }
+ };
+}
diff --git a/Swiften/StreamStack/LowLayer.h b/Swiften/StreamStack/LowLayer.h
index 7d7e0b5..b1bddec 100644
--- a/Swiften/StreamStack/LowLayer.h
+++ b/Swiften/StreamStack/LowLayer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -14,6 +14,7 @@ namespace Swift {
class SWIFTEN_API LowLayer {
friend class StreamStack;
+ friend class DummyStreamLayer;
public:
LowLayer();