[krb5/f19] Backport fix for RT#7858

Nalin Dahyabhai nalin at fedoraproject.org
Tue Feb 18 02:08:09 UTC 2014


commit 16cb10e39e1addb7e668d5ffb2e4930e374813d9
Author: Nalin Dahyabhai <nalin at dahyabhai.net>
Date:   Mon Feb 17 21:06:41 2014 -0500

    Backport fix for RT#7858
    
    - spnego: pull in patch from master to restore preserving the OID of the
      mechanism the initiator requested when we have multiple OIDs for the
      same mechanism, so that we reply using the same mechanism OID and the
      initiator doesn't get confused (#1066000, RT#7858)

 krb5-1.11-spnego-preserve-oid.patch |  171 +++++++++++++++++++++++++++++++++++
 krb5.spec                           |   12 +++-
 2 files changed, 182 insertions(+), 1 deletions(-)
---
diff --git a/krb5-1.11-spnego-preserve-oid.patch b/krb5-1.11-spnego-preserve-oid.patch
new file mode 100644
index 0000000..619a64c
--- /dev/null
+++ b/krb5-1.11-spnego-preserve-oid.patch
@@ -0,0 +1,171 @@
+Adjusted to apply to 1.11.5.
+
+commit 8255613476d4c1583a5e810b50444f188fde871f
+Author: Greg Hudson <ghudson at mit.edu>
+Date:   Mon Feb 3 21:11:34 2014 -0500
+
+    Properly reflect MS krb5 mech in SPNEGO acceptor
+    
+    r25590 changed negotiate_mech() to return an alias into the acceptor's
+    mech set, with the unfortunate side effect of transforming the
+    erroneous Microsoft krb5 mech OID into the correct krb5 mech OID,
+    meaning that we answer with a different OID than the requested one.
+    Return an alias into the initiator's mech set instead, and store that
+    in mech_set field the SPNEGO context.  The acceptor code only uses
+    mech_set to hold the allocated storage pointed into by internal_mech,
+    so this change is safe.
+    
+    ticket: 7858
+    target_version: 1.12.2
+    tags: pullup
+
+diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
+index 7e4bf90..7529c74 100644
+--- a/src/lib/gssapi/spnego/spnego_mech.c
++++ b/src/lib/gssapi/spnego/spnego_mech.c
+@@ -1388,8 +1388,8 @@ acc_ctx_new(OM_uint32 *minor_status,
+ 		*return_token = NO_TOKEN_SEND;
+ 		goto cleanup;
+ 	}
+-	sc->mech_set = supported_mechSet;
+-	supported_mechSet = GSS_C_NO_OID_SET;
++	sc->mech_set = mechTypes;
++	mechTypes = GSS_C_NO_OID_SET;
+ 	sc->internal_mech = mech_wanted;
+ 	sc->DER_mechTypes = der_mechTypes;
+ 	der_mechTypes.length = 0;
+@@ -3538,7 +3538,7 @@ put_negResult(unsigned char **buf_out, OM_uint32 negResult,
+  * is set to ACCEPT_INCOMPLETE if it's the first mech, REQUEST_MIC if
+  * it's not the first mech, otherwise we return NULL and negResult
+  * is set to REJECT. The returned pointer is an alias into
+- * supported->elements and should not be freed.
++ * received->elements and should not be freed.
+  *
+  * NOTE: There is currently no way to specify a preference order of
+  * mechanisms supported by the acceptor.
+@@ -3560,7 +3560,7 @@ negotiate_mech(gss_OID_set supported, gss_OID_set received,
+ 			if (g_OID_equal(mech_oid, &supported->elements[j])) {
+ 				*negResult = (i == 0) ? ACCEPT_INCOMPLETE :
+ 					REQUEST_MIC;
+-				return &supported->elements[j];
++				return &received->elements[i];
+ 			}
+ 		}
+ 	}
+
+commit 53cfb8327c452bd72a8e915338fb5ec838079cd3
+Author: Greg Hudson <ghudson at mit.edu>
+Date:   Mon Feb 3 20:59:54 2014 -0500
+
+    Test SPNEGO acceptor response to MS krb5 mech OID
+    
+    In t_spnego.c, add code to make a SPNEGO request with the erroneous
+    Microsoft OID value and examine the response to make sure that it uses
+    the same OID value as the request did.  The token and tmp variables
+    were unused, so rename them to itok and atok for the purpose of the
+    new test code.
+    
+    ticket: 7858
+    target_version: 1.12.2
+    tags: pullup
+
+diff --git a/src/tests/gssapi/t_spnego.c b/src/tests/gssapi/t_spnego.c
+index cbf720b..ca05848 100644
+--- a/src/tests/gssapi/t_spnego.c
++++ b/src/tests/gssapi/t_spnego.c
+@@ -27,9 +27,15 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <assert.h>
+ 
+ #include "common.h"
+ 
++static gss_OID_desc mech_krb5_wrong = {
++    9, "\052\206\110\202\367\022\001\002\002"
++};
++gss_OID_set_desc mechset_krb5_wrong = { 1, &mech_krb5_wrong };
++
+ /*
+  * Test program for SPNEGO and gss_set_neg_mechs
+  *
+@@ -44,13 +50,16 @@ main(int argc, char *argv[])
+ {
+     OM_uint32 minor, major;
+     gss_cred_id_t verifier_cred_handle = GSS_C_NO_CREDENTIAL;
++    gss_cred_id_t initiator_cred_handle = GSS_C_NO_CREDENTIAL;
+     gss_OID_set actual_mechs = GSS_C_NO_OID_SET;
+     gss_buffer_desc token = GSS_C_EMPTY_BUFFER, tmp = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok = GSS_C_EMPTY_BUFFER;
+     gss_ctx_id_t initiator_context = GSS_C_NO_CONTEXT;
+     gss_ctx_id_t acceptor_context = GSS_C_NO_CONTEXT;
+     gss_name_t target_name, source_name = GSS_C_NO_NAME;
+     OM_uint32 time_rec;
+     gss_OID mech = GSS_C_NO_OID;
++    const unsigned char *atok_oid;
+ 
+     if (argc < 2 || argc > 3) {
+         fprintf(stderr, "Usage: %s target_name [keytab]\n", argv[0]);
+@@ -83,10 +91,59 @@ main(int argc, char *argv[])
+ 
+     (void)gss_delete_sec_context(&minor, &acceptor_context, NULL);
+     (void)gss_release_name(&minor, &source_name);
+-    (void)gss_release_name(&minor, &target_name);
+-    (void)gss_release_buffer(&minor, &token);
+-    (void)gss_release_buffer(&minor, &tmp);
+     (void)gss_release_cred(&minor, &verifier_cred_handle);
+     (void)gss_release_oid_set(&minor, &actual_mechs);
++
++    /*
++     * Test that the SPNEGO acceptor code properly reflects back the erroneous
++     * Microsoft mech OID in the supportedMech field of the NegTokenResp
++     * message.  Our initiator code doesn't care (it treats all variants of the
++     * krb5 mech as equivalent when comparing the supportedMech response to its
++     * first-choice mech), so we have to look directly at the DER encoding of
++     * the response token.  If we don't request mutual authentication, the
++     * SPNEGO reply will contain no underlying mech token, so the encoding of
++     * the correct NegotiationToken response is completely predictable:
++     *
++     *   A1 14 (choice 1, length 20, meaning negTokenResp)
++     *     30 12 (sequence, length 18)
++     *       A0 03 (context tag 0, length 3)
++     *         0A 01 00 (enumerated value 0, meaning accept-completed)
++     *       A1 0B (context tag 1, length 11)
++     *         06 09 (object identifier, length 9)
++     *            2A 86 48 82 F7 12 01 02 02 (the erroneous krb5 OID)
++     *
++     * So we can just compare the length to 22 and the nine bytes at offset 13
++     * to the expected OID.
++     */
++    major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
++                             &mechset_spnego, GSS_C_INITIATE,
++                             &initiator_cred_handle, NULL, NULL);
++    check_gsserr("gss_acquire_cred(2)", major, minor);
++    major = gss_set_neg_mechs(&minor, initiator_cred_handle,
++                              &mechset_krb5_wrong);
++    check_gsserr("gss_set_neg_mechs(2)", major, minor);
++    major = gss_init_sec_context(&minor, initiator_cred_handle,
++                                 &initiator_context, target_name, &mech_spnego,
++                                 GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG,
++                                 GSS_C_INDEFINITE,
++                                 GSS_C_NO_CHANNEL_BINDINGS, &atok, NULL, &itok,
++                                 NULL, NULL);
++    check_gsserr("gss_init_sec_context", major, minor);
++    assert(major == GSS_S_CONTINUE_NEEDED);
++    major = gss_accept_sec_context(&minor, &acceptor_context,
++                                   GSS_C_NO_CREDENTIAL, &itok,
++                                   GSS_C_NO_CHANNEL_BINDINGS, NULL,
++                                   NULL, &atok, NULL, NULL, NULL);
++    assert(atok.length == 22);
++    atok_oid = (unsigned char *)atok.value + 13;
++    assert(memcmp(atok_oid, mech_krb5_wrong.elements, 9) == 0);
++    check_gsserr("gss_accept_sec_context", major, minor);
++
++    (void)gss_delete_sec_context(&minor, &initiator_context, NULL);
++    (void)gss_delete_sec_context(&minor, &acceptor_context, NULL);
++    (void)gss_release_cred(&minor, &initiator_cred_handle);
++    (void)gss_release_name(&minor, &target_name);
++    (void)gss_release_buffer(&minor, &itok);
++    (void)gss_release_buffer(&minor, &atok);
+     return 0;
+ }
diff --git a/krb5.spec b/krb5.spec
index daa9b0e..408dff8 100644
--- a/krb5.spec
+++ b/krb5.spec
@@ -32,7 +32,7 @@
 Summary: The Kerberos network authentication system
 Name: krb5
 Version: 1.11.3
