diff options
-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(); |