1226031Sstas/*- 2226031Sstas * Copyright (c) 2005 Doug Rabson 3226031Sstas * All rights reserved. 4226031Sstas * 5226031Sstas * Redistribution and use in source and binary forms, with or without 6226031Sstas * modification, are permitted provided that the following conditions 7226031Sstas * are met: 8226031Sstas * 1. Redistributions of source code must retain the above copyright 9226031Sstas * notice, this list of conditions and the following disclaimer. 10226031Sstas * 2. Redistributions in binary form must reproduce the above copyright 11226031Sstas * notice, this list of conditions and the following disclaimer in the 12226031Sstas * documentation and/or other materials provided with the distribution. 13226031Sstas * 14226031Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17226031Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24226031Sstas * SUCH DAMAGE. 25226031Sstas * 26226031Sstas * $FreeBSD: src/lib/libgssapi/gss_add_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ 27226031Sstas */ 28226031Sstas 29226031Sstas#include "mech_locl.h" 30226031Sstas 31226031Sstasstruct _gss_mechanism_cred * 32226031Sstas_gss_copy_cred(struct _gss_mechanism_cred *mc) 33226031Sstas{ 34226031Sstas struct _gss_mechanism_cred *new_mc; 35226031Sstas gssapi_mech_interface m = mc->gmc_mech; 36226031Sstas OM_uint32 major_status, minor_status; 37226031Sstas gss_name_t name; 38226031Sstas gss_cred_id_t cred; 39226031Sstas OM_uint32 initiator_lifetime, acceptor_lifetime; 40226031Sstas gss_cred_usage_t cred_usage; 41226031Sstas 42226031Sstas major_status = m->gm_inquire_cred_by_mech(&minor_status, 43226031Sstas mc->gmc_cred, mc->gmc_mech_oid, 44226031Sstas &name, &initiator_lifetime, &acceptor_lifetime, &cred_usage); 45226031Sstas if (major_status) { 46226031Sstas _gss_mg_error(m, major_status, minor_status); 47226031Sstas return (0); 48226031Sstas } 49226031Sstas 50226031Sstas major_status = m->gm_add_cred(&minor_status, 51226031Sstas GSS_C_NO_CREDENTIAL, name, mc->gmc_mech_oid, 52226031Sstas cred_usage, initiator_lifetime, acceptor_lifetime, 53226031Sstas &cred, 0, 0, 0); 54226031Sstas m->gm_release_name(&minor_status, &name); 55226031Sstas 56226031Sstas if (major_status) { 57226031Sstas _gss_mg_error(m, major_status, minor_status); 58226031Sstas return (0); 59226031Sstas } 60226031Sstas 61226031Sstas new_mc = malloc(sizeof(struct _gss_mechanism_cred)); 62226031Sstas if (!new_mc) { 63226031Sstas m->gm_release_cred(&minor_status, &cred); 64226031Sstas return (0); 65226031Sstas } 66226031Sstas new_mc->gmc_mech = m; 67226031Sstas new_mc->gmc_mech_oid = &m->gm_mech_oid; 68226031Sstas new_mc->gmc_cred = cred; 69226031Sstas 70226031Sstas return (new_mc); 71226031Sstas} 72226031Sstas 73226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 74226031Sstasgss_add_cred(OM_uint32 *minor_status, 75226031Sstas const gss_cred_id_t input_cred_handle, 76226031Sstas const gss_name_t desired_name, 77226031Sstas const gss_OID desired_mech, 78226031Sstas gss_cred_usage_t cred_usage, 79226031Sstas OM_uint32 initiator_time_req, 80226031Sstas OM_uint32 acceptor_time_req, 81226031Sstas gss_cred_id_t *output_cred_handle, 82226031Sstas gss_OID_set *actual_mechs, 83226031Sstas OM_uint32 *initiator_time_rec, 84226031Sstas OM_uint32 *acceptor_time_rec) 85226031Sstas{ 86226031Sstas OM_uint32 major_status; 87226031Sstas gssapi_mech_interface m; 88226031Sstas struct _gss_cred *cred = (struct _gss_cred *) input_cred_handle; 89226031Sstas struct _gss_cred *new_cred; 90226031Sstas gss_cred_id_t release_cred; 91226031Sstas struct _gss_mechanism_cred *mc, *target_mc, *copy_mc; 92226031Sstas struct _gss_mechanism_name *mn; 93226031Sstas OM_uint32 junk; 94226031Sstas 95226031Sstas *minor_status = 0; 96226031Sstas *output_cred_handle = GSS_C_NO_CREDENTIAL; 97226031Sstas if (initiator_time_rec) 98226031Sstas *initiator_time_rec = 0; 99226031Sstas if (acceptor_time_rec) 100226031Sstas *acceptor_time_rec = 0; 101226031Sstas if (actual_mechs) 102226031Sstas *actual_mechs = GSS_C_NO_OID_SET; 103226031Sstas 104226031Sstas new_cred = malloc(sizeof(struct _gss_cred)); 105226031Sstas if (!new_cred) { 106226031Sstas *minor_status = ENOMEM; 107226031Sstas return (GSS_S_FAILURE); 108226031Sstas } 109226031Sstas HEIM_SLIST_INIT(&new_cred->gc_mc); 110226031Sstas 111226031Sstas /* 112226031Sstas * We go through all the mc attached to the input_cred_handle 113226031Sstas * and check the mechanism. If it matches, we call 114226031Sstas * gss_add_cred for that mechanism, otherwise we copy the mc 115226031Sstas * to new_cred. 116226031Sstas */ 117226031Sstas target_mc = 0; 118226031Sstas if (cred) { 119226031Sstas HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { 120226031Sstas if (gss_oid_equal(mc->gmc_mech_oid, desired_mech)) { 121226031Sstas target_mc = mc; 122226031Sstas } 123226031Sstas copy_mc = _gss_copy_cred(mc); 124226031Sstas if (!copy_mc) { 125226031Sstas release_cred = (gss_cred_id_t)new_cred; 126226031Sstas gss_release_cred(&junk, &release_cred); 127226031Sstas *minor_status = ENOMEM; 128226031Sstas return (GSS_S_FAILURE); 129226031Sstas } 130226031Sstas HEIM_SLIST_INSERT_HEAD(&new_cred->gc_mc, copy_mc, gmc_link); 131226031Sstas } 132226031Sstas } 133226031Sstas 134226031Sstas /* 135226031Sstas * Figure out a suitable mn, if any. 136226031Sstas */ 137226031Sstas if (desired_name) { 138226031Sstas major_status = _gss_find_mn(minor_status, 139226031Sstas (struct _gss_name *) desired_name, 140226031Sstas desired_mech, 141226031Sstas &mn); 142226031Sstas if (major_status != GSS_S_COMPLETE) { 143226031Sstas free(new_cred); 144226031Sstas return major_status; 145226031Sstas } 146226031Sstas } else { 147226031Sstas mn = 0; 148226031Sstas } 149226031Sstas 150226031Sstas m = __gss_get_mechanism(desired_mech); 151226031Sstas 152226031Sstas mc = malloc(sizeof(struct _gss_mechanism_cred)); 153226031Sstas if (!mc) { 154226031Sstas release_cred = (gss_cred_id_t)new_cred; 155226031Sstas gss_release_cred(&junk, &release_cred); 156226031Sstas *minor_status = ENOMEM; 157226031Sstas return (GSS_S_FAILURE); 158226031Sstas } 159226031Sstas mc->gmc_mech = m; 160226031Sstas mc->gmc_mech_oid = &m->gm_mech_oid; 161226031Sstas 162226031Sstas major_status = m->gm_add_cred(minor_status, 163226031Sstas target_mc ? target_mc->gmc_cred : GSS_C_NO_CREDENTIAL, 164226031Sstas desired_name ? mn->gmn_name : GSS_C_NO_NAME, 165226031Sstas desired_mech, 166226031Sstas cred_usage, 167226031Sstas initiator_time_req, 168226031Sstas acceptor_time_req, 169226031Sstas &mc->gmc_cred, 170226031Sstas actual_mechs, 171226031Sstas initiator_time_rec, 172226031Sstas acceptor_time_rec); 173226031Sstas 174226031Sstas if (major_status) { 175226031Sstas _gss_mg_error(m, major_status, *minor_status); 176226031Sstas release_cred = (gss_cred_id_t)new_cred; 177226031Sstas gss_release_cred(&junk, &release_cred); 178226031Sstas free(mc); 179226031Sstas return (major_status); 180226031Sstas } 181226031Sstas HEIM_SLIST_INSERT_HEAD(&new_cred->gc_mc, mc, gmc_link); 182226031Sstas *output_cred_handle = (gss_cred_id_t) new_cred; 183226031Sstas 184226031Sstas return (GSS_S_COMPLETE); 185226031Sstas} 186226031Sstas 187