Blame SOURCES/cyrus-sasl-2.1.26-gss-ssf.patch

6611fc
From 862b60c249c8a51095315062b22c0702a6500d80 Mon Sep 17 00:00:00 2001
6611fc
From: Simo Sorce <simo@redhat.com>
6611fc
Date: Tue, 11 Apr 2017 18:31:46 -0400
6611fc
Subject: [PATCH 1/3] Drop unused parameter from gssapi_spnego_ssf()
6611fc
6611fc
Signed-off-by: Simo Sorce <simo@redhat.com>
6611fc
---
6611fc
 plugins/gssapi.c | 7 +++----
6611fc
 1 file changed, 3 insertions(+), 4 deletions(-)
6611fc
6611fc
diff --git a/plugins/gssapi.c b/plugins/gssapi.c
6611fc
index 010c236d..3050962e 100644
6611fc
--- a/plugins/gssapi.c
6611fc
+++ b/plugins/gssapi.c
6611fc
@@ -652,7 +652,7 @@ static void gssapi_common_mech_free(void *global_context __attribute__((unused))
6611fc
  * flags negotiated by GSSAPI to determine If confidentiality or integrity are
6611fc
  * used. These flags are stored in text->qop transalated as layers by the
6611fc
  * caller */
6611fc
-static int gssapi_spnego_ssf(context_t *text, const sasl_utils_t *utils,
6611fc
+static int gssapi_spnego_ssf(context_t *text,
6611fc
                              sasl_security_properties_t *props,
6611fc
                              sasl_out_params_t *oparams)
6611fc
 {
6611fc
@@ -1019,7 +1019,7 @@ gssapi_server_mech_authneg(context_t *text,
6611fc
 	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
6611fc
 	ret = SASL_OK;
6611fc
     } else if (text->mech_type && text->mech_type == &gss_spnego_oid) {
6611fc
-        ret = gssapi_spnego_ssf(text, params->utils, &params->props, oparams);
6611fc
+        ret = gssapi_spnego_ssf(text, &params->props, oparams);
6611fc
     } else {
6611fc
 	/* Switch to ssf negotiation */
6611fc
 	text->state = SASL_GSSAPI_STATE_SSFCAP;
6611fc
@@ -1825,8 +1825,7 @@ static int gssapi_client_mech_step(void *conn_context,
6611fc
 		return SASL_OK;
6611fc
 	    } else if (text->mech_type && text->mech_type == &gss_spnego_oid) {
6611fc
 		oparams->doneflag = 1;
6611fc
-                return gssapi_spnego_ssf(text, params->utils, &params->props,
6611fc
-                                         oparams);
6611fc
+                return gssapi_spnego_ssf(text, &params->props, oparams);
6611fc
             }
6611fc
 
6611fc
 	    /* Switch to ssf negotiation */
6611fc
6611fc
From 72181257d77bda09afa7d0d640d322c4472f4833 Mon Sep 17 00:00:00 2001
6611fc
From: Simo Sorce <simo@redhat.com>
6611fc
Date: Mon, 10 Apr 2017 18:35:10 -0400
6611fc
Subject: [PATCH 2/3] Check return error from gss_wrap_size_limit()
6611fc
6611fc
The return error of this function is ignored and potentially
6611fc
uninitialized values returned by this function are used.
6611fc
6611fc
Fix this by moving the function into a proper helper as it is used in an
6611fc
identical way in 3 different places.
6611fc
6611fc
Signed-off-by: Simo Sorce <simo@redhat.com>
6611fc
---
6611fc
 plugins/gssapi.c | 104 +++++++++++++++++++++++++++----------------------------
6611fc
 1 file changed, 51 insertions(+), 53 deletions(-)
6611fc
6611fc
diff --git a/plugins/gssapi.c b/plugins/gssapi.c
6611fc
index 3050962e..348debe0 100644
6611fc
--- a/plugins/gssapi.c
6611fc
+++ b/plugins/gssapi.c
6611fc
@@ -648,6 +648,32 @@ static void gssapi_common_mech_free(void *global_context __attribute__((unused))
6611fc
 #endif
6611fc
 }
6611fc
 
6611fc
+static int gssapi_wrap_sizes(context_t *text, sasl_out_params_t *oparams)
6611fc
+{
6611fc
+    OM_uint32 maj_stat = 0, min_stat = 0;
6611fc
+    OM_uint32 max_input = 0;
6611fc
+
6611fc
+    maj_stat = gss_wrap_size_limit(&min_stat,
6611fc
+                                   text->gss_ctx,
6611fc
+                                   1,
6611fc
+                                   GSS_C_QOP_DEFAULT,
6611fc
+                                   (OM_uint32)oparams->maxoutbuf,
6611fc
+                                   &max_input);
6611fc
+   if (maj_stat != GSS_S_COMPLETE) {
6611fc
+       return SASL_FAIL;
6611fc
+   }
6611fc
+
6611fc
+    if (max_input > oparams->maxoutbuf) {
6611fc
+        /* Heimdal appears to get this wrong */
6611fc
+        oparams->maxoutbuf -= (max_input - oparams->maxoutbuf);
6611fc
+    } else {
6611fc
+        /* This code is actually correct */
6611fc
+        oparams->maxoutbuf = max_input;
6611fc
+    }
6611fc
+
6611fc
+    return SASL_OK;
6611fc
+}
6611fc
+
6611fc
 /* The GSS-SPNEGO mechanism does not do SSF negotiation, instead it uses the
6611fc
  * flags negotiated by GSSAPI to determine If confidentiality or integrity are
6611fc
  * used. These flags are stored in text->qop transalated as layers by the
6611fc
@@ -656,8 +682,7 @@ static int gssapi_spnego_ssf(context_t *text,
6611fc
                              sasl_security_properties_t *props,
6611fc
                              sasl_out_params_t *oparams)
6611fc
 {
6611fc
-    OM_uint32 maj_stat = 0, min_stat = 0;
6611fc
-    OM_uint32 max_input;
6611fc
+    int ret;
6611fc
 
6611fc
     if (text->qop & LAYER_CONFIDENTIALITY) {
6611fc
         oparams->encode = &gssapi_privacy_encode;
6611fc
@@ -674,20 +699,10 @@ static int gssapi_spnego_ssf(context_t *text,
6611fc
     }
6611fc
 
6611fc
     if (oparams->mech_ssf) {
6611fc
-        maj_stat = gss_wrap_size_limit(&min_stat,
6611fc
-                                       text->gss_ctx,
6611fc
-                                       1,
6611fc
-                                       GSS_C_QOP_DEFAULT,
6611fc
-                                       (OM_uint32)oparams->maxoutbuf,
6611fc
-                                       &max_input);
6611fc
-
6611fc
-	if (max_input > oparams->maxoutbuf) {
6611fc
-	    /* Heimdal appears to get this wrong */
6611fc
-	    oparams->maxoutbuf -= (max_input - oparams->maxoutbuf);
6611fc
-	} else {
6611fc
-	    /* This code is actually correct */
6611fc
-	    oparams->maxoutbuf = max_input;
6611fc
-	}
6611fc
+        ret = gssapi_wrap_sizes(text, oparams);
6611fc
+        if (ret != SASL_OK) {
6611fc
+            return ret;
6611fc
+        }
6611fc
     }
6611fc
 
6611fc
     text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
6611fc
@@ -1208,7 +1223,6 @@ gssapi_server_mech_ssfreq(context_t *text,
6611fc
     gss_buffer_t input_token, output_token;
6611fc
     gss_buffer_desc real_input_token, real_output_token;
6611fc
     OM_uint32 maj_stat = 0, min_stat = 0;
6611fc
-    OM_uint32 max_input;
6611fc
     int layerchoice;
6611fc
 	
6611fc
     input_token = &real_input_token;
6611fc
@@ -1297,27 +1311,20 @@ gssapi_server_mech_ssfreq(context_t *text,
6611fc
 	(((unsigned char *) output_token->value)[2] << 8) |
6611fc
 	(((unsigned char *) output_token->value)[3] << 0);
6611fc
 
6611fc
-    if (oparams->mech_ssf) {
6611fc
-	maj_stat = gss_wrap_size_limit( &min_stat,
6611fc
-					text->gss_ctx,
6611fc
-					1,
6611fc
-					GSS_C_QOP_DEFAULT,
6611fc
-					(OM_uint32) oparams->maxoutbuf,
6611fc
-					&max_input);
6611fc
-
6611fc
-	if(max_input > oparams->maxoutbuf) {
6611fc
-	    /* Heimdal appears to get this wrong */
6611fc
-	    oparams->maxoutbuf -= (max_input - oparams->maxoutbuf);
6611fc
-	} else {
6611fc
-	    /* This code is actually correct */
6611fc
-	    oparams->maxoutbuf = max_input;
6611fc
-	}    
6611fc
-    }
6611fc
-	
6611fc
     GSS_LOCK_MUTEX_CTX(params->utils, text);
6611fc
     gss_release_buffer(&min_stat, output_token);
6611fc
     GSS_UNLOCK_MUTEX_CTX(params->utils, text);
6611fc
 
6611fc
+    if (oparams->mech_ssf) {
6611fc
+        int ret;
6611fc
+
6611fc
+        ret = gssapi_wrap_sizes(text, oparams);
6611fc
+        if (ret != SASL_OK) {
6611fc
+	    sasl_gss_free_context_contents(text);
6611fc
+            return ret;
6611fc
+        }
6611fc
+    }
6611fc
+
6611fc
     text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
6611fc
 
6611fc
     /* used by layers */
6611fc
@@ -1569,7 +1576,6 @@ static int gssapi_client_mech_step(void *conn_context,
6611fc
     gss_buffer_t input_token, output_token;
6611fc
     gss_buffer_desc real_input_token, real_output_token;
6611fc
     OM_uint32 maj_stat = 0, min_stat = 0;
6611fc
-    OM_uint32 max_input;
6611fc
     gss_buffer_desc name_token;
6611fc
     int ret;
6611fc
     OM_uint32 req_flags = 0, out_req_flags = 0;
6611fc
@@ -1952,27 +1958,19 @@ static int gssapi_client_mech_step(void *conn_context,
6611fc
             (((unsigned char *) output_token->value)[2] << 8) |
6611fc
             (((unsigned char *) output_token->value)[3] << 0);
6611fc
 
6611fc
-	if (oparams->mech_ssf) {
6611fc
-            maj_stat = gss_wrap_size_limit( &min_stat,
6611fc
-                                            text->gss_ctx,
6611fc
-                                            1,
6611fc
-                                            GSS_C_QOP_DEFAULT,
6611fc
-                                            (OM_uint32) oparams->maxoutbuf,
6611fc
-                                            &max_input);
6611fc
-
6611fc
-	    if (max_input > oparams->maxoutbuf) {
6611fc
-		/* Heimdal appears to get this wrong */
6611fc
-		oparams->maxoutbuf -= (max_input - oparams->maxoutbuf);
6611fc
-	    } else {
6611fc
-		/* This code is actually correct */
6611fc
-		oparams->maxoutbuf = max_input;
6611fc
-	    }
6611fc
-	}
6611fc
-	
6611fc
 	GSS_LOCK_MUTEX_CTX(params->utils, text);
6611fc
 	gss_release_buffer(&min_stat, output_token);
6611fc
 	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
6611fc
-	
6611fc
+
6611fc
+	if (oparams->mech_ssf) {
6611fc
+            int ret;
6611fc
+
6611fc
+            ret = gssapi_wrap_sizes(text, oparams);
6611fc
+            if (ret != SASL_OK) {
6611fc
+	        sasl_gss_free_context_contents(text);
6611fc
+                return ret;
6611fc
+            }
6611fc
+	}
6611fc
 	/* oparams->user is always set, due to canon_user requirements.
6611fc
 	 * Make sure the client actually requested it though, by checking
6611fc
 	 * if our context was set.
6611fc
6611fc
From ff9f9caeb6db6d7513128fff9321f9bd445f58b7 Mon Sep 17 00:00:00 2001
6611fc
From: Simo Sorce <simo@redhat.com>
6611fc
Date: Mon, 10 Apr 2017 19:54:19 -0400
6611fc
Subject: [PATCH 3/3] Add support for retrieving the mech_ssf
6611fc
6611fc
In the latest MIT Kerberos implementation it is possible to extract
6611fc
the calculated SSF wich is based on the encryption type that has been
6611fc
used to establish the GSSAPI security context.
6611fc
6611fc
Use this method if available or fall back to the old "DES" value.
6611fc
6611fc
Signed-off-by: Simo Sorce <simo@redhat.com>
6611fc
---
6611fc
 cmulocal/sasl2.m4      |  20 +++++++++++
6611fc
 plugins/gssapi.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++------
6611fc
 2 files changed, 111 insertions(+), 11 deletions(-)
6611fc
6611fc
diff --git a/cmulocal/sasl2.m4 b/cmulocal/sasl2.m4
6611fc
index 66b291b0..686c4bc7 100644
6611fc
--- a/cmulocal/sasl2.m4
6611fc
+++ b/cmulocal/sasl2.m4
6611fc
@@ -290,6 +290,26 @@ if test "$gssapi" != no; then
6611fc
 
6611fc
   cmu_save_LIBS="$LIBS"
6611fc
   LIBS="$LIBS $GSSAPIBASE_LIBS"
6611fc
+  AC_CHECK_FUNCS(gss_inquire_sec_context_by_oid)
6611fc
+  if test "$ac_cv_func_gss_inquire_sec_context_by_oid" = no ; then
6611fc
+    if test "$ac_cv_header_gssapi_gssapi_ext_h" = "yes"; then
6611fc
+      AC_CHECK_DECL(gss_inquire_sec_context_by_oid,
6611fc
+                    [AC_DEFINE(HAVE_GSS_INQUIRE_SEC_CONTEXT_BY_OID,1,
6611fc
+                               [Define if your GSSAPI implementation defines gss_inquire_sec_context_by_oid])],,
6611fc
+                    [
6611fc
+                    AC_INCLUDES_DEFAULT
6611fc
+                    #include <gssapi/gssapi_ext.h>
6611fc
+                    ])
6611fc
+    fi
6611fc
+  fi
6611fc
+  if test "$ac_cv_header_gssapi_gssapi_ext_h" = "yes"; then
6611fc
+    AC_EGREP_HEADER(GSS_C_SEC_CONTEXT_SASL_SSF, gssapi/gssapi_ext.h,
6611fc
+                    [AC_DEFINE(HAVE_GSS_C_SEC_CONTEXT_SASL_SSF,,
6611fc
+                               [Define if your GSSAPI implementation defines GSS_C_SEC_CONTEXT_SASL_SSF])])
6611fc
+  fi
6611fc
+  cmu_save_LIBS="$LIBS"
6611fc
+  LIBS="$LIBS $GSSAPIBASE_LIBS"
6611fc
+
6611fc
   AC_MSG_CHECKING([for SPNEGO support in GSSAPI libraries])
6611fc
   AC_TRY_RUN([
6611fc
 #ifdef HAVE_GSSAPI_H
6611fc
diff --git a/plugins/gssapi.c b/plugins/gssapi.c
6611fc
index 348debe0..5f554ce3 100644
6611fc
--- a/plugins/gssapi.c
6611fc
+++ b/plugins/gssapi.c
6611fc
@@ -51,6 +51,9 @@
6611fc
 #endif
6611fc
 
6611fc
 #include <gssapi/gssapi_krb5.h>
6611fc
+#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
6611fc
+#include <gssapi/gssapi_ext.h>
6611fc
+#endif
6611fc
 
6611fc
 #ifdef WIN32
6611fc
 #  include <winsock2.h>
6611fc
@@ -98,18 +103,25 @@ extern gss_OID gss_nt_service_name;
6611fc
 /* Check if CyberSafe flag is defined */
6611fc
 #ifdef CSF_GSS_C_DES3_FLAG
6611fc
 #define K5_MAX_SSF	112
6611fc
+#define K5_MIN_SSF	112
6611fc
 #endif
6611fc
 
6611fc
 /* Heimdal and MIT use the following */
6611fc
 #ifdef GSS_KRB5_CONF_C_QOP_DES3_KD
6611fc
 #define K5_MAX_SSF	112
6611fc
+#define K5_MIN_SSF	112
6611fc
 #endif
6611fc
 
6611fc
 #endif
6611fc
 
6611fc
 #ifndef K5_MAX_SSF
6611fc
+/* All modern Kerberos implementations support AES */
6611fc
+#define K5_MAX_SSF	256
6611fc
+#endif
6611fc
+
6611fc
 /* All Kerberos implementations support DES */
6611fc
-#define K5_MAX_SSF	56
6611fc
+#ifndef K5_MIN_SSF
6611fc
+#define K5_MIN_SSF      56
6611fc
 #endif
6611fc
 
6611fc
 /* GSSAPI SASL Mechanism by Leif Johansson <leifj@matematik.su.se>
6611fc
@@ -674,6 +686,47 @@ static int gssapi_wrap_sizes(context_t *text, sasl_out_params_t *oparams)
6611fc
     return SASL_OK;
6611fc
 }
6611fc
 
6611fc
+#if !defined(HAVE_GSS_C_SEC_CONTEXT_SASL_SSF)
6611fc
+gss_OID_desc gss_sasl_ssf = {
6611fc
+    11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"
6611fc
+};
6611fc
+gss_OID GSS_C_SEC_CONTEXT_SASL_SSF = &gss_sasl_ssf;
6611fc
+#endif
6611fc
+
6611fc
+static int gssapi_get_ssf(context_t *text, sasl_ssf_t *mech_ssf)
6611fc
+{
6611fc
+#ifdef HAVE_GSS_INQUIRE_SEC_CONTEXT_BY_OID
6611fc
+    OM_uint32 maj_stat = 0, min_stat = 0;
6611fc
+    gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET;
6611fc
+    gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF;
6611fc
+    uint32_t ssf;
6611fc
+
6611fc
+    maj_stat = gss_inquire_sec_context_by_oid(&min_stat, text->gss_ctx,
6611fc
+                                              ssf_oid, &bufset);
6611fc
+    switch (maj_stat) {
6611fc
+    case GSS_S_UNAVAILABLE:
6611fc
+        /* Not supported by the library, fallback to default */
6611fc
+        goto fallback;
6611fc
+    case GSS_S_COMPLETE:
6611fc
+        if ((bufset->count != 1) || (bufset->elements[0].length != 4)) {
6611fc
+            /* Malformed bufset, fail */
6611fc
+            (void)gss_release_buffer_set(&min_stat, &bufset);
6611fc
+            return SASL_FAIL;
6611fc
+        }
6611fc
+        memcpy(&ssf, bufset->elements[0].value, 4);
6611fc
+        (void)gss_release_buffer_set(&min_stat, &bufset);
6611fc
+        *mech_ssf = ntohl(ssf);
6611fc
+        return SASL_OK;
6611fc
+    default:
6611fc
+        return SASL_FAIL;
6611fc
+    }
6611fc
+
6611fc
+fallback:
6611fc
+#endif
6611fc
+    *mech_ssf = K5_MIN_SSF;
6611fc
+    return SASL_OK;
6611fc
+}
6611fc
+
6611fc
 /* The GSS-SPNEGO mechanism does not do SSF negotiation, instead it uses the
6611fc
  * flags negotiated by GSSAPI to determine If confidentiality or integrity are
6611fc
  * used. These flags are stored in text->qop transalated as layers by the
6611fc
@@ -687,7 +740,10 @@ static int gssapi_spnego_ssf(context_t *text,
6611fc
     if (text->qop & LAYER_CONFIDENTIALITY) {
6611fc
         oparams->encode = &gssapi_privacy_encode;
6611fc
         oparams->decode = &gssapi_decode;
6611fc
-        oparams->mech_ssf = K5_MAX_SSF;
6611fc
+        ret = gssapi_get_ssf(text, &oparams->mech_ssf);
6611fc
+        if (ret != SASL_OK) {
6611fc
+            return ret;
6611fc
+        }
6611fc
     } else if (text->qop & LAYER_INTEGRITY) {
6611fc
         oparams->encode = &gssapi_integrity_encode;
6611fc
         oparams->decode = &gssapi_decode;
6611fc
@@ -1089,6 +1145,7 @@ gssapi_server_mech_ssfcap(context_t *text,
6611fc
     gss_buffer_desc real_input_token, real_output_token;
6611fc
     OM_uint32 maj_stat = 0, min_stat = 0;
6611fc
     unsigned char sasldata[4];
6611fc
+    sasl_ssf_t mech_ssf;
6611fc
     int ret;
6611fc
 
6611fc
     input_token = &real_input_token;
6611fc
@@ -1149,9 +1206,14 @@ gssapi_server_mech_ssfcap(context_t *text,
6611fc
 	params->props.maxbufsize) {
6611fc
 	sasldata[0] |= LAYER_INTEGRITY;
6611fc
     }
6611fc
+    ret = gssapi_get_ssf(text, &mech_ssf);
6611fc
+    if (ret != SASL_OK) {
6611fc
+	sasl_gss_free_context_contents(text);
6611fc
+        return ret;
6611fc
+    }
6611fc
     if ((text->qop & LAYER_CONFIDENTIALITY) &&
6611fc
-	text->requiressf <= K5_MAX_SSF &&
6611fc
-	text->limitssf >= K5_MAX_SSF &&
6611fc
+	text->requiressf <= mech_ssf &&
6611fc
+	text->limitssf >= mech_ssf &&
6611fc
 	params->props.maxbufsize) {
6611fc
 	sasldata[0] |= LAYER_CONFIDENTIALITY;
6611fc
     }
6611fc
@@ -1271,10 +1333,18 @@ gssapi_server_mech_ssfreq(context_t *text,
6611fc
 	} else if (/* For compatibility with broken clients setting both bits */
6611fc
 		   (layerchoice & (LAYER_CONFIDENTIALITY | LAYER_INTEGRITY)) &&
6611fc
 	       (text->qop & LAYER_CONFIDENTIALITY)) { /* privacy */
6611fc
+        int ret;
6611fc
 	oparams->encode = &gssapi_privacy_encode;
6611fc
 	oparams->decode = &gssapi_decode;
6611fc
-	/* FIX ME: Need to extract the proper value here */
6611fc
-	oparams->mech_ssf = K5_MAX_SSF;
6611fc
+
6611fc
+	ret = gssapi_get_ssf(text, &oparams->mech_ssf);
6611fc
+        if (ret != SASL_OK) {
6611fc
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
6611fc
+	    gss_release_buffer(&min_stat, output_token);
6611fc
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
6611fc
+	    sasl_gss_free_context_contents(text);
6611fc
+	    return ret;
6611fc
+	}
6611fc
     } else {
6611fc
 	/* not a supported encryption layer */
6611fc
 	SETERROR(text->utils,
6611fc
@@ -1845,6 +1915,8 @@ static int gssapi_client_mech_step(void *conn_context,
6611fc
 	unsigned int alen, external = params->external_ssf;
6611fc
 	sasl_ssf_t need, allowed;
6611fc
 	char serverhas, mychoice;
6611fc
+	sasl_ssf_t mech_ssf;
6611fc
+	int ret;
6611fc
 	
6611fc
 	real_input_token.value = (void *) serverin;
6611fc
 	real_input_token.length = serverinlen;
6611fc
@@ -1879,8 +1951,17 @@ static int gssapi_client_mech_step(void *conn_context,
6611fc
 	    return SASL_FAIL;
6611fc
 	}
6611fc
 
6611fc
+	ret = gssapi_get_ssf(text, &mech_ssf);
6611fc
+	if (ret != SASL_OK) {
6611fc
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
6611fc
+	    gss_release_buffer(&min_stat, output_token);
6611fc
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
6611fc
+	    sasl_gss_free_context_contents(text);
6611fc
+	    return SASL_FAIL;
6611fc
+	}
6611fc
+
6611fc
 	/* taken from kerberos.c */
6611fc
-	if (secprops->min_ssf > (K5_MAX_SSF + external)) {
6611fc
+	if (secprops->min_ssf > (mech_ssf + external)) {
6611fc
 	    return SASL_TOOWEAK;
6611fc
 	} else if (secprops->min_ssf > secprops->max_ssf) {
6611fc
 	    return SASL_BADPARAM;
6611fc
@@ -1904,8 +1985,8 @@ static int gssapi_client_mech_step(void *conn_context,
6611fc
 	
6611fc
 	/* use the strongest layer available */
6611fc
 	if ((text->qop & LAYER_CONFIDENTIALITY) &&
6611fc
-	    allowed >= K5_MAX_SSF &&
6611fc
-	    need <= K5_MAX_SSF &&
6611fc
+	    allowed >= mech_ssf &&
6611fc
+	    need <= mech_ssf &&
6611fc
 	    (serverhas & LAYER_CONFIDENTIALITY)) {
6611fc
 	    
6611fc
 	    const char *ad_compat;
6611fc
@@ -1913,8 +1994,7 @@ static int gssapi_client_mech_step(void *conn_context,
6611fc
 	    /* encryption */
6611fc
 	    oparams->encode = &gssapi_privacy_encode;
6611fc
 	    oparams->decode = &gssapi_decode;
6611fc
-	    /* FIX ME: Need to extract the proper value here */
6611fc
-	    oparams->mech_ssf = K5_MAX_SSF;
6611fc
+	    oparams->mech_ssf = mech_ssf;
6611fc
 	    mychoice = LAYER_CONFIDENTIALITY;
6611fc
 
6611fc
 	    if (serverhas & LAYER_INTEGRITY) {
6611fc
6611fc
6611fc
6611fc
diff -U3 cyrus-sasl-2.1.26.old/config.h.in cyrus-sasl-2.1.26/config.h.in
6611fc
--- cyrus-sasl-2.1.26.old/config.h.in   2012-11-06 20:20:59.000000000 +0100
6611fc
+++ cyrus-sasl-2.1.26/config.h.in       2017-09-21 10:33:36.225258244 +0200
6611fc
@@ -132,6 +135,9 @@
6611fc
 /* Define if your GSSAPI implementation defines GSS_C_NT_USER_NAME */
6611fc
 #undef HAVE_GSS_C_NT_USER_NAME
6611fc
 
6611fc
+/* Define if your GSSAPI implementation defines GSS_C_SEC_CONTEXT_SASL_SSF */
6611fc
+#undef HAVE_GSS_C_SEC_CONTEXT_SASL_SSF
6611fc
+
6611fc
 /* Define to 1 if you have the `gss_decapsulate_token' function. */
6611fc
 #undef HAVE_GSS_DECAPSULATE_TOKEN
6611fc
 
6611fc
@@ -141,6 +147,10 @@
6611fc
 /* Define to 1 if you have the `gss_get_name_attribute' function. */
6611fc
 #undef HAVE_GSS_GET_NAME_ATTRIBUTE
6611fc
 
6611fc
+/* Define if your GSSAPI implementation defines gss_inquire_sec_context_by_oid
6611fc
+   */
6611fc
+#undef HAVE_GSS_INQUIRE_SEC_CONTEXT_BY_OID
6611fc
+
6611fc
 /* Define to 1 if you have the `gss_oid_equal' function. */
6611fc
 #undef HAVE_GSS_OID_EQUAL
6611fc
 
6611fc
diff -U3 cyrus-sasl-2.1.26.old/configure cyrus-sasl-2.1.26/configure
6611fc
--- cyrus-sasl-2.1.26.old/configure     2017-09-21 10:11:30.557021831 +0200
6611fc
+++ cyrus-sasl-2.1.26/configure 2017-09-21 10:33:40.389277838 +0200
6611fc
@@ -13984,6 +13984,50 @@
6611fc
 
6611fc
   LIBS="$cmu_save_LIBS"
6611fc
 
6611fc
+  cmu_save_LIBS="$LIBS"
6611fc
+  LIBS="$LIBS $GSSAPIBASE_LIBS"
6611fc
+  for ac_func in gss_inquire_sec_context_by_oid
6611fc
+do :
6611fc
+  ac_fn_c_check_func "$LINENO" "gss_inquire_sec_context_by_oid" "ac_cv_func_gss_inquire_sec_context_by_oid"
6611fc
+if test "x$ac_cv_func_gss_inquire_sec_context_by_oid" = xyes; then :
6611fc
+  cat >>confdefs.h <<_ACEOF
6611fc
+#define HAVE_GSS_INQUIRE_SEC_CONTEXT_BY_OID 1
6611fc
+_ACEOF
6611fc
+
6611fc
+fi
6611fc
+done
6611fc
+
6611fc
+  if test "$ac_cv_func_gss_inquire_sec_context_by_oid" = no ; then
6611fc
+    if test "$ac_cv_header_gssapi_gssapi_ext_h" = "yes"; then
6611fc
+      ac_fn_c_check_decl "$LINENO" "gss_inquire_sec_context_by_oid" "ac_cv_have_decl_gss_inquire_sec_context_by_oid" "
6611fc
+                    $ac_includes_default
6611fc
+                    #include <gssapi/gssapi_ext.h>
6611fc
+
6611fc
+"
6611fc
+if test "x$ac_cv_have_decl_gss_inquire_sec_context_by_oid" = xyes; then :
6611fc
+
6611fc
+$as_echo "#define HAVE_GSS_INQUIRE_SEC_CONTEXT_BY_OID 1" >>confdefs.h
6611fc
+
6611fc
+fi
6611fc
+
6611fc
+    fi
6611fc
+  fi
6611fc
+  if test "$ac_cv_header_gssapi_gssapi_ext_h" = "yes"; then
6611fc
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
6611fc
+/* end confdefs.h.  */
6611fc
+#include <gssapi/gssapi_ext.h>
6611fc
+
6611fc
+_ACEOF
6611fc
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
6611fc
+  $EGREP "GSS_C_SEC_CONTEXT_SASL_SSF" >/dev/null 2>&1; then :
6611fc
+
6611fc
+$as_echo "#define HAVE_GSS_C_SEC_CONTEXT_SASL_SSF /**/" >>confdefs.h
6611fc
+
6611fc
+fi
6611fc
+rm -f conftest*
6611fc
+
6611fc
+  fi
6611fc
+
6611fc
   cmu_save_LIBS="$LIBS"
6611fc
   LIBS="$LIBS $GSSAPIBASE_LIBS"
6611fc
   { $as_echo "$as_me:$LINENO: checking for SPNEGO support in GSSAPI libraries" >&5