diff options
Diffstat (limited to 'Swiften')
-rw-r--r-- | Swiften/Client/CoreClient.cpp | 39 | ||||
-rw-r--r-- | Swiften/Network/BOSHConnection.cpp | 104 | ||||
-rw-r--r-- | Swiften/Network/BOSHConnection.h | 58 | ||||
-rw-r--r-- | Swiften/Network/BOSHConnectionPool.cpp | 58 | ||||
-rw-r--r-- | Swiften/Network/BOSHConnectionPool.h | 18 | ||||
-rw-r--r-- | Swiften/Network/BoostConnection.h | 9 | ||||
-rw-r--r-- | Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp | 23 | ||||
-rw-r--r-- | Swiften/Network/UnitTest/BOSHConnectionTest.cpp | 5 | ||||
-rw-r--r-- | Swiften/QA/TLSTest/CertificateErrorTest.cpp | 3 | ||||
-rw-r--r-- | Swiften/Session/BOSHSessionStream.cpp | 13 | ||||
-rw-r--r-- | Swiften/Session/BOSHSessionStream.h | 1 | ||||
-rw-r--r-- | Swiften/StreamStack/DummyStreamLayer.h | 30 | ||||
-rw-r--r-- | Swiften/StreamStack/LowLayer.h | 3 |
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(); |