Blame SOURCES/Implement-GSS_C_CHANNEL_BOUND_FLAG.patch

677019
From b8bff4973a6642af80cbbc1bc03a52cb0d4e6247 Mon Sep 17 00:00:00 2001
d283c7
From: Alexander Scheel <ascheel@redhat.com>
d283c7
Date: Wed, 5 Jul 2017 11:38:30 -0400
d283c7
Subject: [PATCH] Implement GSS_C_CHANNEL_BOUND_FLAG
d283c7
d283c7
Define a new channel-bound GSS return flag, and set it in the krb5
d283c7
mech if the initiator sent channel bindings matching the acceptor's.
d283c7
Do not error out if the acceptor specifies channel bindings and the
d283c7
initiator does not send them.
d283c7
d283c7
[ghudson@mit.edu: simplified code changes; fleshed out commit message]
d283c7
d283c7
[iboukris: cherry-picked from another PR and reduced in scope]
d283c7
d283c7
ticket: 8899 (new)
d283c7
(cherry picked from commit 429a31146083fac21958631c2af572b08ec91022)
d283c7
(cherry picked from commit 3ea1d6296ced3a998e79356f9be212e4c5e6a5d5)
d283c7
---
d283c7
 src/lib/gssapi/generic/gssapi_ext.h      |  2 ++
d283c7
 src/lib/gssapi/krb5/accept_sec_context.c | 18 +++++++++++++-----
d283c7
 2 files changed, 15 insertions(+), 5 deletions(-)
d283c7
d283c7
diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h
d283c7
index 218456e44..c675e8ebb 100644
d283c7
--- a/src/lib/gssapi/generic/gssapi_ext.h
d283c7
+++ b/src/lib/gssapi/generic/gssapi_ext.h
d283c7
@@ -595,6 +595,8 @@ gss_store_cred_into(
d283c7
  * attribute (along with any applicable RFC 5587 attributes).
d283c7
  */
d283c7
 
d283c7
+#define GSS_C_CHANNEL_BOUND_FLAG 2048 /* 0x00000800 */
d283c7
+
d283c7
 OM_uint32 KRB5_CALLCONV
d283c7
 gssspi_query_meta_data(
d283c7
     OM_uint32 *minor_status,
d283c7
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
d283c7
index 70dd7fc0c..9d3e2f4fe 100644
d283c7
--- a/src/lib/gssapi/krb5/accept_sec_context.c
d283c7
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
d283c7
@@ -427,6 +427,9 @@ kg_process_extension(krb5_context context,
d283c7
                          GSS_C_SEQUENCE_FLAG | GSS_C_DCE_STYLE |        \
d283c7
                          GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG)
d283c7
 
d283c7
+/* A zero-value channel binding, for comparison */
d283c7
+static const uint8_t null_cb[CB_MD5_LEN];
d283c7
+
d283c7
 /*
d283c7
  * The krb5 GSS mech appropriates the authenticator checksum field from RFC
d283c7
  * 4120 to store structured data instead of a checksum, indicated with checksum
d283c7
@@ -435,9 +438,10 @@ kg_process_extension(krb5_context context,
d283c7
  *
d283c7
  * Interpret the checksum.  Read delegated creds into *deleg_out if it is not
d283c7
  * NULL.  Set *flags_out to the allowed subset of token flags, plus
d283c7
- * GSS_C_DELEG_FLAG if a delegated credential was present.  Process any
d283c7
- * extensions found using exts.  On error, set *code_out to a krb5_error code
d283c7
- * for use as a minor status value.
d283c7
+ * GSS_C_DELEG_FLAG if a delegated credential was present and
d283c7
+ * GSS_C_CHANNEL_BOUND_FLAG if matching channel bindings are present.  Process
d283c7
+ * any extensions found using exts.  On error, set *code_out to a krb5_error
d283c7
+ * code for use as a minor status value.
d283c7
  */
d283c7
 static OM_uint32
d283c7
 process_checksum(OM_uint32 *minor_status, krb5_context context,
d283c7
@@ -450,7 +454,7 @@ process_checksum(OM_uint32 *minor_status, krb5_context context,
d283c7
     krb5_error_code code = 0;
d283c7
     OM_uint32 status, option_id, token_flags;
d283c7
     size_t cb_len, option_len;
d283c7
-    krb5_boolean valid;
d283c7
+    krb5_boolean valid, token_cb_present = FALSE, cb_match = FALSE;
d283c7
     krb5_key subkey;
d283c7
     krb5_data option, empty = empty_data();
d283c7
     krb5_checksum cb_cksum;
d283c7
@@ -516,7 +520,9 @@ process_checksum(OM_uint32 *minor_status, krb5_context context,
d283c7
                 goto fail;
d283c7
             }
d283c7
             assert(cb_cksum.length == cb_len);
d283c7
-            if (k5_bcmp(token_cb, cb_cksum.contents, cb_len) != 0) {
d283c7
+            token_cb_present = (k5_bcmp(token_cb, null_cb, cb_len) != 0);
d283c7
+            cb_match = (k5_bcmp(token_cb, cb_cksum.contents, cb_len) == 0);
d283c7
+            if (token_cb_present && !cb_match) {
d283c7
                 status = GSS_S_BAD_BINDINGS;
d283c7
                 goto fail;
d283c7
             }
d283c7
@@ -525,6 +531,8 @@ process_checksum(OM_uint32 *minor_status, krb5_context context,
d283c7
         /* Read the token flags and accept some of them as context flags. */
d283c7
         token_flags = k5_input_get_uint32_le(&in);
d283c7
         *flags_out = token_flags & INITIATOR_FLAGS;
d283c7
+        if (cb_match)
d283c7
+            *flags_out |= GSS_C_CHANNEL_BOUND_FLAG;
d283c7
 
d283c7
         /* Read the delegated credential if present. */
d283c7
         if (in.len >= 4 && (token_flags & GSS_C_DELEG_FLAG)) {