Skip to content

Commit e04f028

Browse files
nicowilliamsgreghudson
authored andcommitted
Fix IAKERB context aliasing bugs [CVE-2015-2696]
The IAKERB mechanism currently replaces its context handle with the krb5 mechanism handle upon establishment, under the assumption that most GSS functions are only called after context establishment. This assumption is incorrect, and can lead to aliasing violations for some programs. Maintain the IAKERB context structure after context establishment and add new IAKERB entry points to refer to it with that type. Add initiate and established flags to the IAKERB context structure for use in gss_inquire_context() prior to context establishment. CVE-2015-2696: In MIT krb5 1.9 and later, applications which call gss_inquire_context() on a partially-established IAKERB context can cause the GSS-API library to read from a pointer using the wrong type, generally causing a process crash. Java server applications using the native JGSS provider are vulnerable to this bug. A carefully crafted IAKERB packet might allow the gss_inquire_context() call to succeed with attacker-determined results, but applications should not make access control decisions based on gss_inquire_context() results prior to context establishment. CVSSv2 Vector: AV:N/AC:M/Au:N/C:N/I:N/A:C/E:POC/RL:OF/RC:C [ghudson@mit.edu: several bugfixes, style changes, and edge-case behavior changes; commit message and CVE description] ticket: 8244 target_version: 1.14 tags: pullup
1 parent b51b33f commit e04f028

File tree

3 files changed

+529
-41
lines changed

3 files changed

+529
-41
lines changed

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

+114
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,21 @@ OM_uint32 KRB5_CALLCONV krb5_gss_accept_sec_context_ext
621621
);
622622
#endif /* LEAN_CLIENT */
623623

624+
OM_uint32 KRB5_CALLCONV krb5_gss_inquire_sec_context_by_oid
625+
(OM_uint32*, /* minor_status */
626+
const gss_ctx_id_t,
627+
/* context_handle */
628+
const gss_OID, /* desired_object */
629+
gss_buffer_set_t* /* data_set */
630+
);
631+
632+
OM_uint32 KRB5_CALLCONV krb5_gss_set_sec_context_option
633+
(OM_uint32*, /* minor_status */
634+
gss_ctx_id_t*, /* context_handle */
635+
const gss_OID, /* desired_object */
636+
const gss_buffer_t/* value */
637+
);
638+
624639
OM_uint32 KRB5_CALLCONV krb5_gss_process_context_token
625640
(OM_uint32*, /* minor_status */
626641
gss_ctx_id_t, /* context_handle */
@@ -1302,6 +1317,105 @@ OM_uint32 KRB5_CALLCONV
13021317
krb5_gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token,
13031318
gss_cred_id_t *cred_handle);
13041319

