From ab651834c9088e34e6e66eb105e0fb855f1572c4 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Mon, 19 Oct 2015 16:23:42 +0200 Subject: Add support for client certificate authentication in BOSH This allows to authenticate using SASL EXTERNAL over BOSH using a client TLS certificate for the HTTPS connection of the BOSH channel. The implementation also enforces the HTTPS server certificate of subsequent BOSH connections not to change. This commit also removes TLSConnection and TLSConnectionFactory as no code is using them. Test-Information: Tested against M-Link 16.3v6-0 on Debian 7.9 and Swift on OS X 10.10.5. Verified working client certificate authentication. Verified Swift not falling back to password-based authentication, in case EXTERNAL is not allowed by the server over BOSH or the client certificate is invalid. Change-Id: Ia96bcac27cac9fc9261ed847c82c6328307bfbd1 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(boost::make_shared(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(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_ = boost::shared_ptr(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 #include #include +#include +#include +#include +#include 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(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(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(data)); +} + +void BOSHConnection::handleTLSNetowrkDataWriteRequest(const SafeByteArray& data) { + SWIFT_LOG(debug) << std::endl; + connection_->write(data); +} + +void BOSHConnection::handleRawDataRead(boost::shared_ptr data) { + SWIFT_LOG(debug) << std::endl; + tlsLayer_->handleDataRead(*data.get()); +} + +void BOSHConnection::handleTLSError(boost::shared_ptr 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 BOSHConnection::getPeerCertificateChain() const { + std::vector 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 #include +#include +#include +#include #include #include #include -#include -#include -#include #include +#include 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 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 ref; + + private: + Type type; + }; class SWIFTEN_API BOSHConnection : public boost::enable_shared_from_this { public: typedef boost::shared_ptr 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 getPeerCertificateChain() const; + CertificateVerificationError::ref getPeerCertificateVerificationError() const; boost::signal onConnectFinished; boost::signal 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 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 data); + void handleTLSError(boost::shared_ptr error); + void writeData(const SafeByteArray& data); + URL boshURL_; Connector::ref connector_; XMLParserFactory* parserFactory_; boost::shared_ptr connection_; + boost::shared_ptr dummyLayer_; + boost::shared_ptr 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 #include +#include #include #include #include #include -#include 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 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 BOSHConnectionPool::getPeerCertificateChain() const { + return pinnedCertificateChain_; +} + +boost::shared_ptr 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 BOSHConnectionPool::createConnection() { Connector::ref connector = Connector::create(boshURL.getHost(), URL::getPortOrDefaultPort(boshURL), boost::optional(), 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 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 #include #include +#include #include 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 trafficFilter = boost::shared_ptr()); ~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 getPeerCertificateChain() const; + boost::shared_ptr getPeerCertificateVerificationError() const; + boost::signal onSessionTerminated; boost::signal onSessionStarted; boost::signal onXMPPDataRead; @@ -68,5 +79,10 @@ namespace Swift { bool pendingRestart; std::vector myConnectionFactories; CachingDomainNameResolver* resolver; + CertificateWithKey::ref clientCertificate; + TLSContextFactory* tlsContextFactory_; + TLSOptions tlsOptions_; + std::vector > pinnedCertificateChain_; + boost::shared_ptr 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 #include #include +#include +#include +#include namespace boost { class thread; @@ -47,6 +50,12 @@ namespace Swift { HostAddressPort getLocalAddress() const; + bool setClientCertificate(CertificateWithKey::ref cert); + + Certificate::ref getPeerCertificate() const; + std::vector getPeerCertificateChain() const; + boost::shared_ptr getPeerCertificateVerificationError() const; + private: BoostConnection(boost::shared_ptr 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 +#include +#include +#include +#include + #include #include #include -#include -#include -#include -#include -#include - #include #include #include @@ -27,8 +27,6 @@ #include #include - - using namespace Swift; typedef boost::shared_ptr PoolRef; @@ -323,10 +321,9 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture { private: PoolRef createTestling() { - BOSHConnectionPool* a = new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast(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(boshURL, resolver, connectionFactory, &parserFactory, static_cast(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(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 #include #include +#include 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(), 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(); @@ -96,7 +95,6 @@ class CertificateErrorTest : public CppUnit::TestFixture { } void connectToServer(boost::shared_ptr 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 connection = boost::dynamic_pointer_cast(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 BOSHSessionStream::getPeerCertificateChain() const { - return std::vector(); + return connectionPool->getPeerCertificateChain(); } boost::shared_ptr BOSHSessionStream::getPeerCertificateVerificationError() const { - return boost::shared_ptr(); + 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 +#include +#include + +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(); -- cgit v0.10.2-6-g49f6