diff --git a/SOURCES/cyrus-sasl-2.1.26-gss-spnego.patch b/SOURCES/cyrus-sasl-2.1.26-gss-spnego.patch
new file mode 100644
index 0000000..69ab893
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.26-gss-spnego.patch
@@ -0,0 +1,139 @@
+From 67ca66685e11acc0f69d5ff8013107d4b172e67f Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Thu, 16 Feb 2017 15:25:56 -0500
+Subject: [PATCH] Fix GSS-SPNEGO mechanism's incompatible behavior
+
+The GSS-SPNEGO mechanism has been designed and introduced by Microsoft for use
+by Active Directory clients. It allows to negotiate an underlying
+Security Mechanism like Krb5 or NTLMSSP.
+However, the implementaion in cyrus-sasl is broken and never correctly
+interoperated with Microsoft servers or clients. This patch fixes the
+compatibility issue which is caused by incorrectly trying to negotiate
+SSF layers explicitly instead of using the flags negotiated by GSSAPI
+as required by Microsoft's implementation.
+
+Signed-off-by: Simo Sorce <simo@redhat.com>
+---
+ plugins/gssapi.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 64 insertions(+), 6 deletions(-)
+
+diff --git a/plugins/gssapi.c b/plugins/gssapi.c
+index bfc278d..010c236 100644
+--- a/plugins/gssapi.c
++++ b/plugins/gssapi.c
+@@ -648,10 +648,62 @@ static void gssapi_common_mech_free(void *global_context __attribute__((unused))
+ #endif
+ }
+ 
++/* The GSS-SPNEGO mechanism does not do SSF negotiation, instead it uses the
++ * flags negotiated by GSSAPI to determine If confidentiality or integrity are
++ * used. These flags are stored in text->qop transalated as layers by the
++ * caller */
++static int gssapi_spnego_ssf(context_t *text, const sasl_utils_t *utils,
++                             sasl_security_properties_t *props,
++                             sasl_out_params_t *oparams)
++{
++    OM_uint32 maj_stat = 0, min_stat = 0;
++    OM_uint32 max_input;
++
++    if (text->qop & LAYER_CONFIDENTIALITY) {
++        oparams->encode = &gssapi_privacy_encode;
++        oparams->decode = &gssapi_decode;
++        oparams->mech_ssf = K5_MAX_SSF;
++    } else if (text->qop & LAYER_INTEGRITY) {
++        oparams->encode = &gssapi_integrity_encode;
++        oparams->decode = &gssapi_decode;
++        oparams->mech_ssf = 1;
++    } else {
++        oparams->encode = NULL;
++        oparams->decode = NULL;
++        oparams->mech_ssf = 0;
++    }
++
++    if (oparams->mech_ssf) {
++        maj_stat = gss_wrap_size_limit(&min_stat,
++                                       text->gss_ctx,
++                                       1,
++                                       GSS_C_QOP_DEFAULT,
++                                       (OM_uint32)oparams->maxoutbuf,
++                                       &max_input);
++
++	if (max_input > oparams->maxoutbuf) {
++	    /* Heimdal appears to get this wrong */
++	    oparams->maxoutbuf -= (max_input - oparams->maxoutbuf);
++	} else {
++	    /* This code is actually correct */
++	    oparams->maxoutbuf = max_input;
++	}
++    }
++
++    text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
++
++    /* used by layers */
++    _plug_decode_init(&text->decode_context, text->utils,
++		      (props->maxbufsize > 0xFFFFFF) ? 0xFFFFFF :
++                      props->maxbufsize);
++
++    return SASL_OK;
++}
++
+ /*****************************  Server Section  *****************************/
+ 
+ static int 
+-gssapi_server_mech_new(void *glob_context __attribute__((unused)), 
++gssapi_server_mech_new(void *glob_context,
+ 		       sasl_server_params_t *params,
+ 		       const char *challenge __attribute__((unused)), 
+ 		       unsigned challen __attribute__((unused)),
+@@ -673,6 +725,7 @@ gssapi_server_mech_new(void *glob_context __attribute__((unused)),
+     text->state = SASL_GSSAPI_STATE_AUTHNEG;
+     
+     text->http_mode = (params->flags & SASL_NEED_HTTP);
++    text->mech_type = (gss_OID) glob_context;
+ 
+     *conn_context = text;
+     
+@@ -686,7 +739,7 @@ gssapi_server_mech_authneg(context_t *text,
+ 			   unsigned clientinlen,
+ 			   const char **serverout,
+ 			   unsigned *serveroutlen,
+-			   sasl_out_params_t *oparams __attribute__((unused)))
++			   sasl_out_params_t *oparams)
+ {
+     gss_buffer_t input_token, output_token;
+     gss_buffer_desc real_input_token, real_output_token;
+@@ -965,8 +1018,9 @@ gssapi_server_mech_authneg(context_t *text,
+ 	/* HTTP doesn't do any ssf negotiation */
+ 	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
+ 	ret = SASL_OK;
+-    }
+-    else {
++    } else if (text->mech_type && text->mech_type == &gss_spnego_oid) {
++        ret = gssapi_spnego_ssf(text, params->utils, &params->props, oparams);
++    } else {
+ 	/* Switch to ssf negotiation */
+ 	text->state = SASL_GSSAPI_STATE_SSFCAP;
+ 	ret = SASL_CONTINUE;
+@@ -1391,7 +1445,7 @@ static sasl_server_plug_t gssapi_server_plugins[] =
+ 	| SASL_FEAT_ALLOWS_PROXY
+ 	| SASL_FEAT_DONTUSE_USERPASSWD
+ 	| SASL_FEAT_SUPPORTS_HTTP,	/* features */
+-	NULL,				/* glob_context */
++	&gss_spnego_oid,		/* glob_context */
+ 	&gssapi_server_mech_new,	/* mech_new */
+ 	&gssapi_server_mech_step,	/* mech_step */
+ 	&gssapi_common_mech_dispose,	/* mech_dispose */
+@@ -1769,7 +1823,11 @@ static int gssapi_client_mech_step(void *conn_context,
+ 		text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
+ 		oparams->doneflag = 1;
+ 		return SASL_OK;
+-	    }
++	    } else if (text->mech_type && text->mech_type == &gss_spnego_oid) {
++		oparams->doneflag = 1;
++                return gssapi_spnego_ssf(text, params->utils, &params->props,
++                                         oparams);
++            }
+ 
+ 	    /* Switch to ssf negotiation */
+ 	    text->state = SASL_GSSAPI_STATE_SSFCAP;
+
diff --git a/SPECS/cyrus-sasl.spec b/SPECS/cyrus-sasl.spec
index 2124c7f..8c60980 100644
--- a/SPECS/cyrus-sasl.spec
+++ b/SPECS/cyrus-sasl.spec
@@ -10,7 +10,7 @@
 Summary: The Cyrus SASL library
 Name: cyrus-sasl
 Version: 2.1.26
-Release: 20%{?dist}
+Release: 21%{?dist}
 License: BSD with advertising
 Group: System Environment/Libraries
 # Source0 originally comes from ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/;
@@ -64,6 +64,8 @@ Patch56: cyrus-sasl-2.1.26-handle-single-character-mechanisms.patch
 Patch57: cyrus-sasl-2.1.26-error-message-when-config-has-typo.patch
 # GSSAPI: Use per-connection mutex where possible (#1263017)
 Patch58: cyrus-sasl-2.1.26-gssapi-use-per-connection-mutex.patch
+# GSS-SPNEGO compatible with Windows clients (#1421663)
+Patch59: cyrus-sasl-2.1.26-gss-spnego.patch
 
 Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: autoconf, automake, libtool, gdbm-devel, groff
@@ -214,6 +216,7 @@ chmod -x include/*.h
 %patch56 -p1 -b .prefix
 %patch57 -p1 -b .typo
 %patch58 -p1 -b .mutex
+%patch59 -p1 -b .spnego
 
 
 %build
@@ -437,6 +440,9 @@ getent passwd %{username} >/dev/null || useradd -r -g %{username} -d %{homedir} 
 %{_sbindir}/sasl2-shared-mechlist
 
 %changelog
+* Mon Mar 06 2017 Jakub Jelen <jjelen@redhat.com> - 2.1.26-21
+- support proper SASL GSS-SPNEGO (#1421663)
+
 * Fri Dec 04 2015 Jakub Jelen <jjelen@redhat.com> 2.1.26-20
 - GSSAPI: Use per-connection mutex where possible (#1263017)