Skip to content

Commit 82dc33d

Browse files
committed
Fix gss_process_context_token() [CVE-2014-5352]
[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
1 parent 19bb843 commit 82dc33d

14 files changed

+36
-13
lines changed

Diff for: src/lib/gssapi/krb5/context_time.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ krb5_gss_context_time(minor_status, context_handle, time_rec)
4040

4141
ctx = (krb5_gss_ctx_id_rec *) context_handle;
4242

43-
if (! ctx->established) {
43+
if (ctx->terminated || !ctx->established) {
4444
*minor_status = KG_CTX_INCOMPLETE;
4545
return(GSS_S_NO_CONTEXT);
4646
}

Diff for: src/lib/gssapi/krb5/export_sec_context.c

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ krb5_gss_export_sec_context(minor_status, context_handle, interprocess_token)
4545
*minor_status = 0;
4646

4747
ctx = (krb5_gss_ctx_id_t) *context_handle;
48+
if (ctx->terminated) {
49+
*minor_status = KG_CTX_INCOMPLETE;
50+
return (GSS_S_NO_CONTEXT);
51+
}
52+
4853
context = ctx->k5_context;
4954
kret = krb5_gss_ser_init(context);
5055
if (kret)

Diff for: src/lib/gssapi/krb5/gssapiP_krb5.h

+1
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ typedef struct _krb5_gss_ctx_id_rec {
206206
unsigned int established : 1;
207207
unsigned int have_acceptor_subkey : 1;
208208
unsigned int seed_init : 1; /* XXX tested but never actually set */
209+
unsigned int terminated : 1;
209210
OM_uint32 gss_flags;
210211
unsigned char seed[16];
211212
krb5_gss_name_t here;

Diff for: src/lib/gssapi/krb5/gssapi_krb5.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
369369

370370
ctx = (krb5_gss_ctx_id_rec *) context_handle;
371371

372-
if (!ctx->established)
372+
if (ctx->terminated || !ctx->established)
373373
return GSS_S_NO_CONTEXT;
374374

375375
for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/

Diff for: src/lib/gssapi/krb5/inq_context.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
105105

106106
ctx = (krb5_gss_ctx_id_rec *) context_handle;
107107

108-
if (! ctx->established) {
108+
if (ctx->terminated || !ctx->established) {
109109
*minor_status = KG_CTX_INCOMPLETE;
110110
return(GSS_S_NO_CONTEXT);
111111
}

Diff for: src/lib/gssapi/krb5/k5seal.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ kg_seal(minor_status, context_handle, conf_req_flag, qop_req,
342342

343343
ctx = (krb5_gss_ctx_id_rec *) context_handle;
344344

345-
if (! ctx->established) {
345+
if (ctx->terminated || !ctx->established) {
346346
*minor_status = KG_CTX_INCOMPLETE;
347347
return(GSS_S_NO_CONTEXT);
348348
}

Diff for: src/lib/gssapi/krb5/k5sealiov.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ kg_seal_iov(OM_uint32 *minor_status,
281281
}
282282

283283
ctx = (krb5_gss_ctx_id_rec *)context_handle;
284-
if (!ctx->established) {
284+
if (ctx->terminated || !ctx->established) {
285285
*minor_status = KG_CTX_INCOMPLETE;
286286
return GSS_S_NO_CONTEXT;
287287
}

Diff for: src/lib/gssapi/krb5/k5unseal.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ kg_unseal(minor_status, context_handle, input_token_buffer,
492492

493493
ctx = (krb5_gss_ctx_id_rec *) context_handle;
494494

495-
if (! ctx->established) {
495+
if (ctx->terminated || !ctx->established) {
496496
*minor_status = KG_CTX_INCOMPLETE;
497497
return(GSS_S_NO_CONTEXT);
498498
}

Diff for: src/lib/gssapi/krb5/k5unsealiov.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ kg_unseal_iov(OM_uint32 *minor_status,
625625
OM_uint32 code;
626626

627627
ctx = (krb5_gss_ctx_id_rec *)context_handle;
628-
if (!ctx->established) {
628+
if (ctx->terminated || !ctx->established) {
629629
*minor_status = KG_CTX_INCOMPLETE;
630630
return GSS_S_NO_CONTEXT;
631631
}

Diff for: src/lib/gssapi/krb5/lucid_context.c

+5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ gss_krb5int_export_lucid_sec_context(
7575
*minor_status = 0;
7676
*data_set = GSS_C_NO_BUFFER_SET;
7777

78+
if (ctx->terminated || !ctx->established) {
79+
*minor_status = KG_CTX_INCOMPLETE;
80+
return GSS_S_NO_CONTEXT;
81+
}
82+
7883
retval = generic_gss_oid_decompose(minor_status,
7984
GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID,
8085
GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH,

Diff for: src/lib/gssapi/krb5/prf.c

+4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ krb5_gss_pseudo_random(OM_uint32 *minor_status,
5858
ns.data = NULL;
5959

6060
ctx = (krb5_gss_ctx_id_t)context;
61+
if (ctx->terminated || !ctx->established) {
62+
*minor_status = KG_CTX_INCOMPLETE;
63+
return GSS_S_NO_CONTEXT;
64+
}
6165

6266
switch (prf_key) {
6367
case GSS_C_PRF_KEY_FULL:

Diff for: src/lib/gssapi/krb5/process_context_token.c

+12-5
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,18 @@ krb5_gss_process_context_token(minor_status, context_handle,
3939

4040
ctx = (krb5_gss_ctx_id_t) context_handle;
4141

42-
if (! ctx->established) {
42+
if (ctx->terminated || !ctx->established) {
4343
*minor_status = KG_CTX_INCOMPLETE;
4444
return(GSS_S_NO_CONTEXT);
4545
}
4646

47+
/* We only support context deletion tokens for now, and RFC 4121 does not
48+
* define a context deletion token. */
49+
if (ctx->proto) {
50+
*minor_status = 0;
51+
return(GSS_S_DEFECTIVE_TOKEN);
52+
}
53+
4754
/* "unseal" the token */
4855

4956
if (GSS_ERROR(majerr = kg_unseal(minor_status, context_handle,
@@ -52,8 +59,8 @@ krb5_gss_process_context_token(minor_status, context_handle,
5259
KG_TOK_DEL_CTX)))
5360
return(majerr);
5461

55-
/* that's it. delete the context */
56-
57-
return(krb5_gss_delete_sec_context(minor_status, &context_handle,
58-
GSS_C_NO_BUFFER));
62+
/* Mark the context as terminated, but do not delete it (as that would
63+
* leave the caller with a dangling context handle). */
64+
ctx->terminated = 1;
65+
return(GSS_S_COMPLETE);
5966
}

Diff for: src/lib/gssapi/krb5/wrap_size_limit.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
9595
}
9696

9797
ctx = (krb5_gss_ctx_id_rec *) context_handle;
98-
if (! ctx->established) {
98+
if (ctx->terminated || !ctx->established) {
9999
*minor_status = KG_CTX_INCOMPLETE;
100100
return(GSS_S_NO_CONTEXT);
101101
}

Diff for: src/tests/gssapi/t_prf.c

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ main(int argc, char *argv[])
127127
uctx.mech_type = &mech_krb5;
128128
uctx.internal_ctx_id = (gss_ctx_id_t)&kgctx;
129129
kgctx.k5_context = NULL;
130+
kgctx.established = 1;
130131
kgctx.have_acceptor_subkey = 1;
131132
kb1.contents = k1buf;
132133
kb2.contents = k2buf;

0 commit comments

Comments
 (0)