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 @@ -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> >&); |