components/krb5/patches/024-smb-compat.patch
changeset 5490 9bf0bc57423a
child 5562 880dc66054d5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/patches/024-smb-compat.patch	Wed Feb 24 10:43:57 2016 -0600
@@ -0,0 +1,183 @@
+#
+# 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 -pur old/src/lib/gssapi/krb5/accept_sec_context.c new/src/lib/gssapi/krb5/accept_sec_context.c
+--- old/src/lib/gssapi/krb5/accept_sec_context.c	2015-03-30 23:53:08.814324223 -0600
++++ new/src/lib/gssapi/krb5/accept_sec_context.c	2015-04-02 00:05:08.243563972 -0600
+@@ -1226,6 +1226,35 @@ fail:
+          */
+         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")) {
++            char *ms_e_data = "\x30\x05\xa1\x03\x02\x01\x02";
++            int len = strlen(ms_e_data);
++
++            krb_error_data.e_data.data = malloc(len);
++            if (krb_error_data.e_data.data) {
++                (void) memcpy(krb_error_data.e_data.data, ms_e_data, len);
++                krb_error_data.e_data.length = len;
++            }
++            major_status = GSS_S_CONTINUE_NEEDED;
++        }
++
+         code -= ERROR_TABLE_BASE_krb5;
+         if (code < 0 || code > KRB_ERR_MAX)
+             code = 60 /* KRB_ERR_GENERIC */;
+diff -pur old/src/lib/gssapi/spnego/spnego_mech.c new/src/lib/gssapi/spnego/spnego_mech.c
+--- old/src/lib/gssapi/spnego/spnego_mech.c	2015-03-30 23:53:08.816648991 -0600
++++ new/src/lib/gssapi/spnego/spnego_mech.c	2015-04-15 18:52:40.053965732 -0600
+@@ -190,6 +190,13 @@ static const gss_OID_set_desc spnego_oid
+ };
+ 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
+@@ -1243,7 +1250,7 @@ make_NegHints(OM_uint32 *minor_status,
+ 					&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);
+@@ -1386,6 +1393,7 @@ acc_ctx_new(OM_uint32 *minor_status,
+ 	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;
+@@ -1409,6 +1417,24 @@ acc_ctx_new(OM_uint32 *minor_status,
+ 		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.
+@@ -2989,6 +3015,7 @@ get_available_mechs(OM_uint32 *minor_sta
+ 	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);
+ 
+@@ -3003,6 +3030,15 @@ get_available_mechs(OM_uint32 *minor_sta
+ 		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) ||
+@@ -3018,6 +3054,25 @@ get_available_mechs(OM_uint32 *minor_sta
+ 		}
+ 	}
+ 
++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
+@@ -3593,9 +3648,17 @@ negotiate_mech(gss_OID_set supported, gs
+ 	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])) {