From 20b067232c03ce7f63bd883ff5fafc2efd04cb36 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 3 Apr 2023 11:27:02 -0400 Subject: Add GSS_C_INQ_ODBC_SESSION_KEY The Oracle database wire protocol contains a cipher reinitialization operation using the ticket session key. Add a query operation (similar to GSS_C_INQ_SSPI_SESSION_KEY) to retrieve the ticket session key rather than the subkey. ticket: 9091 (new) --- src/lib/gssapi/generic/gssapi_ext.h | 7 +++ src/lib/gssapi/generic/gssapi_generic.c | 10 ++++ src/lib/gssapi/krb5/gssapiP_krb5.h | 6 ++- src/lib/gssapi/krb5/gssapi_krb5.c | 6 ++- src/lib/gssapi/krb5/inq_context.c | 95 +++++++++++++++++++++++---------- 5 files changed, 93 insertions(+), 31 deletions(-) diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h index c675e8e..38e3961 100644 --- a/src/lib/gssapi/generic/gssapi_ext.h +++ b/src/lib/gssapi/generic/gssapi_ext.h @@ -237,6 +237,13 @@ OM_uint32 KRB5_CALLCONV gss_unwrap_aead */ GSS_DLLIMP extern gss_OID GSS_C_INQ_SSPI_SESSION_KEY; +/* + * Returns a buffer set with the first member containing the ticket session key + * for ODBC compatibility. The optional second member contains an OID + * identifying the session key type. + */ +GSS_DLLIMP extern gss_OID GSS_C_INQ_ODBC_SESSION_KEY; + GSS_DLLIMP extern gss_OID GSS_C_INQ_NEGOEX_KEY; GSS_DLLIMP extern gss_OID GSS_C_INQ_NEGOEX_VERIFY_KEY; diff --git a/src/lib/gssapi/generic/gssapi_generic.c b/src/lib/gssapi/generic/gssapi_generic.c index 3601585..7fbecbe 100644 --- a/src/lib/gssapi/generic/gssapi_generic.c +++ b/src/lib/gssapi/generic/gssapi_generic.c @@ -170,6 +170,14 @@ static const gss_OID_desc const_oids[] = { * infosys(1) gssapi(2) krb5(2) krb5-gssapi-ext(5) sasl-ssf(15) */ {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"}, + + /* + * GSS_C_INQ_ODBC_SESSION_KEY 1.2.840.113554.1.2.2.5.19 + * iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) ssapi(2) krb5(2) krb5-gssapi-ext(5) + * inq-odbc-session-key(19) + */ + {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05\13"}, }; /* Here are the constants which point to the static structure above. @@ -235,6 +243,8 @@ GSS_DLLIMP gss_const_OID GSS_C_MA_NEGOEX_AND_SPNEGO = oids+38; GSS_DLLIMP gss_OID GSS_C_SEC_CONTEXT_SASL_SSF = oids+39; +GSS_DLLIMP gss_OID GSS_C_INQ_ODBC_SESSION_KEY = oids+40; + static gss_OID_set_desc gss_ma_known_attrs_desc = { 28, oids+11 }; gss_OID_set gss_ma_known_attrs = &gss_ma_known_attrs_desc; diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index a444653..7364607 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -1079,9 +1079,13 @@ gss_krb5int_ccache_name(OM_uint32 *minor_status, const gss_OID, const gss_OID, #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" +#define GSS_KRB5_INQ_ODBC_SESSION_KEY_OID_LENGTH 11 +#define GSS_KRB5_INQ_ODBC_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x13" OM_uint32 -gss_krb5int_inq_session_key(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); +gss_krb5int_inq_sspi_session_key(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); +OM_uint32 +gss_krb5int_inq_odbc_session_key(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); #define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH 11 #define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x04" diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index 9915a8b..1e62b07 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -337,7 +337,11 @@ static struct { }, { {GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_SSPI_SESSION_KEY_OID}, - gss_krb5int_inq_session_key + gss_krb5int_inq_sspi_session_key + }, + { + {GSS_KRB5_INQ_ODBC_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_ODBC_SESSION_KEY_OID}, + gss_krb5int_inq_odbc_session_key }, { {GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID}, diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c index 51be202..97678e3 100644 --- a/src/lib/gssapi/krb5/inq_context.c +++ b/src/lib/gssapi/krb5/inq_context.c @@ -186,58 +186,95 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name, return GSS_S_COMPLETE; } -OM_uint32 -gss_krb5int_inq_session_key( - OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - const gss_OID desired_object, - gss_buffer_set_t *data_set) +/* Add two buffers to data_set giving the contents and enctype of key. */ +static OM_uint32 +inq_session_key_result(OM_uint32 *minor_status, krb5_key key, + gss_buffer_set_t *data_set) { - krb5_gss_ctx_id_rec *ctx; - krb5_key key; gss_buffer_desc keyvalue, keyinfo; - OM_uint32 major_status, minor; + OM_uint32 major, tmpmin; unsigned char oid_buf[GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH + 6]; gss_OID_desc oid; - ctx = (krb5_gss_ctx_id_rec *) context_handle; - key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey; - keyvalue.value = key->keyblock.contents; keyvalue.length = key->keyblock.length; - - major_status = generic_gss_add_buffer_set_member(minor_status, &keyvalue, data_set); - if (GSS_ERROR(major_status)) + major = generic_gss_add_buffer_set_member(minor_status, &keyvalue, + data_set); + if (GSS_ERROR(major)) goto cleanup; oid.elements = oid_buf; oid.length = sizeof(oid_buf); - - major_status = generic_gss_oid_compose(minor_status, - GSS_KRB5_SESSION_KEY_ENCTYPE_OID, - GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH, - key->keyblock.enctype, - &oid); - if (GSS_ERROR(major_status)) + major = generic_gss_oid_compose(minor_status, + GSS_KRB5_SESSION_KEY_ENCTYPE_OID, + GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH, + key->keyblock.enctype, &oid); + if (GSS_ERROR(major)) goto cleanup; keyinfo.value = oid.elements; keyinfo.length = oid.length; - - major_status = generic_gss_add_buffer_set_member(minor_status, &keyinfo, data_set); - if (GSS_ERROR(major_status)) + major = generic_gss_add_buffer_set_member(minor_status, &keyinfo, + data_set); + if (GSS_ERROR(major)) goto cleanup; return GSS_S_COMPLETE; cleanup: if (*data_set != GSS_C_NO_BUFFER_SET) { - if ((*data_set)->count != 0) - memset((*data_set)->elements[0].value, 0, (*data_set)->elements[0].length); - gss_release_buffer_set(&minor, data_set); + if ((*data_set)->count != 0) { + zap((*data_set)->elements[0].value, + (*data_set)->elements[0].length); + } + gss_release_buffer_set(&tmpmin, data_set); } - return major_status; + return major; +} + +OM_uint32 +gss_krb5int_inq_sspi_session_key(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_t ctx = (krb5_gss_ctx_id_t)context_handle; + krb5_key key; + + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey; + return inq_session_key_result(minor_status, key, data_set); +} + +OM_uint32 +gss_krb5int_inq_odbc_session_key(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 major; + krb5_error_code ret; + krb5_gss_ctx_id_t ctx = (krb5_gss_ctx_id_t)context_handle; + krb5_key key; + + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + ret = krb5_auth_con_getkey_k(ctx->k5_context, ctx->auth_context, &key); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + major = inq_session_key_result(minor_status, key, data_set); + krb5_k_free_key(ctx->k5_context, key); + return major; } OM_uint32 -- cgit v1.1