Blob Blame History Raw
Backport of part of Upstream PR#603 minimal part needed for interop

From 0e722dd3266d5ebd0f889462cc23856fde3d21ed Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Thu, 19 Sep 2019 15:58:04 -0400
Subject: [PATCH] Add support for setting max ssf 0 to GSS-SPNEGO

This is needed to interop with Windows within a TLS channel.

Signed-off-by: Simo Sorce <simo@redhat.com>
---
 m4/sasl2.m4      | 13 +++++++++++++
 plugins/gssapi.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/m4/sasl2.m4 b/m4/sasl2.m4
index 17f5d081..60306943 100644
--- a/m4/sasl2.m4
+++ b/m4/sasl2.m4
@@ -287,6 +287,19 @@ if test "$gssapi" != no; then
   AC_CHECK_FUNCS(gss_oid_equal)
   LIBS="$cmu_save_LIBS"
 
+  cmu_save_LIBS="$LIBS"
+  LIBS="$LIBS $GSSAPIBASE_LIBS"
+  if test "$ac_cv_header_gssapi_gssapi_krb5_h" = "yes"; then
+    AC_CHECK_DECL(GSS_KRB5_CRED_NO_CI_FLAGS_X,
+                  [AC_DEFINE(HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X,1,
+                             [Define if your GSSAPI implementation supports GSS_KRB5_CRED_NO_CI_FLAGS_X])],,
+                  [
+                    AC_INCLUDES_DEFAULT
+                    #include <gssapi/gssapi_krb5.h>
+                    ])
+  fi
+  LIBS="$cmu_save_LIBS"
+
   cmu_save_LIBS="$LIBS"
   LIBS="$LIBS $GSSAPIBASE_LIBS"
   AC_CHECK_FUNCS(gss_get_name_attribute)
diff --git a/plugins/gssapi.c b/plugins/gssapi.c
index 46de7d48..cca6cc0a 100644
--- a/plugins/gssapi.c
+++ b/plugins/gssapi.c
@@ -2123,7 +2123,50 @@ static int gssapi_client_mech_step(void *conn_context,
 		/* We want to try for privacy */
 		req_flags |= GSS_C_CONF_FLAG;
 	    }
-	}
+#ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
+        /* The krb5 mechanism automatically adds INTEG and CONF flags even when
+         * not specified, this has the effect of rendering explicit requests
+         * of no confidentiality and integrity via setting maxssf 0 moot.
+         * However to interoperate with Windows machines it needs to be
+         * possible to unset these flags as Windows machines refuse to allow
+         * two layers (say TLS and GSSAPI) to both provide these services.
+         * So if we do not suppress these flags a SASL/GSS-SPNEGO negotiation
+         * over, say, LDAPS will fail against Windows Servers */
+	} else if (params->props.max_ssf == 0) {
+            gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
+            if (client_creds == GSS_C_NO_CREDENTIAL) {
+                gss_OID_set_desc mechs = { 0 };
+                gss_OID_set desired_mechs = GSS_C_NO_OID_SET;
+                if (text->mech_type != GSS_C_NO_OID) {
+                    mechs.count = 1;
+                    mechs.elements = text->mech_type;
+                    desired_mechs = &mechs;
+                }
+
+                maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME,
+                                            GSS_C_INDEFINITE, desired_mechs,
+                                            GSS_C_INITIATE,
+                                            &text->client_creds, NULL, NULL);
+                if (GSS_ERROR(maj_stat)) {
+                    sasl_gss_seterror(text->utils, maj_stat, min_stat);
+                    sasl_gss_free_context_contents(text);
+                    return SASL_FAIL;
+                }
+                client_creds = text->client_creds;
+            }
+
+            maj_stat = gss_set_cred_option(&min_stat, &client_creds,
+                                           (gss_OID)GSS_KRB5_CRED_NO_CI_FLAGS_X,
+                                            &empty_buffer);
+            if (GSS_ERROR(maj_stat)) {
+                sasl_gss_seterror(text->utils, maj_stat, min_stat);
+                sasl_gss_free_context_contents(text);
+                return SASL_FAIL;
+            }
+#endif
+        }
+
+

	if (params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) {
	    req_flags = req_flags |  GSS_C_DELEG_FLAG;