components/krb5/patches/024-smb-compat.patch
author Will Fiveash <will.fiveash@oracle.com>
Mon, 07 Mar 2016 17:03:48 -0600
changeset 5562 880dc66054d5
parent 5490 9bf0bc57423a
child 5969 96bac9fbcfbd
permissions -rw-r--r--
22736580 smbtorture memleak in kg_accept_krb5

#
# This patch allows for better interop with MS Windows clients accessing Solaris
# SMB services.  It fixes a few memory leaks and double frees found during SMB
# stress testing.  The CRs in order:
#
# 15580724 SUNBT6868908 Solaris acceptors should have returned KRB5KRB_AP_...
# 15648322 SUNBT6959251 coredump in gss_release_name+0x36
# 20416772 spnego_gss_accept_sec_context issue with incorrect KRB OID
# 16005842 Should retry SMB authentication upgrade to account for network...
# 15579598 SUNBT6867208 Windows client cannot recover from KRB5KRB_AP_ERR_SKEW..
#
# Note: MIT tickets will subsequently be filed, but the solution may differ from
# what we currently offer in Solaris, because they may want the changes as the
# default behavior therefore removing the dependency on the MS_INTEROP
# environment variable.
# Patch source: in-house
#
diff -ur krb5-1.13.3.023-mem-rcache.patch/src/lib/gssapi/krb5/accept_sec_context.c krb5-1.13.3/src/lib/gssapi/krb5/accept_sec_context.c
--- krb5-1.13.3.023-mem-rcache.patch/src/lib/gssapi/krb5/accept_sec_context.c
+++ krb5-1.13.3/src/lib/gssapi/krb5/accept_sec_context.c
@@ -460,8 +460,6 @@
     const gss_OID_desc *mech_used = NULL;
     OM_uint32 major_status = GSS_S_FAILURE;
     OM_uint32 tmp_minor_status;
-    krb5_error krb_error_data;
-    krb5_data scratch;
     gss_cred_id_t defcred = GSS_C_NO_CREDENTIAL;
     krb5_gss_cred_id_t deleg_cred = NULL;
     krb5int_access kaccess;
@@ -1219,6 +1217,8 @@
          major_status == GSS_S_CONTINUE_NEEDED)) {
         unsigned int tmsglen;
         int toktype;
+        krb5_data scratch;
+        krb5_error krb_error_data;
 
         /*
          * The client is expecting a response, so we can send an
@@ -1226,6 +1226,31 @@
          */
         memset(&krb_error_data, 0, sizeof(krb_error_data));
 
+        /*
+         * We need to remap error conditions for buggy Windows clients if the
+	 * MS_INTEROP env var has been set.
+         */
+        if ((code == KRB5KRB_AP_ERR_BAD_INTEGRITY ||
+             code == KRB5KRB_AP_ERR_NOKEY || code == KRB5KRB_AP_ERR_BADKEYVER)
+            && getenv("MS_INTEROP")) {
+            code = KRB5KRB_AP_ERR_MODIFIED;
+            major_status = GSS_S_CONTINUE_NEEDED;
+        }
+
+        /*
+         * Set e-data to Windows constant (verified by MSFT).
+         *
+         * This facilitates the Windows CIFS client clock skew
+         * recovery feature.
+         */
+        if (code == KRB5KRB_AP_ERR_SKEW && getenv("MS_INTEROP")) {
+            /* Note that free() must not be called on
+             * krb_error_data.e_data.data */
+            krb_error_data.e_data.data = "\x30\x05\xa1\x03\x02\x01\x02";
+            krb_error_data.e_data.length = 7;
+            major_status = GSS_S_CONTINUE_NEEDED;
+        }
+
         code -= ERROR_TABLE_BASE_krb5;
         if (code < 0 || code > KRB_ERR_MAX)
             code = 60 /* KRB_ERR_GENERIC */;
diff -ur krb5-1.13.3.023-mem-rcache.patch/src/lib/gssapi/spnego/spnego_mech.c krb5-1.13.3/src/lib/gssapi/spnego/spnego_mech.c
--- krb5-1.13.3.023-mem-rcache.patch/src/lib/gssapi/spnego/spnego_mech.c
+++ krb5-1.13.3/src/lib/gssapi/spnego/spnego_mech.c
@@ -190,6 +190,13 @@
 };
 const gss_OID_set_desc * const gss_mech_set_spnego = spnego_oidsets+0;
 