1320+
OM_uint32 KRB5_CALLCONV
1321+
iakerb_gss_process_context_token(OM_uint32 *minor_status,
1322+
const gss_ctx_id_t context_handle,
1323+
const gss_buffer_t token_buffer);
1324+
1325+
OM_uint32 KRB5_CALLCONV
1326+
iakerb_gss_context_time(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1327+
OM_uint32 *time_rec);
1328+
1329+
OM_uint32 KRB5_CALLCONV
1330+
iakerb_gss_inquire_context(OM_uint32 *minor_status,
1331+
gss_ctx_id_t context_handle, gss_name_t *src_name,
1332+
gss_name_t *targ_name, OM_uint32 *lifetime_rec,
1333+
gss_OID *mech_type, OM_uint32 *ctx_flags,
1334+
int *locally_initiated, int *opened);
1335+
1336+
OM_uint32 KRB5_CALLCONV
1337+
iakerb_gss_get_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1338+
gss_qop_t qop_req, gss_buffer_t message_buffer,
1339+
gss_buffer_t message_token);
1340+
1341+
OM_uint32 KRB5_CALLCONV
1342+
iakerb_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1343+
gss_qop_t qop_req, gss_iov_buffer_desc *iov,
1344+
int iov_count);
1345+
1346+
OM_uint32 KRB5_CALLCONV
1347+
iakerb_gss_get_mic_iov_length(OM_uint32 *minor_status,
1348+
gss_ctx_id_t context_handle, gss_qop_t qop_req,
1349+
gss_iov_buffer_desc *iov, int iov_count);
1350+
1351+
OM_uint32 KRB5_CALLCONV
1352+
iakerb_gss_verify_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1353+
gss_buffer_t msg_buffer, gss_buffer_t token_buffer,
1354+
gss_qop_t *qop_state);
1355+
1356+
OM_uint32 KRB5_CALLCONV
1357+
iakerb_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1358+
gss_qop_t *qop_state, gss_iov_buffer_desc *iov,
1359+
int iov_count);
1360+
1361+
OM_uint32 KRB5_CALLCONV
1362+
iakerb_gss_wrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1363+
int conf_req_flag, gss_qop_t qop_req,
1364+
gss_buffer_t input_message_buffer, int *conf_state,
1365+
gss_buffer_t output_message_buffer);
1366+
1367+
OM_uint32 KRB5_CALLCONV
1368+
iakerb_gss_wrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1369+
int conf_req_flag, gss_qop_t qop_req, int *conf_state,
1370+
gss_iov_buffer_desc *iov, int iov_count);
1371+
1372+
OM_uint32 KRB5_CALLCONV
1373+
iakerb_gss_wrap_iov_length(OM_uint32 *minor_status,
1374+
gss_ctx_id_t context_handle, int conf_req_flag,
1375+
gss_qop_t qop_req, int *conf_state,
1376+
gss_iov_buffer_desc *iov, int iov_count);
1377+
1378+
OM_uint32 KRB5_CALLCONV
1379+
iakerb_gss_unwrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1380+
gss_buffer_t input_message_buffer,
1381+
gss_buffer_t output_message_buffer, int *conf_state,
1382+
gss_qop_t *qop_state);
1383+
1384+
OM_uint32 KRB5_CALLCONV
1385+
iakerb_gss_unwrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1386+
int *conf_state, gss_qop_t *qop_state,
1387+
gss_iov_buffer_desc *iov, int iov_count);
1388+
1389+
OM_uint32 KRB5_CALLCONV
1390+
iakerb_gss_wrap_size_limit(OM_uint32 *minor_status,
1391+
gss_ctx_id_t context_handle, int conf_req_flag,
1392+
gss_qop_t qop_req, OM_uint32 req_output_size,
1393+
OM_uint32 *max_input_size);
1394+
1395+
#ifndef LEAN_CLIENT
1396+
OM_uint32 KRB5_CALLCONV
1397+
iakerb_gss_export_sec_context(OM_uint32 *minor_status,
1398+
gss_ctx_id_t *context_handle,
1399+
gss_buffer_t interprocess_token);
1400+
#endif /* LEAN_CLIENT */
1401+
1402+
OM_uint32 KRB5_CALLCONV
1403+
iakerb_gss_inquire_sec_context_by_oid(OM_uint32 *minor_status,
1404+
const gss_ctx_id_t context_handle,
1405+
const gss_OID desired_object,
1406+
gss_buffer_set_t *data_set);
1407+
1408+
OM_uint32 KRB5_CALLCONV
1409+
iakerb_gss_set_sec_context_option(OM_uint32 *minor_status,
1410+
gss_ctx_id_t *context_handle,
1411+
const gss_OID desired_object,
1412+
const gss_buffer_t value);
1413+
1414+
OM_uint32 KRB5_CALLCONV
1415+
iakerb_gss_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
1416+
int prf_key, const gss_buffer_t prf_in,
1417+
ssize_t desired_output_len, gss_buffer_t prf_out);
1418+
13051419
/* Magic string to identify exported krb5 GSS credentials. Increment this if
13061420
* the format changes. */
13071421
#define CRED_EXPORT_MAGIC "K5C1"

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

+94-11
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ static struct {
351351
}
352352
};
353353

354-
static OM_uint32 KRB5_CALLCONV
354+
OM_uint32 KRB5_CALLCONV
355355
krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
356356
const gss_ctx_id_t context_handle,
357357
const gss_OID desired_object,
@@ -465,7 +465,7 @@ static struct {
465465
};
466466
#endif
467467