-Release: 20%{?dist}
+Release: 21%{?dist}
 # Maybe we should explode from the now-available-to-everybody tarball instead?
 # http://web.mit.edu/kerberos/dist/krb5/1.11/krb5-1.11.3-signed.tar
 Source0: krb5-%{version}.tar.gz
@@ -118,6 +118,8 @@ Patch155: krb5-master-empty-credstore.patch
 Patch156: krb5-1.11.3-1.12.1-credstoretest.patch
 Patch157: krb5-1.11-rcache-acquirecred-test.patch
 
+Patch158: krb5-1.11-spnego-preserve-oid.patch
+
 # Patches for otp plugin backport
 Patch201: krb5-1.11.2-keycheck.patch
 Patch202: krb5-1.11.2-otp.patch
@@ -389,6 +391,8 @@ ln -s NOTICE LICENSE
 %patch156 -p1 -b .credstoretest
 %patch157 -p1 -b .rcache-acquirecred-test
 
+%patch158 -p1 -b .spnego-preserve-oid
+
 %patch201 -p1 -b .keycheck
 %patch202 -p1 -b .otp
 %patch203 -p1 -b .otp2
@@ -982,6 +986,12 @@ exit 0
 %{_sbindir}/uuserver
 
 %changelog
+* Mon Feb 17 2014 Nalin Dahyabhai <nalin at redhat.com> - 1.11.3-21
+- spnego: pull in patch from master to restore preserving the OID of the
+  mechanism the initiator requested when we have multiple OIDs for the same
+  mechanism, so that we reply using the same mechanism OID and the initiator
+  doesn't get confused (#1066000, RT#7858)
+
 * Fri Jan 31 2014 Nalin Dahyabhai <nalin at redhat.com> - 1.11.3-20
 - add currently-proposed changes to teach ksu about credential cache
   collections and the default_ccache_name setting (#1015559,#1026099)


More information about the scm-commits mailing list