Blame SOURCES/Implement-GSS_C_CHANNEL_BOUND_FLAG.patch

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