diff options
author | Remko Tronçon <git@el-tramo.be> | 2010-11-07 14:58:23 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2010-11-07 18:04:57 (GMT) |
commit | e2f2e48f6e01739ccaa763ff7f037306131d4e61 (patch) | |
tree | 92fefe8ff9255356d849d1eadcad45666bde52e5 /Swiften/Client | |
parent | 832d109bfabc16ef2834790743c1d235b254d781 (diff) | |
download | swift-contrib-e2f2e48f6e01739ccaa763ff7f037306131d4e61.zip swift-contrib-e2f2e48f6e01739ccaa763ff7f037306131d4e61.tar.bz2 |
Added security error handling to Swiften.
Diffstat (limited to 'Swiften/Client')
-rw-r--r-- | Swiften/Client/ClientSession.cpp | 19 | ||||
-rw-r--r-- | Swiften/Client/ClientSession.h | 5 | ||||
-rw-r--r-- | Swiften/Client/CoreClient.cpp | 17 | ||||
-rw-r--r-- | Swiften/Client/CoreClient.h | 32 | ||||
-rw-r--r-- | Swiften/Client/UnitTest/ClientSessionTest.cpp | 8 |
5 files changed, 80 insertions, 1 deletions
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp index 4c2be95..7170a20 100644 --- a/Swiften/Client/ClientSession.cpp +++ b/Swiften/Client/ClientSession.cpp @@ -11,6 +11,7 @@ #include <boost/uuid/uuid_io.hpp> #include <boost/uuid/uuid_generators.hpp> +#include "Swiften/TLS/SecurityError.h" #include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/Elements/StreamFeatures.h" #include "Swiften/Elements/StartTLSRequest.h" @@ -322,8 +323,26 @@ void ClientSession::sendCredentials(const String& password) { stream->writeElement(boost::shared_ptr<AuthRequest>(new AuthRequest(authenticator->getName(), authenticator->getResponse()))); } +void ClientSession::continueAfterSecurityError() { + checkState(WaitingForContinueAfterSecurityError); + continueAfterTLSEncrypted(); +} + void ClientSession::handleTLSEncrypted() { checkState(Encrypting); + + Certificate::ref certificate = stream->getPeerCertificate(); + boost::optional<CertificateVerificationError> verificationError = stream->getPeerCertificateVerificationError(); + if (verificationError) { + state = WaitingForContinueAfterSecurityError; + onSecurityError(SecurityError(*verificationError)); + } + else { + continueAfterTLSEncrypted(); + } +} + +void ClientSession::continueAfterTLSEncrypted() { state = WaitingForStreamStart; stream->resetXMPPParser(); sendStreamHeader(); diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h index 83744e0..b14a6ec 100644 --- a/Swiften/Client/ClientSession.h +++ b/Swiften/Client/ClientSession.h @@ -20,6 +20,7 @@ namespace Swift { class ClientAuthenticator; + class SecurityError; class ClientSession : public boost::enable_shared_from_this<ClientSession> { public: @@ -30,6 +31,7 @@ namespace Swift { Compressing, WaitingForEncrypt, Encrypting, + WaitingForContinueAfterSecurityError, WaitingForCredentials, Authenticating, EnablingSessionManagement, @@ -81,9 +83,11 @@ namespace Swift { void sendCredentials(const String& password); void sendStanza(boost::shared_ptr<Stanza>); + void continueAfterSecurityError(); public: boost::signal<void ()> onNeedCredentials; + boost::signal<void (const SecurityError&)> onSecurityError; boost::signal<void ()> onInitialized; boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; @@ -115,6 +119,7 @@ namespace Swift { void requestAck(); void handleStanzaAcked(boost::shared_ptr<Stanza> stanza); void ack(unsigned int handledStanzasCount); + void continueAfterTLSEncrypted(); private: JID localJID; diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp index 214e6b1..4202483 100644 --- a/Swiften/Client/CoreClient.cpp +++ b/Swiften/Client/CoreClient.cpp @@ -23,7 +23,7 @@ namespace Swift { -CoreClient::CoreClient(EventLoop* eventLoop, const JID& jid, const String& password) : resolver_(eventLoop), jid_(jid), password_(password), eventLoop(eventLoop), disconnectRequested_(false) { +CoreClient::CoreClient(EventLoop* eventLoop, const JID& jid, const String& password) : resolver_(eventLoop), jid_(jid), password_(password), eventLoop(eventLoop), disconnectRequested_(false), ignoreSecurityErrors(true) { stanzaChannel_ = new ClientSessionStanzaChannel(); stanzaChannel_->onMessageReceived.connect(boost::ref(onMessageReceived)); stanzaChannel_->onPresenceReceived.connect(boost::ref(onPresenceReceived)); @@ -93,6 +93,7 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio stanzaChannel_->setSession(session_); session_->onFinished.connect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); session_->onNeedCredentials.connect(boost::bind(&CoreClient::handleNeedCredentials, this)); + session_->onSecurityError.connect(boost::bind(&CoreClient::handleSecurityError, this, _1)); session_->start(); } } @@ -114,6 +115,7 @@ void CoreClient::setCertificate(const String& certificate) { } void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) { + session_->onSecurityError.disconnect(boost::bind(&CoreClient::handleSecurityError, this, _1)); session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this)); session_.reset(); @@ -214,4 +216,17 @@ bool CoreClient::isActive() const { return session_ || connector_; } +void CoreClient::handleSecurityError(const SecurityError& error) { + if (ignoreSecurityErrors) { + session_->continueAfterSecurityError(); + } + else { + onSecurityError(error); + } +} + +void CoreClient::continueAfterSecurityError() { + session_->continueAfterSecurityError(); +} + } diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h index 4170e8d..3176a51 100644 --- a/Swiften/Client/CoreClient.h +++ b/Swiften/Client/CoreClient.h @@ -32,6 +32,7 @@ namespace Swift { class ClientSession; class BasicSessionStream; class EventLoop; + class SecurityError; /** * The central class for communicating with an XMPP server. @@ -71,6 +72,14 @@ namespace Swift { void connect(const String& host); /** + * Instructs the client to continue initializing the session + * after a security error has occurred (and as such ignoring the error) + * + * \see onSecurityError + */ + void continueAfterSecurityError(); + + /** * Sends a message. */ void sendMessage(Message::ref); @@ -131,8 +140,29 @@ namespace Swift { return stanzaChannel_; } + /** + * Sets whether security errors should be ignored or not. + * + * If this is set to 'true', onSecurityError will not be called when a security + * error occurs, and connecting will continue. + * + * Defaults to true. + */ + void setIgnoreSecurityErrors(bool b) { + ignoreSecurityErrors = b; + } + public: /** + * Emitted when an error occurred while establishing a secure connection. + * + * If the error is to be ignored, call continueAfterSecurityError(), otherwise call + * finish(). + * This signal is not emitted when setIgnoreSecurityErrors() is set to true. + */ + boost::signal<void (const SecurityError&)> onSecurityError; + + /** * Emitted when the client was disconnected from the network. * * If the connection was due to a non-recoverable error, the type @@ -187,6 +217,7 @@ namespace Swift { void handleNeedCredentials(); void handleDataRead(const String&); void handleDataWritten(const String&); + void handleSecurityError(const SecurityError& securityError); private: PlatformDomainNameResolver resolver_; @@ -206,5 +237,6 @@ namespace Swift { boost::shared_ptr<ClientSession> session_; String certificate_; bool disconnectRequested_; + bool ignoreSecurityErrors; }; } diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp index 2cd9fd2..43a8bf3 100644 --- a/Swiften/Client/UnitTest/ClientSessionTest.cpp +++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp @@ -283,6 +283,14 @@ class ClientSessionTest : public CppUnit::TestFixture { return tlsEncrypted; } + virtual Certificate::ref getPeerCertificate() const { + return Certificate::ref(); + } + + virtual boost::optional<CertificateVerificationError> getPeerCertificateVerificationError() const { + return boost::optional<CertificateVerificationError>(); + } + virtual void addZLibCompression() { compressed = true; } |