+/* encoded OID octet string for NTLMSSP security mechanism */
+#define GSS_MECH_NTLMSSP_OID_LENGTH 10
+#define GSS_MECH_NTLMSSP_OID "\053\006\001\004\001\202\067\002\002\012"
+static gss_OID_desc ntlmssp_oid = {
+	GSS_MECH_NTLMSSP_OID_LENGTH, GSS_MECH_NTLMSSP_OID
+};
+
 static int make_NegHints(OM_uint32 *, spnego_gss_cred_id_t, gss_buffer_t *);
 static int put_neg_hints(unsigned char **, gss_buffer_t, unsigned int);
 static OM_uint32
@@ -1237,7 +1244,7 @@
 					&hintNameBuf,
 					&hintNameType);
 	if (major_status != GSS_S_COMPLETE) {
-		gss_release_name(&minor, &hintName);
+		gss_release_name(&minor, &hintKerberosName);
 		return (major_status);
 	}
 	gss_release_name(&minor, &hintKerberosName);
@@ -1380,6 +1387,7 @@
 	gss_buffer_desc der_mechTypes;
 	gss_OID mech_wanted;
 	spnego_gss_ctx_id_t sc = NULL;
+	unsigned int i;
 
 	ret = GSS_S_DEFECTIVE_TOKEN;
 	der_mechTypes.length = 0;
@@ -1403,6 +1411,24 @@
 		goto cleanup;
 	}
 	/*
+	 * We add KRB5_WRONG here so that old MS clients can negotiate this
+	 * mechanism, which allows extensions in Kerberos (clock skew
+	 * adjustment, refresh ccache).
+	 */
+	for (i = 0; i < supported_mechSet->count; i++) {
+		if (is_kerb_mech(&supported_mechSet->elements[i])) {
+			extern gss_OID_desc * const gss_mech_krb5_wrong;
+			ret = gss_add_oid_set_member(minor_status,
+			    			     gss_mech_krb5_wrong,
+						     &supported_mechSet);
+			if (ret != GSS_S_COMPLETE) {
+				*return_token = NO_TOKEN_SEND;
+				goto cleanup;
+			}
+			break;
+		}
+        }
+	/*
 	 * Select the best match between the list of mechs
 	 * that the initiator requested and the list that
 	 * the acceptor will support.
@@ -3136,6 +3162,7 @@
 	int		found = 0;
 	OM_uint32 major_status = GSS_S_COMPLETE, tmpmin;
 	gss_OID_set mechs, goodmechs;
+	char *msinterop = getenv("MS_INTEROP");
 
 	major_status = gss_indicate_mechs(minor_status, &mechs);
 
@@ -3150,6 +3177,15 @@
 		return (major_status);
 	}
 
+	/*
+	 * If the required keytab entries for Kerberized SMB service are
+	 * missing due to an SMB authentication upgrade failure, SMB daemon
+	 * will set MS_INTEROP environmment variable to 1 to ensure only
+	 * NTLMSSP security mech is used for negotiation.
+	 */
+	if ((msinterop != NULL) && (!strcmp(msinterop, "1")))
+		goto ntlmssp;
+
 	for (i = 0; i < mechs->count && major_status == GSS_S_COMPLETE; i++) {
 		if ((mechs->elements[i].length
 		    != spnego_mechanism.mech_type.length) ||
@@ -3165,6 +3201,25 @@
 		}
 	}
 
+ntlmssp:
+	/*
+	 * Add NTLMSSP OID to the mech OID set only if MS_INTEROP env var has
+	 * been set to:
+	 * - "1" (NTLMSSP only) or
+	 * - "2" (both Krb5 and NTLMSSP)
+	 *
+	 * This is a requirement until NTLMSSP is implemented as a GSS-API
+	 * plugin.
+	 */
+	if ((msinterop != NULL) &&
+	    (!strcmp(msinterop, "1") || !strcmp(msinterop, "2"))) {
+		major_status = gss_add_oid_set_member(minor_status,
+		    &ntlmssp_oid, rmechs);
+
+		if (major_status == GSS_S_COMPLETE)
+			found++;
+	}
+
 	/*
 	 * If the caller wanted a list of creds returned,
 	 * trim the list of mechanisms down to only those
@@ -3740,9 +3795,17 @@
 	for (i = 0; i < received->count; i++) {
 		gss_OID mech_oid = &received->elements[i];
 
+		/*
+		 * MIT compares against MS' wrong OID, but we actually want to
+		 * select it if the client supports, as this will enable
+		 * features on MS clients that allow credential refresh on
+		 * rekeying and caching system times from servers.
+		 */
+#if 0
 		/* Accept wrong mechanism OID from MS clients */
 		if (g_OID_equal(mech_oid, &gss_mech_krb5_wrong_oid))
 			mech_oid = (gss_OID)&gss_mech_krb5_oid;
+#endif
 
 		for (j = 0; j < supported->count; j++) {
 			if (g_OID_equal(mech_oid, &supported->elements[j])) {