Blame SOURCES/krb5-1.11-spnego-preserve-oid.patch

7d335d
Adjusted to apply to 1.11.5.
7d335d
7d335d
commit 8255613476d4c1583a5e810b50444f188fde871f
7d335d
Author: Greg Hudson <ghudson@mit.edu>
7d335d
Date:   Mon Feb 3 21:11:34 2014 -0500
7d335d
7d335d
    Properly reflect MS krb5 mech in SPNEGO acceptor
7d335d
    
7d335d
    r25590 changed negotiate_mech() to return an alias into the acceptor's
7d335d
    mech set, with the unfortunate side effect of transforming the
7d335d
    erroneous Microsoft krb5 mech OID into the correct krb5 mech OID,
7d335d
    meaning that we answer with a different OID than the requested one.
7d335d
    Return an alias into the initiator's mech set instead, and store that
7d335d
    in mech_set field the SPNEGO context.  The acceptor code only uses
7d335d
    mech_set to hold the allocated storage pointed into by internal_mech,
7d335d
    so this change is safe.
7d335d
    
7d335d
    ticket: 7858
7d335d
    target_version: 1.12.2
7d335d
    tags: pullup
7d335d
7d335d
diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
7d335d
index 7e4bf90..7529c74 100644
7d335d
--- a/src/lib/gssapi/spnego/spnego_mech.c
7d335d
+++ b/src/lib/gssapi/spnego/spnego_mech.c
7d335d
@@ -1388,8 +1388,8 @@ acc_ctx_new(OM_uint32 *minor_status,
7d335d
 		*return_token = NO_TOKEN_SEND;
7d335d
 		goto cleanup;
7d335d
 	}
7d335d
-	sc->mech_set = supported_mechSet;
7d335d
-	supported_mechSet = GSS_C_NO_OID_SET;
7d335d
+	sc->mech_set = mechTypes;
7d335d
+	mechTypes = GSS_C_NO_OID_SET;
7d335d
 	sc->internal_mech = mech_wanted;
7d335d
 	sc->DER_mechTypes = der_mechTypes;
7d335d
 	der_mechTypes.length = 0;
7d335d
@@ -3538,7 +3538,7 @@ put_negResult(unsigned char **buf_out, OM_uint32 negResult,
7d335d
  * is set to ACCEPT_INCOMPLETE if it's the first mech, REQUEST_MIC if
7d335d
  * it's not the first mech, otherwise we return NULL and negResult
7d335d
  * is set to REJECT. The returned pointer is an alias into
7d335d
- * supported->elements and should not be freed.
7d335d
+ * received->elements and should not be freed.
7d335d
  *
7d335d
  * NOTE: There is currently no way to specify a preference order of
7d335d
  * mechanisms supported by the acceptor.
7d335d
@@ -3560,7 +3560,7 @@ negotiate_mech(gss_OID_set supported, gss_OID_set received,
7d335d
 			if (g_OID_equal(mech_oid, &supported->elements[j])) {
7d335d
 				*negResult = (i == 0) ? ACCEPT_INCOMPLETE :
7d335d
 					REQUEST_MIC;
7d335d
-				return &supported->elements[j];
7d335d
+				return &received->elements[i];
7d335d
 			}
7d335d
 		}
7d335d
 	}
7d335d
7d335d
commit 53cfb8327c452bd72a8e915338fb5ec838079cd3
7d335d
Author: Greg Hudson <ghudson@mit.edu>
7d335d
Date:   Mon Feb 3 20:59:54 2014 -0500
7d335d
7d335d
    Test SPNEGO acceptor response to MS krb5 mech OID
7d335d
    
7d335d
    In t_spnego.c, add code to make a SPNEGO request with the erroneous
7d335d
    Microsoft OID value and examine the response to make sure that it uses
7d335d
    the same OID value as the request did.  The token and tmp variables
7d335d
    were unused, so rename them to itok and atok for the purpose of the
7d335d
    new test code.
7d335d
    
7d335d
    ticket: 7858
7d335d
    target_version: 1.12.2
7d335d
    tags: pullup
7d335d
7d335d
diff --git a/src/tests/gssapi/t_spnego.c b/src/tests/gssapi/t_spnego.c
7d335d
index cbf720b..ca05848 100644
7d335d
--- a/src/tests/gssapi/t_spnego.c
7d335d
+++ b/src/tests/gssapi/t_spnego.c
7d335d
@@ -27,9 +27,15 @@
7d335d
 #include <stdio.h>
7d335d
 #include <stdlib.h>
7d335d
 #include <string.h>
7d335d
+#include <assert.h>
7d335d
 
7d335d
 #include "common.h"
7d335d
 
