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