Path: blob/main/crypto/krb5/src/lib/gssapi/mechglue/g_negoex.c
39586 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/*2* Copyright (C) 2011 by the Massachusetts Institute of Technology.3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* * Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* * Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in14* the documentation and/or other materials provided with the15* distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS18* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT19* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS20* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE21* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,22* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES23* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR24* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,26* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)27* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED28* OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This file contains dispatch functions for the three GSSAPI extensions33* described in draft-zhu-negoex-04, renamed to use the gssspi_ prefix. Since34* the only caller of these functions is SPNEGO, argument validation is35* omitted.36*/3738#include "mglueP.h"3940OM_uint32 KRB5_CALLCONV41gssspi_query_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid,42gss_cred_id_t cred_handle, gss_ctx_id_t *context_handle,43const gss_name_t targ_name, OM_uint32 req_flags,44gss_buffer_t meta_data)45{46OM_uint32 status, minor;47gss_union_ctx_id_t ctx = (gss_union_ctx_id_t)*context_handle;48gss_union_cred_t cred = (gss_union_cred_t)cred_handle;49gss_union_name_t union_name = (gss_union_name_t)targ_name;50gss_mechanism mech;51gss_OID selected_mech, public_mech;52gss_cred_id_t internal_cred = GSS_C_NO_CREDENTIAL;53gss_name_t internal_name = GSS_C_NO_NAME, imported_name = GSS_C_NO_NAME;54gss_ctx_id_t new_ctx = GSS_C_NO_CONTEXT, *internal_ctx;5556*minor_status = 0;57meta_data->length = 0;58meta_data->value = NULL;5960status = gssint_select_mech_type(minor_status, mech_oid, &selected_mech);61if (status != GSS_S_COMPLETE)62return status;63public_mech = gssint_get_public_oid(selected_mech);6465mech = gssint_get_mechanism(selected_mech);66if (mech == NULL)67return GSS_S_BAD_MECH;68if (mech->gssspi_query_meta_data == NULL)69return GSS_S_UNAVAILABLE;7071if (cred != NULL) {72internal_cred = gssint_get_mechanism_cred(cred, selected_mech);73if (internal_cred == GSS_C_NO_CREDENTIAL)74return GSS_S_NO_CRED;75}7677if (union_name != NULL) {78if (union_name->mech_type != GSS_C_NO_OID &&79g_OID_equal(union_name->mech_type, selected_mech)) {80internal_name = union_name->mech_name;81} else {82status = gssint_import_internal_name(minor_status, selected_mech,83union_name, &imported_name);84if (status != GSS_S_COMPLETE)85goto cleanup;86internal_name = imported_name;87}88}8990internal_ctx = (ctx != NULL) ? &ctx->internal_ctx_id : &new_ctx;91status = mech->gssspi_query_meta_data(minor_status, public_mech,92internal_cred, internal_ctx,93internal_name, req_flags, meta_data);94if (status != GSS_S_COMPLETE) {95map_error(minor_status, mech);96goto cleanup;97}9899/* If the mech created a context, wrap it in a union context. */100if (new_ctx != GSS_C_NO_CONTEXT) {101assert(ctx == NULL);102status = gssint_create_union_context(minor_status, selected_mech,103&ctx);104if (status != GSS_S_COMPLETE)105goto cleanup;106107ctx->internal_ctx_id = new_ctx;108new_ctx = GSS_C_NO_CONTEXT;109*context_handle = (gss_ctx_id_t)ctx;110}111112cleanup:113if (imported_name != GSS_C_NO_NAME) {114(void)gssint_release_internal_name(&minor, selected_mech,115&imported_name);116}117if (new_ctx != GSS_C_NO_CONTEXT) {118(void)gssint_delete_internal_sec_context(&minor, &mech->mech_type,119&new_ctx, GSS_C_NO_BUFFER);120}121return status;122}123124OM_uint32 KRB5_CALLCONV125gssspi_exchange_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid,126gss_cred_id_t cred_handle,127gss_ctx_id_t *context_handle,128const gss_name_t targ_name, OM_uint32 req_flags,129gss_const_buffer_t meta_data)130{131OM_uint32 status, minor;132gss_union_ctx_id_t ctx = (gss_union_ctx_id_t)*context_handle;133gss_union_cred_t cred = (gss_union_cred_t)cred_handle;134gss_union_name_t union_name = (gss_union_name_t)targ_name;135gss_mechanism mech;136gss_OID selected_mech, public_mech;137gss_cred_id_t internal_cred = GSS_C_NO_CREDENTIAL;138gss_name_t internal_name = GSS_C_NO_NAME, imported_name = GSS_C_NO_NAME;139gss_ctx_id_t new_ctx = GSS_C_NO_CONTEXT, *internal_ctx;140141*minor_status = 0;142143status = gssint_select_mech_type(minor_status, mech_oid, &selected_mech);144if (status != GSS_S_COMPLETE)145return status;146public_mech = gssint_get_public_oid(selected_mech);147148mech = gssint_get_mechanism(selected_mech);149if (mech == NULL)150return GSS_S_BAD_MECH;151if (mech->gssspi_exchange_meta_data == NULL)152return GSS_S_UNAVAILABLE;153154if (cred != NULL) {155internal_cred = gssint_get_mechanism_cred(cred, selected_mech);156if (internal_cred == GSS_C_NO_CREDENTIAL)157return GSS_S_NO_CRED;158}159160if (union_name != NULL) {161if (union_name->mech_type != GSS_C_NO_OID &&162g_OID_equal(union_name->mech_type, selected_mech)) {163internal_name = union_name->mech_name;164} else {165status = gssint_import_internal_name(minor_status, selected_mech,166union_name, &imported_name);167if (GSS_ERROR(status))168return status;169internal_name = imported_name;170}171}172173internal_ctx = (ctx != NULL) ? &ctx->internal_ctx_id : &new_ctx;174status = mech->gssspi_exchange_meta_data(minor_status, public_mech,175internal_cred, internal_ctx,176internal_name, req_flags,177meta_data);178if (status != GSS_S_COMPLETE) {179map_error(minor_status, mech);180goto cleanup;181}182183/* If the mech created a context, wrap it in a union context. */184if (new_ctx != GSS_C_NO_CONTEXT) {185assert(ctx == NULL);186status = gssint_create_union_context(minor_status, selected_mech,187&ctx);188if (status != GSS_S_COMPLETE)189goto cleanup;190191ctx->internal_ctx_id = new_ctx;192new_ctx = GSS_C_NO_CONTEXT;193*context_handle = (gss_ctx_id_t)ctx;194}195196cleanup:197if (imported_name != GSS_C_NO_NAME) {198(void)gssint_release_internal_name(&minor, selected_mech,199&imported_name);200}201if (new_ctx != GSS_C_NO_CONTEXT) {202(void)gssint_delete_internal_sec_context(&minor, &mech->mech_type,203&new_ctx, GSS_C_NO_BUFFER);204}205return status;206}207208OM_uint32 KRB5_CALLCONV209gssspi_query_mechanism_info(OM_uint32 *minor_status, gss_const_OID mech_oid,210unsigned char auth_scheme[16])211{212OM_uint32 status;213gss_OID selected_mech, public_mech;214gss_mechanism mech;215216*minor_status = 0;217memset(auth_scheme, 0, 16);218219status = gssint_select_mech_type(minor_status, mech_oid, &selected_mech);220if (status != GSS_S_COMPLETE)221return status;222public_mech = gssint_get_public_oid(selected_mech);223224mech = gssint_get_mechanism(selected_mech);225if (mech == NULL)226return GSS_S_BAD_MECH;227if (mech->gssspi_query_mechanism_info == NULL)228return GSS_S_UNAVAILABLE;229230status = mech->gssspi_query_mechanism_info(minor_status, public_mech,231auth_scheme);232if (GSS_ERROR(status))233map_error(minor_status, mech);234235return status;236}237238239