summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobbie Harwood <rharwood@redhat.com>2017-09-06 16:43:56 +0000
committerRobbie Harwood <rharwood@redhat.com>2017-09-06 16:43:59 +0000
commit11b90e9e6e42aeb2568fb67e68eb3e398dd4fbcb (patch)
treec38347076283b4512f4cd6695965979c47e169c4
parentf6b653fac2245f542c4370319f252498eff1e9e3 (diff)
downloadkrb5-11b90e9e6e42aeb2568fb67e68eb3e398dd4fbcb.tar.gz
krb5-11b90e9e6e42aeb2568fb67e68eb3e398dd4fbcb.tar.xz
krb5-11b90e9e6e42aeb2568fb67e68eb3e398dd4fbcb.zip
Save other programs from worrying about CVE-2017-11462
Resolves: #1488873 Resolves: #1488874
-rw-r--r--Preserve-GSS-context-on-init-accept-failure.patch413
-rw-r--r--krb5.spec8
2 files changed, 420 insertions, 1 deletions
diff --git a/Preserve-GSS-context-on-init-accept-failure.patch b/Preserve-GSS-context-on-init-accept-failure.patch
new file mode 100644
index 0000000..7166561
--- /dev/null
+++ b/Preserve-GSS-context-on-init-accept-failure.patch
@@ -0,0 +1,413 @@
+From d730a62c2d3f6f75a0fa28b7a8c952fb29dd7aa0 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 14 Jul 2017 13:02:46 -0400
+Subject: [PATCH] Preserve GSS context on init/accept failure
+
+After gss_init_sec_context() or gss_accept_sec_context() has created a
+context, don't delete the mechglue context on failures from subsequent
+calls, even if the mechanism deletes the mech-specific context (which
+is allowed by RFC 2744 but not preferred). Check for union contexts
+with no mechanism context in each GSS function which accepts a
+gss_ctx_id_t.
+
+CVE-2017-11462:
+
+RFC 2744 permits a GSS-API implementation to delete an existing
+security context on a second or subsequent call to
+gss_init_sec_context() or gss_accept_sec_context() if the call results
+in an error. This API behavior has been found to be dangerous,
+leading to the possibility of memory errors in some callers. For
+safety, GSS-API implementations should instead preserve existing
+security contexts on error until the caller deletes them.
+
+All versions of MIT krb5 prior to this change may delete acceptor
+contexts on error. Versions 1.13.4 through 1.13.7, 1.14.1 through
+1.14.5, and 1.15 through 1.15.1 may also delete initiator contexts on
+error.
+
+ticket: 8598 (new)
+target_version: 1.15-next
+target_version: 1.14-next
+tags: pullup
+
+(cherry picked from commit 56f7b1bc95a2a3eeb420e069e7655fb181ade5cf)
+---
+ src/lib/gssapi/mechglue/g_accept_sec_context.c | 22 +++++++++++++++-------
+ src/lib/gssapi/mechglue/g_complete_auth_token.c | 2 ++
+ src/lib/gssapi/mechglue/g_context_time.c | 2 ++
+ src/lib/gssapi/mechglue/g_delete_sec_context.c | 14 ++++++++------
+ src/lib/gssapi/mechglue/g_exp_sec_context.c | 2 ++
+ src/lib/gssapi/mechglue/g_init_sec_context.c | 19 +++++++++++--------
+ src/lib/gssapi/mechglue/g_inq_context.c | 2 ++
+ src/lib/gssapi/mechglue/g_prf.c | 2 ++
+ src/lib/gssapi/mechglue/g_process_context.c | 2 ++
+ src/lib/gssapi/mechglue/g_seal.c | 4 ++++
+ src/lib/gssapi/mechglue/g_sign.c | 2 ++
+ src/lib/gssapi/mechglue/g_unseal.c | 2 ++
+ src/lib/gssapi/mechglue/g_unwrap_aead.c | 2 ++
+ src/lib/gssapi/mechglue/g_unwrap_iov.c | 4 ++++
+ src/lib/gssapi/mechglue/g_verify.c | 2 ++
+ src/lib/gssapi/mechglue/g_wrap_aead.c | 2 ++
+ src/lib/gssapi/mechglue/g_wrap_iov.c | 8 ++++++++
+ 17 files changed, 72 insertions(+), 21 deletions(-)
+
+diff --git a/src/lib/gssapi/mechglue/g_accept_sec_context.c b/src/lib/gssapi/mechglue/g_accept_sec_context.c
+index ddaf87412..f28e2b14a 100644
+--- a/src/lib/gssapi/mechglue/g_accept_sec_context.c
++++ b/src/lib/gssapi/mechglue/g_accept_sec_context.c
+@@ -216,6 +216,8 @@ gss_cred_id_t * d_cred;
+ } else {
+ union_ctx_id = (gss_union_ctx_id_t)*context_handle;
+ selected_mech = union_ctx_id->mech_type;
++ if (union_ctx_id->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ }
+
+ /* Now create a new context if we didn't get one. */
+@@ -234,9 +236,6 @@ gss_cred_id_t * d_cred;
+ free(union_ctx_id);
+ return (status);
+ }
+-
+- /* set the new context handle to caller's data */
+- *context_handle = (gss_ctx_id_t)union_ctx_id;
+ }
+
+ /*
+@@ -277,8 +276,10 @@ gss_cred_id_t * d_cred;
+ d_cred ? &tmp_d_cred : NULL);
+
+ /* If there's more work to do, keep going... */
+- if (status == GSS_S_CONTINUE_NEEDED)
++ if (status == GSS_S_CONTINUE_NEEDED) {
++ *context_handle = (gss_ctx_id_t)union_ctx_id;
+ return GSS_S_CONTINUE_NEEDED;
++ }
+
+ /* if the call failed, return with failure */
+ if (status != GSS_S_COMPLETE) {
+@@ -364,14 +365,22 @@ gss_cred_id_t * d_cred;
+ *mech_type = gssint_get_public_oid(actual_mech);
+ if (ret_flags != NULL)
+ *ret_flags = temp_ret_flags;
+- return (status);
++ *context_handle = (gss_ctx_id_t)union_ctx_id;
++ return GSS_S_COMPLETE;
+ } else {
+
+ status = GSS_S_BAD_MECH;
+ }
+
+ error_out:
+- if (union_ctx_id) {
++ /*
++ * RFC 2744 5.1 requires that we not create a context on a failed first
++ * call to accept, and recommends that on a failed subsequent call we
++ * make the caller responsible for calling gss_delete_sec_context.
++ * Even if the mech deleted its context, keep the union context around
++ * for the caller to delete.
++ */
++ if (union_ctx_id && *context_handle == GSS_C_NO_CONTEXT) {
+ if (union_ctx_id->mech_type) {
+ if (union_ctx_id->mech_type->elements)
+ free(union_ctx_id->mech_type->elements);
+@@ -384,7 +393,6 @@ error_out:
+ GSS_C_NO_BUFFER);
+ }
+ free(union_ctx_id);
+- *context_handle = GSS_C_NO_CONTEXT;
+ }
+
+ if (src_name)
+diff --git a/src/lib/gssapi/mechglue/g_complete_auth_token.c b/src/lib/gssapi/mechglue/g_complete_auth_token.c
+index 918155130..4bcb47e84 100644
+--- a/src/lib/gssapi/mechglue/g_complete_auth_token.c
++++ b/src/lib/gssapi/mechglue/g_complete_auth_token.c
+@@ -52,6 +52,8 @@ gss_complete_auth_token (OM_uint32 *minor_status,
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return GSS_S_NO_CONTEXT;
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech != NULL) {
+diff --git a/src/lib/gssapi/mechglue/g_context_time.c b/src/lib/gssapi/mechglue/g_context_time.c
+index 2ff8d0996..c947e7646 100644
+--- a/src/lib/gssapi/mechglue/g_context_time.c
++++ b/src/lib/gssapi/mechglue/g_context_time.c
+@@ -58,6 +58,8 @@ OM_uint32 * time_rec;
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech) {
+diff --git a/src/lib/gssapi/mechglue/g_delete_sec_context.c b/src/lib/gssapi/mechglue/g_delete_sec_context.c
+index 4bf0dec5c..574ff0294 100644
+--- a/src/lib/gssapi/mechglue/g_delete_sec_context.c
++++ b/src/lib/gssapi/mechglue/g_delete_sec_context.c
+@@ -87,12 +87,14 @@ gss_buffer_t output_token;
+ if (GSSINT_CHK_LOOP(ctx))
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+- status = gssint_delete_internal_sec_context(minor_status,
+- ctx->mech_type,
+- &ctx->internal_ctx_id,
+- output_token);
+- if (status)
+- return status;
++ if (ctx->internal_ctx_id != GSS_C_NO_CONTEXT) {
++ status = gssint_delete_internal_sec_context(minor_status,
++ ctx->mech_type,
++ &ctx->internal_ctx_id,
++ output_token);
++ if (status)
++ return status;
++ }
+
+ /* now free up the space for the union context structure */
+ free(ctx->mech_type->elements);
+diff --git a/src/lib/gssapi/mechglue/g_exp_sec_context.c b/src/lib/gssapi/mechglue/g_exp_sec_context.c
+index b63745299..1d7990b1c 100644
+--- a/src/lib/gssapi/mechglue/g_exp_sec_context.c
++++ b/src/lib/gssapi/mechglue/g_exp_sec_context.c
+@@ -95,6 +95,8 @@ gss_buffer_t interprocess_token;
+ */
+
+ ctx = (gss_union_ctx_id_t) *context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+ if (!mech)
+ return GSS_S_BAD_MECH;
+diff --git a/src/lib/gssapi/mechglue/g_init_sec_context.c b/src/lib/gssapi/mechglue/g_init_sec_context.c
+index 9f154b893..e2df1ce26 100644
+--- a/src/lib/gssapi/mechglue/g_init_sec_context.c
++++ b/src/lib/gssapi/mechglue/g_init_sec_context.c
+@@ -192,8 +192,13 @@ OM_uint32 * time_rec;
+
+ /* copy the supplied context handle */
+ union_ctx_id->internal_ctx_id = GSS_C_NO_CONTEXT;
+- } else
++ } else {
+ union_ctx_id = (gss_union_ctx_id_t)*context_handle;
++ if (union_ctx_id->internal_ctx_id == GSS_C_NO_CONTEXT) {
++ status = GSS_S_NO_CONTEXT;
++ goto end;
++ }
++ }
+
+ /*
+ * get the appropriate cred handle from the union cred struct.
+@@ -224,15 +229,13 @@ OM_uint32 * time_rec;
+
+ if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
+ /*
+- * The spec says the preferred method is to delete all context info on
+- * the first call to init, and on all subsequent calls make the caller
+- * responsible for calling gss_delete_sec_context. However, if the
+- * mechanism decided to delete the internal context, we should also
+- * delete the union context.
++ * RFC 2744 5.19 requires that we not create a context on a failed
++ * first call to init, and recommends that on a failed subsequent call
++ * we make the caller responsible for calling gss_delete_sec_context.
++ * Even if the mech deleted its context, keep the union context around
++ * for the caller to delete.
+ */
+ map_error(minor_status, mech);
+- if (union_ctx_id->internal_ctx_id == GSS_C_NO_CONTEXT)
+- *context_handle = GSS_C_NO_CONTEXT;
+ if (*context_handle == GSS_C_NO_CONTEXT) {
+ free(union_ctx_id->mech_type->elements);
+ free(union_ctx_id->mech_type);
+diff --git a/src/lib/gssapi/mechglue/g_inq_context.c b/src/lib/gssapi/mechglue/g_inq_context.c
+index 6f1c71eed..6c0d98dd3 100644
+--- a/src/lib/gssapi/mechglue/g_inq_context.c
++++ b/src/lib/gssapi/mechglue/g_inq_context.c
+@@ -104,6 +104,8 @@ gss_inquire_context(
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (!mech || !mech->gss_inquire_context || !mech->gss_display_name ||
+diff --git a/src/lib/gssapi/mechglue/g_prf.c b/src/lib/gssapi/mechglue/g_prf.c
+index fcca3e44c..9e168adfe 100644
+--- a/src/lib/gssapi/mechglue/g_prf.c
++++ b/src/lib/gssapi/mechglue/g_prf.c
+@@ -59,6 +59,8 @@ gss_pseudo_random (OM_uint32 *minor_status,
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return GSS_S_NO_CONTEXT;
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech != NULL) {
+diff --git a/src/lib/gssapi/mechglue/g_process_context.c b/src/lib/gssapi/mechglue/g_process_context.c
+index bc260aeb1..3968b5d9c 100644
+--- a/src/lib/gssapi/mechglue/g_process_context.c
++++ b/src/lib/gssapi/mechglue/g_process_context.c
+@@ -61,6 +61,8 @@ gss_buffer_t token_buffer;
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech) {
+diff --git a/src/lib/gssapi/mechglue/g_seal.c b/src/lib/gssapi/mechglue/g_seal.c
+index f17241c90..3db1ee095 100644
+--- a/src/lib/gssapi/mechglue/g_seal.c
++++ b/src/lib/gssapi/mechglue/g_seal.c
+@@ -92,6 +92,8 @@ gss_wrap( OM_uint32 *minor_status,
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech) {
+@@ -226,6 +228,8 @@ gss_wrap_size_limit(OM_uint32 *minor_status,
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (!mech)
+diff --git a/src/lib/gssapi/mechglue/g_sign.c b/src/lib/gssapi/mechglue/g_sign.c
+index 86d641aa2..03fbd8c01 100644
+--- a/src/lib/gssapi/mechglue/g_sign.c
++++ b/src/lib/gssapi/mechglue/g_sign.c
+@@ -94,6 +94,8 @@ gss_buffer_t msg_token;
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech) {
+diff --git a/src/lib/gssapi/mechglue/g_unseal.c b/src/lib/gssapi/mechglue/g_unseal.c
+index 3e8053c6e..c208635b6 100644
+--- a/src/lib/gssapi/mechglue/g_unseal.c
++++ b/src/lib/gssapi/mechglue/g_unseal.c
+@@ -76,6 +76,8 @@ gss_qop_t * qop_state;
+ * call it.
+ */
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech) {
+diff --git a/src/lib/gssapi/mechglue/g_unwrap_aead.c b/src/lib/gssapi/mechglue/g_unwrap_aead.c
+index e78bff2d3..0682bd899 100644
+--- a/src/lib/gssapi/mechglue/g_unwrap_aead.c
++++ b/src/lib/gssapi/mechglue/g_unwrap_aead.c
+@@ -186,6 +186,8 @@ gss_qop_t *qop_state;
+ * call it.
+ */
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (!mech)
+diff --git a/src/lib/gssapi/mechglue/g_unwrap_iov.c b/src/lib/gssapi/mechglue/g_unwrap_iov.c
+index c0dd314b1..599be2c7b 100644
+--- a/src/lib/gssapi/mechglue/g_unwrap_iov.c
++++ b/src/lib/gssapi/mechglue/g_unwrap_iov.c
+@@ -89,6 +89,8 @@ int iov_count;
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech) {
+@@ -128,6 +130,8 @@ gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
+
+ /* Select the approprate underlying mechanism routine and call it. */
+ ctx = (gss_union_ctx_id_t)context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return GSS_S_NO_CONTEXT;
+ mech = gssint_get_mechanism(ctx->mech_type);
+ if (mech == NULL)
+ return GSS_S_BAD_MECH;
+diff --git a/src/lib/gssapi/mechglue/g_verify.c b/src/lib/gssapi/mechglue/g_verify.c
+index 1578ae111..8996fce8d 100644
+--- a/src/lib/gssapi/mechglue/g_verify.c
++++ b/src/lib/gssapi/mechglue/g_verify.c
+@@ -65,6 +65,8 @@ gss_qop_t * qop_state;
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech) {
+diff --git a/src/lib/gssapi/mechglue/g_wrap_aead.c b/src/lib/gssapi/mechglue/g_wrap_aead.c
+index 96cdf3ce6..7fe3b7b35 100644
+--- a/src/lib/gssapi/mechglue/g_wrap_aead.c
++++ b/src/lib/gssapi/mechglue/g_wrap_aead.c
+@@ -256,6 +256,8 @@ gss_buffer_t output_message_buffer;
+ * call it.
+ */
+ ctx = (gss_union_ctx_id_t)context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+ if (!mech)
+ return (GSS_S_BAD_MECH);
+diff --git a/src/lib/gssapi/mechglue/g_wrap_iov.c b/src/lib/gssapi/mechglue/g_wrap_iov.c
+index 40cd98fc9..14447c4ee 100644
+--- a/src/lib/gssapi/mechglue/g_wrap_iov.c
++++ b/src/lib/gssapi/mechglue/g_wrap_iov.c
+@@ -93,6 +93,8 @@ int iov_count;
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech) {
+@@ -151,6 +153,8 @@ int iov_count;
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return (GSS_S_NO_CONTEXT);
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech) {
+@@ -190,6 +194,8 @@ gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
+
+ /* Select the approprate underlying mechanism routine and call it. */
+ ctx = (gss_union_ctx_id_t)context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return GSS_S_NO_CONTEXT;
+ mech = gssint_get_mechanism(ctx->mech_type);
+ if (mech == NULL)
+ return GSS_S_BAD_MECH;
+@@ -218,6 +224,8 @@ gss_get_mic_iov_length(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
+
+ /* Select the approprate underlying mechanism routine and call it. */
+ ctx = (gss_union_ctx_id_t)context_handle;
++ if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT)
++ return GSS_S_NO_CONTEXT;
+ mech = gssint_get_mechanism(ctx->mech_type);
+ if (mech == NULL)
+ return GSS_S_BAD_MECH;
diff --git a/krb5.spec b/krb5.spec
index c4c5b49..dbaa049 100644
--- a/krb5.spec
+++ b/krb5.spec
@@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system
Name: krb5
Version: 1.15.1
# for prerelease, should be e.g., 0.3.beta2%{?dist}
-Release: 27%{?dist}
+Release: 28%{?dist}
# - Maybe we should explode from the now-available-to-everybody tarball instead?
# http://web.mit.edu/kerberos/dist/krb5/1.13/krb5-1.13.2-signed.tar
# - The sources below are stored in a lookaside cache. Upload with
@@ -96,6 +96,7 @@ Patch67: Fix-certauth-built-in-module-returns.patch
Patch68: Add-test-cert-with-no-extensions.patch
Patch69: Add-PKINIT-test-case-for-generic-client-cert.patch
Patch70: Add-hostname-based-ccselect-module.patch
+Patch71: Preserve-GSS-context-on-init-accept-failure.patch
License: MIT
URL: http://web.mit.edu/kerberos/www/
@@ -747,6 +748,11 @@ exit 0
%{_libdir}/libkadm5srv_mit.so.*
%changelog
+* Wed Sep 06 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-28
+- Save other programs from worrying about CVE-2017-11462
+- Resolves: #1488873
+- Resolves: #1488874
+
* Tue Sep 05 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-27
- Add hostname-based ccselect module
- Resolves: #1463665