summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/Client')
-rw-r--r--Swiften/Client/CoreClient.cpp31
-rw-r--r--Swiften/Client/CoreClient.h12
2 files changed, 12 insertions, 31 deletions
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 36bfe35..e2a8e5a 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -94,135 +94,110 @@ void CoreClient::connect(const std::string& host) {
networkFactories->getDomainNameResolver(),
host,
options.boshHTTPConnectProxyURL,
options.boshHTTPConnectProxyAuthID,
options.boshHTTPConnectProxyAuthPassword));
sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1));
sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1));
bindSessionToStream();
}
}
void CoreClient::bindSessionToStream() {
session_ = ClientSession::create(jid_, sessionStream_);
session_->setCertificateTrustChecker(certificateTrustChecker);
session_->setUseStreamCompression(options.useStreamCompression);
session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS);
switch(options.useTLS) {
case ClientOptions::UseTLSWhenAvailable:
session_->setUseTLS(ClientSession::UseTLSWhenAvailable);
break;
case ClientOptions::NeverUseTLS:
session_->setUseTLS(ClientSession::NeverUseTLS);
break;
case ClientOptions::RequireTLS:
session_->setUseTLS(ClientSession::RequireTLS);
break;
}
session_->setUseAcks(options.useAcks);
stanzaChannel_->setSession(session_);
session_->onFinished.connect(boost::bind(&CoreClient::handleSessionFinished, this, _1));
session_->onNeedCredentials.connect(boost::bind(&CoreClient::handleNeedCredentials, this));
session_->start();
}
-bool CoreClient::isCAPIURI() {
-#ifdef HAVE_SCHANNEL
- if (!boost::iequals(certificate_.substr(0, 10), "certstore:")) {
- return false;
- }
-
- return true;
-
-#else
- return false;
-#endif
-}
-
/**
* Only called for TCP sessions. BOSH is handled inside the BOSHSessionStream.
*/
void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
resetConnector();
if (!connection) {
if (options.forgetPassword) {
purgePassword();
}
onDisconnected(disconnectRequested_ ? boost::optional<ClientError>() : boost::optional<ClientError>(ClientError::ConnectionError));
}
else {
assert(!connection_);
connection_ = connection;
assert(!sessionStream_);
sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory());
- if (!certificate_.empty()) {
- CertificateWithKey* cert;
-
-#if defined(SWIFTEN_PLATFORM_WIN32)
- if (isCAPIURI()) {
- cert = new CAPICertificate(certificate_);
- } else {
- cert = new PKCS12Certificate(certificate_, password_);
- }
-#else
- cert = new PKCS12Certificate(certificate_, password_);
-#endif
-
- sessionStream_->setTLSCertificate(cert);
+ if (certificate_ && !certificate_->isNull()) {
+ sessionStream_->setTLSCertificate(certificate_);
}
sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1));
sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1));
bindSessionToStream();
}
}
void CoreClient::disconnect() {
// FIXME: We should be able to do without this boolean. We just have to make sure we can tell the difference between
// connector finishing without a connection due to an error or because of a disconnect.
disconnectRequested_ = true;
if (session_ && !session_->isFinished()) {
session_->finish();
}
else if (connector_) {
connector_->stop();
}
}
-void CoreClient::setCertificate(const std::string& certificate) {
+void CoreClient::setCertificate(CertificateWithKey::ref certificate) {
certificate_ = certificate;
}
void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) {
if (options.forgetPassword) {
purgePassword();
}
resetSession();
boost::optional<ClientError> actualError;
if (error) {
ClientError clientError;
if (boost::shared_ptr<ClientSession::Error> actualError = boost::dynamic_pointer_cast<ClientSession::Error>(error)) {
switch(actualError->type) {
case ClientSession::Error::AuthenticationFailedError:
clientError = ClientError(ClientError::AuthenticationFailedError);
break;
case ClientSession::Error::CompressionFailedError:
clientError = ClientError(ClientError::CompressionFailedError);
break;
case ClientSession::Error::ServerVerificationFailedError:
clientError = ClientError(ClientError::ServerVerificationFailedError);
break;
case ClientSession::Error::NoSupportedAuthMechanismsError:
clientError = ClientError(ClientError::NoSupportedAuthMechanismsError);
break;
case ClientSession::Error::UnexpectedElementError:
clientError = ClientError(ClientError::UnexpectedElementError);
break;
case ClientSession::Error::ResourceBindError:
clientError = ClientError(ClientError::ResourceBindError);
break;
case ClientSession::Error::SessionStartError:
clientError = ClientError(ClientError::SessionStartError);
break;
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index 6712e03..1b875d2 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -1,91 +1,97 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2012 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <string>
#include <boost/shared_ptr.hpp>
#include <Swiften/Base/boost_bsignals.h>
#include <Swiften/Entity/Entity.h>
#include <Swiften/JID/JID.h>
#include <Swiften/Client/ClientError.h>
#include <Swiften/Client/ClientOptions.h>
#include <Swiften/Base/SafeByteArray.h>
+#include <Swiften/TLS/CertificateWithKey.h>
namespace Swift {
class ChainedConnector;
class Message;
class Presence;
class Error;
class IQRouter;
class TLSContextFactory;
class ConnectionFactory;
class Connection;
class TimerFactory;
class ClientSession;
class StanzaChannel;
class Stanza;
class SessionStream;
class CertificateTrustChecker;
class NetworkFactories;
class ClientSessionStanzaChannel;
/**
* The central class for communicating with an XMPP server.
*
* This class is responsible for setting up the connection with the XMPP
* server, authenticating, and initializing the session.
*
* This class can be used directly in your application, although the Client
* subclass provides more functionality and interfaces, and is better suited
* for most needs.
*/
class CoreClient : public Entity {
public:
/**
* Constructs a client for the given JID with the given password.
* The given eventLoop will be used to post events to.
*/
CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories);
~CoreClient();
- void setCertificate(const std::string& certificate);
+ /**
+ * Set a client certificate to use for strong authentication with the server.
+ * Ensure that it is of the correct type for the TLS engine in use.
+ * This means, largely, PKCS12Certificate for OpenSSL and CAPICertificate for CAPI.
+ */
+ void setCertificate(CertificateWithKey::ref certificate);
/**
* Connects the client to the server.
*
* After the connection is established, the client will set
* initialize the stream and authenticate.
*/
void connect(const ClientOptions& = ClientOptions());
/**
* Disconnects the client from the server.
*/
void disconnect();
void connect(const std::string& host);
/**
* Sends a message.
*/
void sendMessage(boost::shared_ptr<Message>);
/**
* Sends a presence stanza.
*/
void sendPresence(boost::shared_ptr<Presence>);
/**
* Sends raw, unchecked data.
*/
void sendData(const std::string& data);
/**
* Returns the IQ router for this client.
*/
IQRouter* getIQRouter() const {
@@ -195,40 +201,40 @@ namespace Swift {
* Called before onConnected signal is emmitted.
*/
virtual void handleConnected() {};
bool isCAPIURI();
private:
void handleConnectorFinished(boost::shared_ptr<Connection>);
void handleStanzaChannelAvailableChanged(bool available);
void handleSessionFinished(boost::shared_ptr<Error>);
void handleNeedCredentials();
void handleDataRead(const SafeByteArray&);
void handleDataWritten(const SafeByteArray&);
void handlePresenceReceived(boost::shared_ptr<Presence>);
void handleMessageReceived(boost::shared_ptr<Message>);
void handleStanzaAcked(boost::shared_ptr<Stanza>);
void purgePassword();
void bindSessionToStream();
void resetConnector();
void resetSession();
void forceReset();
private:
JID jid_;
SafeByteArray password_;
NetworkFactories* networkFactories;
ClientSessionStanzaChannel* stanzaChannel_;
IQRouter* iqRouter_;
ClientOptions options;
boost::shared_ptr<ChainedConnector> connector_;
std::vector<ConnectionFactory*> proxyConnectionFactories;
boost::shared_ptr<Connection> connection_;
boost::shared_ptr<SessionStream> sessionStream_;
boost::shared_ptr<ClientSession> session_;
- std::string certificate_;
+ CertificateWithKey::ref certificate_;
bool disconnectRequested_;
CertificateTrustChecker* certificateTrustChecker;
};
}