7d335d
+static gss_OID_desc mech_krb5_wrong = {
7d335d
+    9, "\052\206\110\202\367\022\001\002\002"
7d335d
+};
7d335d
+gss_OID_set_desc mechset_krb5_wrong = { 1, &mech_krb5_wrong };
7d335d
+
7d335d
 /*
7d335d
  * Test program for SPNEGO and gss_set_neg_mechs
7d335d
  *
7d335d
@@ -44,13 +50,16 @@ main(int argc, char *argv[])
7d335d
 {
7d335d
     OM_uint32 minor, major;
7d335d
     gss_cred_id_t verifier_cred_handle = GSS_C_NO_CREDENTIAL;
7d335d
+    gss_cred_id_t initiator_cred_handle = GSS_C_NO_CREDENTIAL;
7d335d
     gss_OID_set actual_mechs = GSS_C_NO_OID_SET;
7d335d
     gss_buffer_desc token = GSS_C_EMPTY_BUFFER, tmp = GSS_C_EMPTY_BUFFER;
7d335d
+    gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok = GSS_C_EMPTY_BUFFER;
7d335d
     gss_ctx_id_t initiator_context = GSS_C_NO_CONTEXT;
7d335d
     gss_ctx_id_t acceptor_context = GSS_C_NO_CONTEXT;
7d335d
     gss_name_t target_name, source_name = GSS_C_NO_NAME;
7d335d
     OM_uint32 time_rec;
7d335d
     gss_OID mech = GSS_C_NO_OID;
7d335d
+    const unsigned char *atok_oid;
7d335d
 
7d335d
     if (argc < 2 || argc > 3) {
7d335d
         fprintf(stderr, "Usage: %s target_name [keytab]\n", argv[0]);
7d335d
@@ -83,10 +91,59 @@ main(int argc, char *argv[])
7d335d
 
7d335d
     (void)gss_delete_sec_context(&minor, &acceptor_context, NULL);
7d335d
     (void)gss_release_name(&minor, &source_name);
7d335d
-    (void)gss_release_name(&minor, &target_name);
7d335d
-    (void)gss_release_buffer(&minor, &token);
7d335d
-    (void)gss_release_buffer(&minor, &tmp);
7d335d
     (void)gss_release_cred(&minor, &verifier_cred_handle);
7d335d
     (void)gss_release_oid_set(&minor, &actual_mechs);
7d335d
+
7d335d
+    /*
7d335d
+     * Test that the SPNEGO acceptor code properly reflects back the erroneous
7d335d
+     * Microsoft mech OID in the supportedMech field of the NegTokenResp
7d335d
+     * message.  Our initiator code doesn't care (it treats all variants of the
7d335d
+     * krb5 mech as equivalent when comparing the supportedMech response to its
7d335d
+     * first-choice mech), so we have to look directly at the DER encoding of
7d335d
+     * the response token.  If we don't request mutual authentication, the
7d335d
+     * SPNEGO reply will contain no underlying mech token, so the encoding of
7d335d
+     * the correct NegotiationToken response is completely predictable:
7d335d
+     *
7d335d
+     *   A1 14 (choice 1, length 20, meaning negTokenResp)
7d335d
+     *     30 12 (sequence, length 18)
7d335d
+     *       A0 03 (context tag 0, length 3)
7d335d
+     *         0A 01 00 (enumerated value 0, meaning accept-completed)
7d335d
+     *       A1 0B (context tag 1, length 11)
7d335d
+     *         06 09 (object identifier, length 9)
7d335d
+     *            2A 86 48 82 F7 12 01 02 02 (the erroneous krb5 OID)
7d335d
+     *
7d335d
+     * So we can just compare the length to 22 and the nine bytes at offset 13
7d335d
+     * to the expected OID.
7d335d
+     */
7d335d
+    major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
7d335d
+                             &mechset_spnego, GSS_C_INITIATE,
7d335d
+                             &initiator_cred_handle, NULL, NULL);
7d335d
+    check_gsserr("gss_acquire_cred(2)", major, minor);
7d335d
+    major = gss_set_neg_mechs(&minor, initiator_cred_handle,
7d335d
+                              &mechset_krb5_wrong);
7d335d
+    check_gsserr("gss_set_neg_mechs(2)", major, minor);
7d335d
+    major = gss_init_sec_context(&minor, initiator_cred_handle,
7d335d
+                                 &initiator_context, target_name, &mech_spnego,
7d335d
+                                 GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG,
7d335d
+                                 GSS_C_INDEFINITE,
7d335d
+                                 GSS_C_NO_CHANNEL_BINDINGS, &atok, NULL, &itok,
7d335d
+                                 NULL, NULL);
7d335d
+    check_gsserr("gss_init_sec_context", major, minor);
7d335d
+    assert(major == GSS_S_CONTINUE_NEEDED);
7d335d
+    major = gss_accept_sec_context(&minor, &acceptor_context,
7d335d
+                                   GSS_C_NO_CREDENTIAL, &itok,
7d335d
+                                   GSS_C_NO_CHANNEL_BINDINGS, NULL,
7d335d
+                                   NULL, &atok, NULL, NULL, NULL);
7d335d
+    assert(atok.length == 22);
7d335d
+    atok_oid = (unsigned char *)atok.value + 13;
7d335d
+    assert(memcmp(atok_oid, mech_krb5_wrong.elements, 9) == 0);
7d335d
+    check_gsserr("gss_accept_sec_context", major, minor);
7d335d
+
7d335d
+    (void)gss_delete_sec_context(&minor, &initiator_context, NULL);
7d335d
+    (void)gss_delete_sec_context(&minor, &acceptor_context, NULL);
7d335d
+    (void)gss_release_cred(&minor, &initiator_cred_handle);
7d335d
+    (void)gss_release_name(&minor, &target_name);
7d335d
+    (void)gss_release_buffer(&minor, &itok);
7d335d
+    (void)gss_release_buffer(&minor, &atok);
7d335d
     return 0;
7d335d
 }