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.

ticket: 8055 (new)
target_version: 1.13.1
tags: pullup
  • Loading branch information
greghudson committed Feb 4, 2015
1 parent 19bb843 commit 82dc33d
Show file tree
Hide file tree
Showing 14 changed files with 36 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/lib/gssapi/krb5/context_time.c
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
1 change: 1 addition & 0 deletions src/tests/gssapi/t_prf.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ main(int argc, char *argv[])
uctx.mech_type = &mech_krb5;
uctx.internal_ctx_id = (gss_ctx_id_t)&kgctx;
kgctx.k5_context = NULL;
kgctx.established = 1;
kgctx.have_acceptor_subkey = 1;
kb1.contents = k1buf;
kb2.contents = k2buf;
Expand Down

0 comments on commit 82dc33d

Please sign in to comment.