Skip to content

Commit

Permalink
Fix gss_process_context_token() [CVE-2014-5352]
Browse files Browse the repository at this point in the history
[MITKRB5-SA-2015-001] The krb5 gss_process_context_token() should not
actually delete the context; that leaves the caller with a dangling
pointer and no way to know that it is invalid.  Instead, mark the
context as terminated, and check for terminated contexts in the GSS
functions which expect established contexts.  Also add checks in
export_sec_context and pseudo_random, and adjust t_prf.c for the
pseudo_random check.

(back ported from commit 82dc33d)

ticket: 8067 (new)
version_fixed: 1.12.3
status: resolved
  • Loading branch information
tlyu committed Feb 4, 2015
1 parent 148cd34 commit e76dbd8
Show file tree
Hide file tree
Showing 13 changed files with 35 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/context_time.c
Expand Up @@ -40,7 +40,7 @@ krb5_gss_context_time(minor_status, context_handle, time_rec)

ctx = (krb5_gss_ctx_id_rec *) context_handle;

if (! ctx->established) {
if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return(GSS_S_NO_CONTEXT);
}
Expand Down
5 changes: 5 additions & 0 deletions src/lib/gssapi/krb5/export_sec_context.c
Expand Up @@ -45,6 +45,11 @@ krb5_gss_export_sec_context(minor_status, context_handle, interprocess_token)
*minor_status = 0;

ctx = (krb5_gss_ctx_id_t) *context_handle;
if (ctx->terminated) {
*minor_status = KG_CTX_INCOMPLETE;
return (GSS_S_NO_CONTEXT);
}

context = ctx->k5_context;
kret = krb5_gss_ser_init(context);
if (kret)
Expand Down
1 change: 1 addition & 0 deletions src/lib/gssapi/krb5/gssapiP_krb5.h
Expand Up @@ -204,6 +204,7 @@ typedef struct _krb5_gss_ctx_id_rec {
unsigned int established : 1;
unsigned int have_acceptor_subkey : 1;
unsigned int seed_init : 1; /* XXX tested but never actually set */
unsigned int terminated : 1;
OM_uint32 gss_flags;
unsigned char seed[16];
krb5_gss_name_t here;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/gssapi_krb5.c
Expand Up @@ -369,7 +369,7 @@ krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,

ctx = (krb5_gss_ctx_id_rec *) context_handle;

if (!ctx->established)
if (ctx->terminated || !ctx->established)
return GSS_S_NO_CONTEXT;

for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/
Expand Down
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/inq_context.c
Expand Up @@ -105,7 +105,7 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,

ctx = (krb5_gss_ctx_id_rec *) context_handle;

if (! ctx->established) {
if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return(GSS_S_NO_CONTEXT);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/k5seal.c
Expand Up @@ -342,7 +342,7 @@ kg_seal(minor_status, context_handle, conf_req_flag, qop_req,

ctx = (krb5_gss_ctx_id_rec *) context_handle;

if (! ctx->established) {
if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return(GSS_S_NO_CONTEXT);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/k5sealiov.c
Expand Up @@ -284,7 +284,7 @@ kg_seal_iov(OM_uint32 *minor_status,
}

ctx = (krb5_gss_ctx_id_rec *)context_handle;
if (!ctx->established) {
if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return GSS_S_NO_CONTEXT;
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/k5unseal.c
Expand Up @@ -492,7 +492,7 @@ kg_unseal(minor_status, context_handle, input_token_buffer,

ctx = (krb5_gss_ctx_id_rec *) context_handle;

if (! ctx->established) {
if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return(GSS_S_NO_CONTEXT);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/k5unsealiov.c
Expand Up @@ -628,7 +628,7 @@ kg_unseal_iov(OM_uint32 *minor_status,
OM_uint32 code;

ctx = (krb5_gss_ctx_id_rec *)context_handle;
if (!ctx->established) {
if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return GSS_S_NO_CONTEXT;
}
Expand Down
5 changes: 5 additions & 0 deletions src/lib/gssapi/krb5/lucid_context.c
Expand Up @@ -75,6 +75,11 @@ gss_krb5int_export_lucid_sec_context(
*minor_status = 0;
*data_set = GSS_C_NO_BUFFER_SET;

if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return GSS_S_NO_CONTEXT;
}

retval = generic_gss_oid_decompose(minor_status,
GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID,
GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH,
Expand Down
4 changes: 4 additions & 0 deletions src/lib/gssapi/krb5/prf.c
Expand Up @@ -60,6 +60,10 @@ krb5_gss_pseudo_random(OM_uint32 *minor_status,
ns.data = NULL;

ctx = (krb5_gss_ctx_id_t)context;
if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return GSS_S_NO_CONTEXT;
}

switch (prf_key) {
case GSS_C_PRF_KEY_FULL:
Expand Down
17 changes: 12 additions & 5 deletions src/lib/gssapi/krb5/process_context_token.c
Expand Up @@ -39,11 +39,18 @@ krb5_gss_process_context_token(minor_status, context_handle,

ctx = (krb5_gss_ctx_id_t) context_handle;

if (! ctx->established) {
if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return(GSS_S_NO_CONTEXT);
}

/* We only support context deletion tokens for now, and RFC 4121 does not
* define a context deletion token. */
if (ctx->proto) {
*minor_status = 0;
return(GSS_S_DEFECTIVE_TOKEN);
}

/* "unseal" the token */

if (GSS_ERROR(majerr = kg_unseal(minor_status, context_handle,
Expand All @@ -52,8 +59,8 @@ krb5_gss_process_context_token(minor_status, context_handle,
KG_TOK_DEL_CTX)))
return(majerr);

/* that's it. delete the context */

return(krb5_gss_delete_sec_context(minor_status, &context_handle,
GSS_C_NO_BUFFER));
/* Mark the context as terminated, but do not delete it (as that would
* leave the caller with a dangling context handle). */
ctx->terminated = 1;
return(GSS_S_COMPLETE);
}
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/wrap_size_limit.c
Expand Up @@ -95,7 +95,7 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
}

ctx = (krb5_gss_ctx_id_rec *) context_handle;
if (! ctx->established) {
if (ctx->terminated || !ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return(GSS_S_NO_CONTEXT);
}
Expand Down

0 comments on commit e76dbd8

Please sign in to comment.