summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2010-11-07 14:58:23 (GMT)
committerRemko Tronçon <git@el-tramo.be>2010-11-07 18:04:57 (GMT)
commite2f2e48f6e01739ccaa763ff7f037306131d4e61 (patch)
tree92fefe8ff9255356d849d1eadcad45666bde52e5 /Swiften/Client
parent832d109bfabc16ef2834790743c1d235b254d781 (diff)
downloadswift-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.cpp19
-rw-r--r--Swiften/Client/ClientSession.h5
-rw-r--r--Swiften/Client/CoreClient.cpp17
-rw-r--r--Swiften/Client/CoreClient.h32
-rw-r--r--Swiften/Client/UnitTest/ClientSessionTest.cpp8
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;
}