summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swiften/Client/ClientOptions.h7
-rw-r--r--Swiften/Client/ClientSession.cpp41
-rw-r--r--Swiften/Client/ClientSession.h14
-rw-r--r--Swiften/Client/CoreClient.cpp2
-rw-r--r--Swiften/SASL/WindowsGSSAPIClientAuthenticator.cpp5
-rw-r--r--Swiften/SASL/WindowsGSSAPIClientAuthenticator.h2
6 files changed, 67 insertions, 4 deletions
diff --git a/Swiften/Client/ClientOptions.h b/Swiften/Client/ClientOptions.h
index 25393e4..c09b987 100644
--- a/Swiften/Client/ClientOptions.h
+++ b/Swiften/Client/ClientOptions.h
@@ -35,12 +35,13 @@ namespace Swift {
useStreamCompression(true),
useTLS(UseTLSWhenAvailable),
allowPLAINWithoutTLS(false),
useStreamResumption(false),
forgetPassword(false),
useAcks(true),
+ singleSignOn(false),
manualHostname(""),
manualPort(-1),
proxyType(SystemConfiguredProxy),
manualProxyHostname(""),
manualProxyPort(-1),
boshHTTPConnectProxyAuthID(""),
@@ -90,12 +91,18 @@ namespace Swift {
* Use XEP-0198 acks in the stream when available.
* Default: true
*/
bool useAcks;
/**
+ * Use Single Sign On.
+ * Default: false
+ */
+ bool singleSignOn;
+
+ /**
* The hostname to connect to.
* Leave this empty for standard XMPP connection, based on the JID domain.
*/
std::string manualHostname;
/**
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index 26b89c4..52b8cfb 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -1,8 +1,8 @@
/*
- * Copyright (c) 2010-2014 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swiften/Client/ClientSession.h>
@@ -44,12 +44,13 @@
#include <Swiften/Session/SessionStream.h>
#include <Swiften/TLS/CertificateTrustChecker.h>
#include <Swiften/TLS/ServerIdentityVerifier.h>
#ifdef SWIFTEN_PLATFORM_WIN32
#include <Swiften/Base/WindowsRegistry.h>
+#include <Swiften/SASL/WindowsGSSAPIClientAuthenticator.h>
#endif
#define CHECK_STATE_OR_RETURN(a) \
if (!checkState(a)) { return; }
namespace Swift {
@@ -70,13 +71,15 @@ ClientSession::ClientSession(
useAcks(true),
needSessionStart(false),
needResourceBind(false),
needAcking(false),
rosterVersioningSupported(false),
authenticator(NULL),
- certificateTrustChecker(NULL) {
+ certificateTrustChecker(NULL),
+ singleSignOn(false),
+ authenticationPort(-1) {
#ifdef SWIFTEN_PLATFORM_WIN32
if (WindowsRegistry::isFIPSEnabled()) {
SWIFT_LOG(info) << "Windows is running in FIPS-140 mode. Some authentication methods will be unavailable." << std::endl;
}
#endif
}
@@ -201,12 +204,38 @@ void ClientSession::handleElement(boost::shared_ptr<ToplevelElement> element) {
}
else if (useStreamCompression && stream->supportsZLibCompression() && streamFeatures->hasCompressionMethod("zlib")) {
state = Compressing;
stream->writeElement(boost::make_shared<CompressRequest>("zlib"));
}
else if (streamFeatures->hasAuthenticationMechanisms()) {
+#ifdef SWIFTEN_PLATFORM_WIN32
+ if (singleSignOn) {
+ const boost::optional<std::string> authenticationHostname = streamFeatures->getAuthenticationHostname();
+ bool gssapiSupported = streamFeatures->hasAuthenticationMechanism("GSSAPI") && authenticationHostname && !authenticationHostname->empty();
+
+ if (!gssapiSupported) {
+ finishSession(Error::NoSupportedAuthMechanismsError);
+ }
+ else {
+ WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = new WindowsGSSAPIClientAuthenticator(*authenticationHostname, localJID.getDomain(), authenticationPort);
+ boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError);
+
+ authenticator = gssapiAuthenticator;
+
+ if (!gssapiAuthenticator->isError()) {
+ state = Authenticating;
+ stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse()));
+ }
+ else {
+ error->errorCode = gssapiAuthenticator->getErrorCode();
+ finishSession(error);
+ }
+ }
+ }
+ else
+#endif
if (stream->hasTLSCertificate()) {
if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) {
authenticator = new EXTERNALClientAuthenticator();
state = Authenticating;
stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray("")));
}
@@ -295,12 +324,20 @@ void ClientSession::handleElement(boost::shared_ptr<ToplevelElement> element) {
else if (AuthChallenge* challenge = dynamic_cast<AuthChallenge*>(element.get())) {
CHECK_STATE_OR_RETURN(Authenticating);
assert(authenticator);
if (authenticator->setChallenge(challenge->getValue())) {
stream->writeElement(boost::make_shared<AuthResponse>(authenticator->getResponse()));
}
+#ifdef SWIFTEN_PLATFORM_WIN32
+ else if (WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = dynamic_cast<WindowsGSSAPIClientAuthenticator*>(authenticator)) {
+ boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError);
+
+ error->errorCode = gssapiAuthenticator->getErrorCode();
+ finishSession(error);
+ }
+#endif
else {
finishSession(Error::AuthenticationFailedError);
}
}
else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) {
CHECK_STATE_OR_RETURN(Authenticating);
diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h
index 9bbc3f2..c4b6abe 100644
--- a/Swiften/Client/ClientSession.h
+++ b/Swiften/Client/ClientSession.h
@@ -123,12 +123,24 @@ namespace Swift {
void sendStanza(boost::shared_ptr<Stanza>);
void setCertificateTrustChecker(CertificateTrustChecker* checker) {
certificateTrustChecker = checker;
}
+ void setSingleSignOn(bool b) {
+ singleSignOn = b;
+ }
+
+ /**
+ * Sets the port number used in Kerberos authentication
+ * Does not affect network connectivity.
+ */
+ void setAuthenticationPort(int i) {
+ authenticationPort = i;
+ }
+
public:
boost::signal<void ()> onNeedCredentials;
boost::signal<void ()> onInitialized;
boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished;
boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived;
boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked;
@@ -180,8 +192,10 @@ namespace Swift {
bool rosterVersioningSupported;
ClientAuthenticator* authenticator;
boost::shared_ptr<StanzaAckRequester> stanzaAckRequester_;
boost::shared_ptr<StanzaAckResponder> stanzaAckResponder_;
boost::shared_ptr<Swift::Error> error_;
CertificateTrustChecker* certificateTrustChecker;
+ bool singleSignOn;
+ int authenticationPort;
};
}
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index baebd4a..b1a375b 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -149,12 +149,14 @@ void CoreClient::connect(const ClientOptions& o) {
void CoreClient::bindSessionToStream() {
session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter(), networkFactories->getCryptoProvider());
session_->setCertificateTrustChecker(certificateTrustChecker);
session_->setUseStreamCompression(options.useStreamCompression);
session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS);
+ session_->setSingleSignOn(options.singleSignOn);
+ session_->setAuthenticationPort(options.manualPort);
switch(options.useTLS) {
case ClientOptions::UseTLSWhenAvailable:
session_->setUseTLS(ClientSession::UseTLSWhenAvailable);
break;
case ClientOptions::NeverUseTLS:
session_->setUseTLS(ClientSession::NeverUseTLS);
diff --git a/Swiften/SASL/WindowsGSSAPIClientAuthenticator.cpp b/Swiften/SASL/WindowsGSSAPIClientAuthenticator.cpp
index 7423243..f602bff 100644
--- a/Swiften/SASL/WindowsGSSAPIClientAuthenticator.cpp
+++ b/Swiften/SASL/WindowsGSSAPIClientAuthenticator.cpp
@@ -11,15 +11,18 @@
#include <Swiften/SASL/WindowsServicePrincipalName.h>
#define SECURITY_LAYER_NONE 1
namespace Swift {
-WindowsGSSAPIClientAuthenticator::WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname) : ClientAuthenticator("GSSAPI"), step_(BuildingSecurityContext), error_(false), haveCredentialsHandle_(false), haveContextHandle_(false), haveCompleteContext_(false) {
+WindowsGSSAPIClientAuthenticator::WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname, int port) : ClientAuthenticator("GSSAPI"), step_(BuildingSecurityContext), error_(false), haveCredentialsHandle_(false), haveContextHandle_(false), haveCompleteContext_(false) {
WindowsServicePrincipalName servicePrincipalName(domainname);
servicePrincipalName.setInstanceName(hostname);
+ if ((port != -1) && (port != 5222)) {
+ servicePrincipalName.setInstancePort(port);
+ }
servicePrincipalNameString_ = servicePrincipalName.toString();
errorCode_ = acquireCredentialsHandle(&credentialsHandle_);
if (isError()) {
return;
}
diff --git a/Swiften/SASL/WindowsGSSAPIClientAuthenticator.h b/Swiften/SASL/WindowsGSSAPIClientAuthenticator.h
index d046999..f772b71 100644
--- a/Swiften/SASL/WindowsGSSAPIClientAuthenticator.h
+++ b/Swiften/SASL/WindowsGSSAPIClientAuthenticator.h
@@ -17,13 +17,13 @@
#include <Swiften/Base/SafeByteArray.h>
#include <Swiften/SASL/ClientAuthenticator.h>
namespace Swift {
class SWIFTEN_API WindowsGSSAPIClientAuthenticator : public ClientAuthenticator {
public:
- WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname);
+ WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname, int port);
~WindowsGSSAPIClientAuthenticator();
virtual boost::optional<SafeByteArray> getResponse() const;
virtual bool setChallenge(const boost::optional<std::vector<unsigned char> >&);