diff --git a/lib/gssapi/krb5/get_mic.c b/lib/gssapi/krb5/get_mic.c index 0c74778f8..02b1fc947 100644 --- a/lib/gssapi/krb5/get_mic.c +++ b/lib/gssapi/krb5/get_mic.c @@ -283,7 +283,9 @@ OM_uint32 _gsskrb5_get_mic OM_uint32 ret; krb5_keytype keytype; - ret = _gsskrb5i_get_subkey(ctx, &key); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (ret) { _gsskrb5_set_error_string (); *minor_status = ret; diff --git a/lib/gssapi/krb5/inquire_sec_context_by_oid.c b/lib/gssapi/krb5/inquire_sec_context_by_oid.c index c2e1630a7..9352dd943 100644 --- a/lib/gssapi/krb5/inquire_sec_context_by_oid.c +++ b/lib/gssapi/krb5/inquire_sec_context_by_oid.c @@ -100,6 +100,75 @@ static OM_uint32 inquire_sec_context_tkt_flags data_set); } +enum keytype { ACCEPTOR_KEY, INITIATOR_KEY, TOKEN_KEY }; + +static OM_uint32 inquire_sec_context_get_subkey + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + enum keytype keytype, + gss_buffer_set_t *data_set) +{ + krb5_keyblock *key = NULL; + krb5_storage *sp = NULL; + krb5_data data; + OM_uint32 maj_stat = GSS_S_COMPLETE; + krb5_error_code ret = EINVAL; + + krb5_data_zero(&data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + ret = ENOMEM; + goto out; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + switch(keytype) { + case ACCEPTOR_KEY: + ret = _gsskrb5i_get_acceptor_subkey(context_handle, &key); + break; + case INITIATOR_KEY: + ret = _gsskrb5i_get_initiator_subkey(context_handle, &key); + break; + case TOKEN_KEY: + ret = _gsskrb5i_get_token_key(context_handle, &key); + break; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (ret) + goto out; + + ret = krb5_store_keyblock(sp, *key); + krb5_free_keyblock (_gsskrb5_context, key); + if (ret) + goto out; + + ret = krb5_storage_to_data(sp, &data); + if (ret) + goto out; + + { + gss_buffer_desc value; + + value.length = data.length; + value.value = data.data; + + maj_stat = gss_add_buffer_set_member(minor_status, + &value, + data_set); + } + +out: + krb5_data_free(&data); + if (sp) + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + maj_stat = GSS_S_FAILURE; + } + return maj_stat; +} + static OM_uint32 inquire_sec_context_authz_data (OM_uint32 *minor_status, const gsskrb5_ctx context_handle, @@ -227,7 +296,9 @@ export_lucid_sec_context_v1(OM_uint32 *minor_status, ret = krb5_store_int32(sp, (is_cfx) ? 1 : 0); if (ret) goto out; - ret = _gsskrb5i_get_subkey(context_handle, &key); + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(context_handle, &key); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); if (ret) goto out; if (is_cfx == 0) { @@ -328,6 +399,21 @@ OM_uint32 _gsskrb5_inquire_sec_context_by_oid return inquire_sec_context_has_updated_spnego(minor_status, ctx, data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + TOKEN_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_INITIATOR_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + INITIATOR_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_ACCEPTOR_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + ACCEPTOR_SUBKEY, + data_set); } else if (oid_prefix_equal(desired_object, GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X, &suffix)) { diff --git a/lib/gssapi/krb5/unwrap.c b/lib/gssapi/krb5/unwrap.c index 752f75479..e8a400886 100644 --- a/lib/gssapi/krb5/unwrap.c +++ b/lib/gssapi/krb5/unwrap.c @@ -376,7 +376,9 @@ OM_uint32 _gsskrb5_unwrap if (qop_state != NULL) *qop_state = GSS_C_QOP_DEFAULT; - ret = _gsskrb5i_get_subkey(ctx, &key); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (ret) { _gsskrb5_set_error_string (); *minor_status = ret; diff --git a/lib/gssapi/krb5/verify_mic.c b/lib/gssapi/krb5/verify_mic.c index c829a6146..79dd110e3 100644 --- a/lib/gssapi/krb5/verify_mic.c +++ b/lib/gssapi/krb5/verify_mic.c @@ -278,7 +278,9 @@ _gsskrb5_verify_mic_internal OM_uint32 ret; krb5_keytype keytype; - ret = _gsskrb5i_get_subkey(context_handle, &key); + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(context_handle, &key); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); if (ret) { _gsskrb5_set_error_string (); *minor_status = ret; diff --git a/lib/gssapi/krb5/wrap.c b/lib/gssapi/krb5/wrap.c index 8d755c944..e9694c085 100644 --- a/lib/gssapi/krb5/wrap.c +++ b/lib/gssapi/krb5/wrap.c @@ -35,46 +35,64 @@ RCSID("$Id$"); -OM_uint32 -_gsskrb5i_get_subkey(const gsskrb5_ctx ctx, - krb5_keyblock **key) -{ - krb5_keyblock *skey = NULL; +/* + * Return initiator subkey, or if that doesn't exists, the subkey. + */ + +krb5_error_code +_gsskrb5i_get_initiator_subkey(const gsskrb5_ctx ctx, krb5_keyblock **key) +{ + krb5_error_code ret; + *key = NULL; - HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); if (ctx->more_flags & LOCAL) { - krb5_auth_con_getremotesubkey(_gsskrb5_context, - ctx->auth_context, - &skey); - } else { - krb5_auth_con_getlocalsubkey(_gsskrb5_context, + ret = krb5_auth_con_getlocalsubkey(_gsskrb5_context, ctx->auth_context, - &skey); + key); + } else { + ret = krb5_auth_con_getremotesubkey(_gsskrb5_context, + ctx->auth_context, + key); } - /* - * Only use the initiator subkey or ticket session key if - * an acceptor subkey was not required. - */ - if (skey == NULL && - (ctx->more_flags & ACCEPTOR_SUBKEY) == 0) { - if (ctx->more_flags & LOCAL) { - krb5_auth_con_getlocalsubkey(_gsskrb5_context, - ctx->auth_context, - &skey); - } else { - krb5_auth_con_getremotesubkey(_gsskrb5_context, - ctx->auth_context, - &skey); - } - if(skey == NULL) - krb5_auth_con_getkey(_gsskrb5_context, - ctx->auth_context, - &skey); + if (*key == NULL) + ret = krb5_auth_con_getkey(_gsskrb5_context, + ctx->auth_context, + key); + return ret; +} + +krb5_error_code +_gsskrb5i_get_acceptor_subkey(const gsskrb5_ctx ctx, krb5_keyblock **key) +{ + krb5_error_code ret; + *key = NULL; + + if (ctx->more_flags & LOCAL) { + ret = krb5_auth_con_getremotesubkey(_gsskrb5_context, + ctx->auth_context, + key); + } else { + ret = krb5_auth_con_getlocalsubkey(_gsskrb5_context, + ctx->auth_context, + key); } - HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - if(skey == NULL) - return GSS_KRB5_S_KG_NO_SUBKEY; /* XXX */ - *key = skey; + return ret; +} + +OM_uint32 +_gsskrb5i_get_token_key(const gsskrb5_ctx ctx, krb5_keyblock **key) +{ + _gsskrb5i_get_acceptor_subkey(ctx, key); + if(*key == NULL) { + /* + * Only use the initiator subkey or ticket session key if an + * acceptor subkey was not required. + */ + if ((ctx->more_flags & ACCEPTOR_SUBKEY) == 0) + _gsskrb5i_get_initiator_subkey(ctx, key); + } + if (*key == NULL) + return GSS_KRB5_S_KG_NO_SUBKEY; return 0; } @@ -117,7 +135,9 @@ _gsskrb5_wrap_size_limit ( krb5_keytype keytype; const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; - ret = _gsskrb5i_get_subkey(ctx, &key); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (ret) { _gsskrb5_set_error_string (); *minor_status = ret; @@ -476,7 +496,9 @@ OM_uint32 _gsskrb5_wrap krb5_keytype keytype; const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; - ret = _gsskrb5i_get_subkey(ctx, &key); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (ret) { _gsskrb5_set_error_string (); *minor_status = ret;