diff options
author | Mili Verma <mili.verma@isode.com> | 2015-07-08 15:27:52 (GMT) |
---|---|---|
committer | Mili Verma <mili.verma@isode.com> | 2015-07-08 15:33:09 (GMT) |
commit | 58bb58557368c520e8a9368fcacff8d22466e759 (patch) | |
tree | bfd8bb3b93ab771482fe46e1d558f4ad399bdaa1 | |
parent | 0e6beadc1b4427e8ab5109e52872f99a5f85c3d8 (diff) | |
download | swift-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
-rw-r--r-- | Swiften/Client/ClientOptions.h | 7 | ||||
-rw-r--r-- | Swiften/Client/ClientSession.cpp | 41 | ||||
-rw-r--r-- | Swiften/Client/ClientSession.h | 14 | ||||
-rw-r--r-- | Swiften/Client/CoreClient.cpp | 2 | ||||
-rw-r--r-- | Swiften/SASL/WindowsGSSAPIClientAuthenticator.cpp | 5 | ||||
-rw-r--r-- | Swiften/SASL/WindowsGSSAPIClientAuthenticator.h | 2 |
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 @@ -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); 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 @@ -14,9 +14,12 @@ 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_); 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 @@ -20,7 +20,7 @@ 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(); |