468-
static OM_uint32 KRB5_CALLCONV
468+
OM_uint32 KRB5_CALLCONV
469469
krb5_gss_set_sec_context_option (OM_uint32 *minor_status,
470470
gss_ctx_id_t *context_handle,
471471
const gss_OID desired_object,
@@ -929,20 +929,103 @@ static struct gss_config krb5_mechanism = {
929929
krb5_gss_get_mic_iov_length,
930930
};
931931

932+
/* Functions which use security contexts or acquire creds are IAKERB-specific;
933+
* other functions can borrow from the krb5 mech. */
934+
static struct gss_config iakerb_mechanism = {
935+
{ GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
936+
NULL,
937+
iakerb_gss_acquire_cred,
938+
krb5_gss_release_cred,
939+
iakerb_gss_init_sec_context,
940+
#ifdef LEAN_CLIENT
941+
NULL,
942+
#else
943+
iakerb_gss_accept_sec_context,
944+
#endif
945+
iakerb_gss_process_context_token,
946+
iakerb_gss_delete_sec_context,
947+
iakerb_gss_context_time,
948+
iakerb_gss_get_mic,
949+
iakerb_gss_verify_mic,
950+
#if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE)
951+
NULL,
952+
#else
953+
iakerb_gss_wrap,
954+
#endif
955+
#if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE)
956+
NULL,
957+
#else
958+
iakerb_gss_unwrap,
959+
#endif
960+
krb5_gss_display_status,
961+
krb5_gss_indicate_mechs,
962+
krb5_gss_compare_name,
963+
krb5_gss_display_name,
964+
krb5_gss_import_name,
965+
krb5_gss_release_name,
966+
krb5_gss_inquire_cred,
967+
NULL, /* add_cred */
968+
#ifdef LEAN_CLIENT
969+
NULL,
970+
NULL,
971+
#else
972+
iakerb_gss_export_sec_context,
973+
NULL,
974+
#endif
975+
krb5_gss_inquire_cred_by_mech,
976+
krb5_gss_inquire_names_for_mech,
977+
iakerb_gss_inquire_context,
978+
krb5_gss_internal_release_oid,
979+
iakerb_gss_wrap_size_limit,
980+
krb5_gss_localname,
981+
krb5_gss_authorize_localname,
982+
krb5_gss_export_name,
983+
krb5_gss_duplicate_name,
984+
krb5_gss_store_cred,
985+
iakerb_gss_inquire_sec_context_by_oid,
986+
krb5_gss_inquire_cred_by_oid,
987+
iakerb_gss_set_sec_context_option,
988+
krb5_gssspi_set_cred_option,
989+
krb5_gssspi_mech_invoke,
990+
NULL, /* wrap_aead */
991+
NULL, /* unwrap_aead */
992+
iakerb_gss_wrap_iov,
993+
iakerb_gss_unwrap_iov,
994+
iakerb_gss_wrap_iov_length,
995+
NULL, /* complete_auth_token */
996+
NULL, /* acquire_cred_impersonate_name */
997+
NULL, /* add_cred_impersonate_name */
998+
NULL, /* display_name_ext */
999+
krb5_gss_inquire_name,
1000+
krb5_gss_get_name_attribute,
1001+
krb5_gss_set_name_attribute,
1002+
krb5_gss_delete_name_attribute,
1003+
krb5_gss_export_name_composite,
1004+
krb5_gss_map_name_to_any,
1005+
krb5_gss_release_any_name_mapping,
1006+
iakerb_gss_pseudo_random,
1007+
NULL, /* set_neg_mechs */
1008+
krb5_gss_inquire_saslname_for_mech,
1009+
krb5_gss_inquire_mech_for_saslname,
1010+
krb5_gss_inquire_attrs_for_mech,
1011+
krb5_gss_acquire_cred_from,
1012+
krb5_gss_store_cred_into,
1013+
iakerb_gss_acquire_cred_with_password,
1014+
krb5_gss_export_cred,
1015+
krb5_gss_import_cred,
1016+
NULL, /* import_sec_context_by_mech */
1017+
NULL, /* import_name_by_mech */
1018+
NULL, /* import_cred_by_mech */
1019+
iakerb_gss_get_mic_iov,
1020+
iakerb_gss_verify_mic_iov,
1021+
iakerb_gss_get_mic_iov_length,
1022+
};
1023+
9321024
#ifdef _GSS_STATIC_LINK
9331025
#include "mglueP.h"
9341026
static int gss_iakerbmechglue_init(void)
9351027
{
9361028
struct gss_mech_config mech_iakerb;
937-
struct gss_config iakerb_mechanism = krb5_mechanism;
938-
939-
/* IAKERB mechanism mirrors krb5, but with different context SPIs */
940-
iakerb_mechanism.gss_accept_sec_context = iakerb_gss_accept_sec_context;
941-
iakerb_mechanism.gss_init_sec_context = iakerb_gss_init_sec_context;
942-
iakerb_mechanism.gss_delete_sec_context = iakerb_gss_delete_sec_context;
943-
iakerb_mechanism.gss_acquire_cred = iakerb_gss_acquire_cred;
944-
iakerb_mechanism.gssspi_acquire_cred_with_password
945-
= iakerb_gss_acquire_cred_with_password;
9461029

9471030
memset(&mech_iakerb, 0, sizeof(mech_iakerb));
9481031
mech_iakerb.mech = &iakerb_mechanism;

0 commit comments

Comments
 (0)