#
# 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])) {