summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMili Verma <mili.verma@isode.com>2015-07-08 15:27:52 (GMT)
committerMili Verma <mili.verma@isode.com>2015-07-08 15:33:09 (GMT)
commit58bb58557368c520e8a9368fcacff8d22466e759 (patch)
treebfd8bb3b93ab771482fe46e1d558f4ad399bdaa1 /Swiften/Client
parent0e6beadc1b4427e8ab5109e52872f99a5f85c3d8 (diff)
downloadswift-58bb58557368c520e8a9368fcacff8d22466e759.zip
swift-58bb58557368c520e8a9368fcacff8d22466e759.tar.bz2
Use GSSAPI when SSO is used
This patch uses the GSSAPI authenticator on Windows if the server advertises it and the client requests it. (The user is not able to request it in the UI yet) Also sends the manual port to the GSSAPI authenticator to construct the SPN if a non-default port is used. Test-information: Tested on Windows using WIP code. Tested both on TLS & without. Unit tests pass. Change-Id: I9a9ad9604fe084d5fb2003b7a91174a9512e2eec
Diffstat (limited to 'Swiften/Client')
-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
4 files changed, 62 insertions, 2 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
@@ -38,6 +38,7 @@ namespace Swift {
useStreamResumption(false),
forgetPassword(false),
useAcks(true),
+ singleSignOn(false),
manualHostname(""),
manualPort(-1),
proxyType(SystemConfiguredProxy),
@@ -93,6 +94,12 @@ namespace Swift {
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.
*/
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,5 +1,5 @@
/*
- * Copyright (c) 2010-2014 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -47,6 +47,7 @@
#ifdef SWIFTEN_PLATFORM_WIN32
#include <Swiften/Base/WindowsRegistry.h>
+#include <Swiften/SASL/WindowsGSSAPIClientAuthenticator.h>
#endif
#define CHECK_STATE_OR_RETURN(a) \
@@ -73,7 +74,9 @@ ClientSession::ClientSession(
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;
@@ -204,6 +207,32 @@ void ClientSession::handleElement(boost::shared_ptr<ToplevelElement> element) {
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();
@@ -298,6 +327,14 @@ void ClientSession::handleElement(boost::shared_ptr<ToplevelElement> element) {
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);
}
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
@@ -126,6 +126,18 @@ namespace Swift {
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;
@@ -183,5 +195,7 @@ namespace Swift {
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
@@ -152,6 +152,8 @@ void CoreClient::bindSessionToStream() {
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);