Path: blob/main/crypto/krb5/src/lib/gssapi/mechglue/g_imp_cred.c
39586 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* lib/gssapi/mechglue/g_imp_cred.c - gss_import_cred definition */2/*3* Copyright (C) 2012 by the Massachusetts Institute of Technology.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9*10* * Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12*13* * Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in15* the documentation and/or other materials provided with the16* distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS19* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT20* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS21* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE22* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,23* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES24* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR25* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,27* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED29* OF THE POSSIBILITY OF SUCH DAMAGE.30*/3132#include "mglueP.h"3334static OM_uint3235val_imp_cred_args(OM_uint32 *minor_status, gss_buffer_t token,36gss_cred_id_t *cred_handle)37{38/* Initialize outputs. */39if (minor_status != NULL)40*minor_status = 0;41if (cred_handle != NULL)42*cred_handle = GSS_C_NO_CREDENTIAL;4344/* Validate arguments. */45if (minor_status == NULL)46return GSS_S_CALL_INACCESSIBLE_WRITE;47if (cred_handle == NULL)48return GSS_S_CALL_INACCESSIBLE_WRITE;49if (token == GSS_C_NO_BUFFER)50return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN;51if (GSS_EMPTY_BUFFER(token))52return GSS_S_DEFECTIVE_TOKEN;53return GSS_S_COMPLETE;54}5556/* Populate mech_oid and mech_token with the next entry in token, using aliased57* memory from token. Advance token by the amount consumed. */58static OM_uint3259get_entry(OM_uint32 *minor_status, gss_buffer_t token, gss_OID mech_oid,60gss_buffer_t mech_token)61{62OM_uint32 len;6364/* Get the mechanism OID. */65if (token->length < 4)66return GSS_S_DEFECTIVE_TOKEN;67len = load_32_be(token->value);68if (token->length - 4 < len)69return GSS_S_DEFECTIVE_TOKEN;70mech_oid->length = len;71mech_oid->elements = (char *)token->value + 4;72token->value = (char *)token->value + 4 + len;73token->length -= 4 + len;7475/* Get the mechanism token. */76if (token->length < 4)77return GSS_S_DEFECTIVE_TOKEN;78len = load_32_be(token->value);79if (token->length - 4 < len)80return GSS_S_DEFECTIVE_TOKEN;81mech_token->length = len;82mech_token->value = (char *)token->value + 4;83token->value = (char *)token->value + 4 + len;84token->length -= 4 + len;8586return GSS_S_COMPLETE;87}8889OM_uint32 KRB5_CALLCONV90gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token,91gss_cred_id_t *cred_handle)92{93OM_uint32 status, tmpmin, count;94gss_union_cred_t cred = NULL;95gss_mechanism mech;96gss_buffer_desc tok, mech_token;97gss_OID_desc mech_oid;98gss_OID selected_mech;99gss_cred_id_t mech_cred;100void *elemcopy;101102status = val_imp_cred_args(minor_status, token, cred_handle);103if (status != GSS_S_COMPLETE)104return status;105106/* Count the entries in token. */107for (tok = *token, count = 0; tok.length > 0; count++) {108status = get_entry(minor_status, &tok, &mech_oid, &mech_token);109if (status != GSS_S_COMPLETE)110return status;111}112113/* Allocate a union credential. */114cred = calloc(1, sizeof(*cred));115if (cred == NULL)116goto oom;117cred->loopback = cred;118cred->count = 0;119cred->mechs_array = calloc(count, sizeof(*cred->mechs_array));120if (cred->mechs_array == NULL)121goto oom;122cred->cred_array = calloc(count, sizeof(*cred->cred_array));123if (cred->cred_array == NULL)124goto oom;125126tok = *token;127while (tok.length > 0) {128(void)get_entry(minor_status, &tok, &mech_oid, &mech_token);129130/* Import this entry's mechanism token. */131status = gssint_select_mech_type(minor_status, &mech_oid,132&selected_mech);133if (status != GSS_S_COMPLETE)134goto error;135mech = gssint_get_mechanism(selected_mech);136if (mech == NULL || (mech->gss_import_cred == NULL &&137mech->gssspi_import_cred_by_mech == NULL)) {138status = GSS_S_DEFECTIVE_TOKEN;139goto error;140}141if (mech->gssspi_import_cred_by_mech) {142status = mech->gssspi_import_cred_by_mech(minor_status,143gssint_get_public_oid(selected_mech),144&mech_token, &mech_cred);145} else {146status = mech->gss_import_cred(minor_status, &mech_token,147&mech_cred);148}149if (status != GSS_S_COMPLETE) {150map_error(minor_status, mech);151goto error;152}153154/* Add the resulting mechanism cred to the union cred. */155elemcopy = malloc(selected_mech->length);156if (elemcopy == NULL) {157if (mech->gss_release_cred != NULL)158mech->gss_release_cred(&tmpmin, &mech_cred);159goto oom;160}161memcpy(elemcopy, selected_mech->elements, selected_mech->length);162cred->mechs_array[cred->count].length = selected_mech->length;163cred->mechs_array[cred->count].elements = elemcopy;164cred->cred_array[cred->count++] = mech_cred;165}166167*cred_handle = cred;168return GSS_S_COMPLETE;169170oom:171status = GSS_S_FAILURE;172*minor_status = ENOMEM;173error:174(void)gss_release_cred(&tmpmin, &cred);175return status;176}177178179