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
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
-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
@@ -36,10 +36,11 @@ namespace Swift {
36 useTLS(UseTLSWhenAvailable), 36 useTLS(UseTLSWhenAvailable),
37 allowPLAINWithoutTLS(false), 37 allowPLAINWithoutTLS(false),
38 useStreamResumption(false), 38 useStreamResumption(false),
39 forgetPassword(false), 39 forgetPassword(false),
40 useAcks(true), 40 useAcks(true),
41 singleSignOn(false),
41 manualHostname(""), 42 manualHostname(""),
42 manualPort(-1), 43 manualPort(-1),
43 proxyType(SystemConfiguredProxy), 44 proxyType(SystemConfiguredProxy),
44 manualProxyHostname(""), 45 manualProxyHostname(""),
45 manualProxyPort(-1), 46 manualProxyPort(-1),
@@ -91,10 +92,16 @@ namespace Swift {
91 * Default: true 92 * Default: true
92 */ 93 */
93 bool useAcks; 94 bool useAcks;
94 95
95 /** 96 /**
97 * Use Single Sign On.
98 * Default: false
99 */
100 bool singleSignOn;
101
102 /**
96 * The hostname to connect to. 103 * The hostname to connect to.
97 * Leave this empty for standard XMPP connection, based on the JID domain. 104 * Leave this empty for standard XMPP connection, based on the JID domain.
98 */ 105 */
99 std::string manualHostname; 106 std::string manualHostname;
100 107
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,7 +1,7 @@
1/* 1/*
2 * Copyright (c) 2010-2014 Isode Limited. 2 * Copyright (c) 2010-2015 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
6 6
7#include <Swiften/Client/ClientSession.h> 7#include <Swiften/Client/ClientSession.h>
@@ -45,10 +45,11 @@
45#include <Swiften/TLS/CertificateTrustChecker.h> 45#include <Swiften/TLS/CertificateTrustChecker.h>
46#include <Swiften/TLS/ServerIdentityVerifier.h> 46#include <Swiften/TLS/ServerIdentityVerifier.h>
47 47
48#ifdef SWIFTEN_PLATFORM_WIN32 48#ifdef SWIFTEN_PLATFORM_WIN32
49#include <Swiften/Base/WindowsRegistry.h> 49#include <Swiften/Base/WindowsRegistry.h>
50#include <Swiften/SASL/WindowsGSSAPIClientAuthenticator.h>
50#endif 51#endif
51 52
52#define CHECK_STATE_OR_RETURN(a) \ 53#define CHECK_STATE_OR_RETURN(a) \
53 if (!checkState(a)) { return; } 54 if (!checkState(a)) { return; }
54 55
@@ -71,11 +72,13 @@ ClientSession::ClientSession(
71 needSessionStart(false), 72 needSessionStart(false),
72 needResourceBind(false), 73 needResourceBind(false),
73 needAcking(false), 74 needAcking(false),
74 rosterVersioningSupported(false), 75 rosterVersioningSupported(false),
75 authenticator(NULL), 76 authenticator(NULL),
76 certificateTrustChecker(NULL) { 77 certificateTrustChecker(NULL),
78 singleSignOn(false),
79 authenticationPort(-1) {
77#ifdef SWIFTEN_PLATFORM_WIN32 80#ifdef SWIFTEN_PLATFORM_WIN32
78if (WindowsRegistry::isFIPSEnabled()) { 81if (WindowsRegistry::isFIPSEnabled()) {
79 SWIFT_LOG(info) << "Windows is running in FIPS-140 mode. Some authentication methods will be unavailable." << std::endl; 82 SWIFT_LOG(info) << "Windows is running in FIPS-140 mode. Some authentication methods will be unavailable." << std::endl;
80} 83}
81#endif 84#endif
@@ -202,10 +205,36 @@ void ClientSession::handleElement(boost::shared_ptr<ToplevelElement> element) {
202 else if (useStreamCompression && stream->supportsZLibCompression() && streamFeatures->hasCompressionMethod("zlib")) { 205 else if (useStreamCompression && stream->supportsZLibCompression() && streamFeatures->hasCompressionMethod("zlib")) {
203 state = Compressing; 206 state = Compressing;
204 stream->writeElement(boost::make_shared<CompressRequest>("zlib")); 207 stream->writeElement(boost::make_shared<CompressRequest>("zlib"));
205 } 208 }
206 else if (streamFeatures->hasAuthenticationMechanisms()) { 209 else if (streamFeatures->hasAuthenticationMechanisms()) {
210#ifdef SWIFTEN_PLATFORM_WIN32
211 if (singleSignOn) {
212 const boost::optional<std::string> authenticationHostname = streamFeatures->getAuthenticationHostname();
213 bool gssapiSupported = streamFeatures->hasAuthenticationMechanism("GSSAPI") && authenticationHostname && !authenticationHostname->empty();
214
215 if (!gssapiSupported) {
216 finishSession(Error::NoSupportedAuthMechanismsError);
217 }
218 else {
219 WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = new WindowsGSSAPIClientAuthenticator(*authenticationHostname, localJID.getDomain(), authenticationPort);
220 boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError);
221
222 authenticator = gssapiAuthenticator;
223
224 if (!gssapiAuthenticator->isError()) {
225 state = Authenticating;
226 stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse()));
227 }
228 else {
229 error->errorCode = gssapiAuthenticator->getErrorCode();
230 finishSession(error);
231 }
232 }
233 }
234 else
235#endif
207 if (stream->hasTLSCertificate()) { 236 if (stream->hasTLSCertificate()) {
208 if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { 237 if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) {
209 authenticator = new EXTERNALClientAuthenticator(); 238 authenticator = new EXTERNALClientAuthenticator();
210 state = Authenticating; 239 state = Authenticating;
211 stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray(""))); 240 stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray("")));
@@ -296,10 +325,18 @@ void ClientSession::handleElement(boost::shared_ptr<ToplevelElement> element) {
296 CHECK_STATE_OR_RETURN(Authenticating); 325 CHECK_STATE_OR_RETURN(Authenticating);
297 assert(authenticator); 326 assert(authenticator);
298 if (authenticator->setChallenge(challenge->getValue())) { 327 if (authenticator->setChallenge(challenge->getValue())) {
299 stream->writeElement(boost::make_shared<AuthResponse>(authenticator->getResponse())); 328 stream->writeElement(boost::make_shared<AuthResponse>(authenticator->getResponse()));
300 } 329 }
330#ifdef SWIFTEN_PLATFORM_WIN32
331 else if (WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = dynamic_cast<WindowsGSSAPIClientAuthenticator*>(authenticator)) {
332 boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError);
333
334 error->errorCode = gssapiAuthenticator->getErrorCode();
335 finishSession(error);
336 }
337#endif
301 else { 338 else {
302 finishSession(Error::AuthenticationFailedError); 339 finishSession(Error::AuthenticationFailedError);
303 } 340 }
304 } 341 }
305 else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) { 342 else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) {
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
@@ -124,10 +124,22 @@ namespace Swift {
124 124
125 void setCertificateTrustChecker(CertificateTrustChecker* checker) { 125 void setCertificateTrustChecker(CertificateTrustChecker* checker) {
126 certificateTrustChecker = checker; 126 certificateTrustChecker = checker;
127 } 127 }
128 128
129 void setSingleSignOn(bool b) {
130 singleSignOn = b;
131 }
132
133 /**
134 * Sets the port number used in Kerberos authentication
135 * Does not affect network connectivity.
136 */
137 void setAuthenticationPort(int i) {
138 authenticationPort = i;
139 }
140
129 public: 141 public:
130 boost::signal<void ()> onNeedCredentials; 142 boost::signal<void ()> onNeedCredentials;
131 boost::signal<void ()> onInitialized; 143 boost::signal<void ()> onInitialized;
132 boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; 144 boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished;
133 boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; 145 boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived;
@@ -181,7 +193,9 @@ namespace Swift {
181 ClientAuthenticator* authenticator; 193 ClientAuthenticator* authenticator;
182 boost::shared_ptr<StanzaAckRequester> stanzaAckRequester_; 194 boost::shared_ptr<StanzaAckRequester> stanzaAckRequester_;
183 boost::shared_ptr<StanzaAckResponder> stanzaAckResponder_; 195 boost::shared_ptr<StanzaAckResponder> stanzaAckResponder_;
184 boost::shared_ptr<Swift::Error> error_; 196 boost::shared_ptr<Swift::Error> error_;
185 CertificateTrustChecker* certificateTrustChecker; 197 CertificateTrustChecker* certificateTrustChecker;
198 bool singleSignOn;
199 int authenticationPort;
186 }; 200 };
187} 201}
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
@@ -150,10 +150,12 @@ void CoreClient::connect(const ClientOptions& o) {
150void CoreClient::bindSessionToStream() { 150void CoreClient::bindSessionToStream() {
151 session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter(), networkFactories->getCryptoProvider()); 151 session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter(), networkFactories->getCryptoProvider());
152 session_->setCertificateTrustChecker(certificateTrustChecker); 152 session_->setCertificateTrustChecker(certificateTrustChecker);
153 session_->setUseStreamCompression(options.useStreamCompression); 153 session_->setUseStreamCompression(options.useStreamCompression);
154 session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS); 154 session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS);
155 session_->setSingleSignOn(options.singleSignOn);
156 session_->setAuthenticationPort(options.manualPort);
155 switch(options.useTLS) { 157 switch(options.useTLS) {
156 case ClientOptions::UseTLSWhenAvailable: 158 case ClientOptions::UseTLSWhenAvailable:
157 session_->setUseTLS(ClientSession::UseTLSWhenAvailable); 159 session_->setUseTLS(ClientSession::UseTLSWhenAvailable);
158 break; 160 break;
159 case ClientOptions::NeverUseTLS: 161 case ClientOptions::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
@@ -12,13 +12,16 @@
12 12
13#define SECURITY_LAYER_NONE 1 13#define SECURITY_LAYER_NONE 1
14 14
15namespace Swift { 15namespace Swift {
16 16
17WindowsGSSAPIClientAuthenticator::WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname) : ClientAuthenticator("GSSAPI"), step_(BuildingSecurityContext), error_(false), haveCredentialsHandle_(false), haveContextHandle_(false), haveCompleteContext_(false) { 17WindowsGSSAPIClientAuthenticator::WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname, int port) : ClientAuthenticator("GSSAPI"), step_(BuildingSecurityContext), error_(false), haveCredentialsHandle_(false), haveContextHandle_(false), haveCompleteContext_(false) {
18 WindowsServicePrincipalName servicePrincipalName(domainname); 18 WindowsServicePrincipalName servicePrincipalName(domainname);
19 servicePrincipalName.setInstanceName(hostname); 19 servicePrincipalName.setInstanceName(hostname);
20 if ((port != -1) && (port != 5222)) {
21 servicePrincipalName.setInstancePort(port);
22 }
20 servicePrincipalNameString_ = servicePrincipalName.toString(); 23 servicePrincipalNameString_ = servicePrincipalName.toString();
21 24
22 errorCode_ = acquireCredentialsHandle(&credentialsHandle_); 25 errorCode_ = acquireCredentialsHandle(&credentialsHandle_);
23 if (isError()) { 26 if (isError()) {
24 return; 27 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
@@ -18,11 +18,11 @@
18#include <Swiften/SASL/ClientAuthenticator.h> 18#include <Swiften/SASL/ClientAuthenticator.h>
19 19
20namespace Swift { 20namespace Swift {
21 class SWIFTEN_API WindowsGSSAPIClientAuthenticator : public ClientAuthenticator { 21 class SWIFTEN_API WindowsGSSAPIClientAuthenticator : public ClientAuthenticator {
22 public: 22 public:
23 WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname); 23 WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname, int port);
24 24
25 ~WindowsGSSAPIClientAuthenticator(); 25 ~WindowsGSSAPIClientAuthenticator();
26 26
27 virtual boost::optional<SafeByteArray> getResponse() const; 27 virtual boost::optional<SafeByteArray> getResponse() const;
28 virtual bool setChallenge(const boost::optional<std::vector<unsigned char> >&); 28 virtual bool setChallenge(const boost::optional<std::vector<unsigned char> >&);