1153838Sdfr/*- 2153838Sdfr * Copyright (c) 2005 Doug Rabson 3153838Sdfr * All rights reserved. 4153838Sdfr * 5153838Sdfr * Redistribution and use in source and binary forms, with or without 6153838Sdfr * modification, are permitted provided that the following conditions 7153838Sdfr * are met: 8153838Sdfr * 1. Redistributions of source code must retain the above copyright 9153838Sdfr * notice, this list of conditions and the following disclaimer. 10153838Sdfr * 2. Redistributions in binary form must reproduce the above copyright 11153838Sdfr * notice, this list of conditions and the following disclaimer in the 12153838Sdfr * documentation and/or other materials provided with the distribution. 13153838Sdfr * 14153838Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15153838Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16153838Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17153838Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18153838Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19153838Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20153838Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21153838Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22153838Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23153838Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24153838Sdfr * SUCH DAMAGE. 25153838Sdfr * 26153838Sdfr * $FreeBSD$ 27153838Sdfr */ 28153838Sdfr 29153838Sdfr#include <gssapi/gssapi.h> 30168340Skan#include <stdlib.h> 31153838Sdfr#include <errno.h> 32153838Sdfr 33153838Sdfr#include "mech_switch.h" 34153838Sdfr#include "cred.h" 35153838Sdfr#include "name.h" 36178828Sdfr#include "utils.h" 37153838Sdfr 38153838Sdfrstatic struct _gss_mechanism_cred * 39153838Sdfr_gss_copy_cred(struct _gss_mechanism_cred *mc) 40153838Sdfr{ 41153838Sdfr struct _gss_mechanism_cred *new_mc; 42153838Sdfr struct _gss_mech_switch *m = mc->gmc_mech; 43153838Sdfr OM_uint32 major_status, minor_status; 44153838Sdfr gss_name_t name; 45153838Sdfr gss_cred_id_t cred; 46153838Sdfr OM_uint32 initiator_lifetime, acceptor_lifetime; 47153838Sdfr gss_cred_usage_t cred_usage; 48153838Sdfr 49153838Sdfr major_status = m->gm_inquire_cred_by_mech(&minor_status, 50153838Sdfr mc->gmc_cred, mc->gmc_mech_oid, 51153838Sdfr &name, &initiator_lifetime, &acceptor_lifetime, &cred_usage); 52178828Sdfr if (major_status) { 53178828Sdfr _gss_mg_error(m, major_status, minor_status); 54153838Sdfr return (0); 55178828Sdfr } 56153838Sdfr 57153838Sdfr major_status = m->gm_add_cred(&minor_status, 58153838Sdfr GSS_C_NO_CREDENTIAL, name, mc->gmc_mech_oid, 59153838Sdfr cred_usage, initiator_lifetime, acceptor_lifetime, 60153838Sdfr &cred, 0, 0, 0); 61153838Sdfr m->gm_release_name(&minor_status, &name); 62153838Sdfr 63178828Sdfr if (major_status) { 64178828Sdfr _gss_mg_error(m, major_status, minor_status); 65153838Sdfr return (0); 66178828Sdfr } 67153838Sdfr 68153838Sdfr new_mc = malloc(sizeof(struct _gss_mechanism_cred)); 69153838Sdfr if (!new_mc) { 70153838Sdfr m->gm_release_cred(&minor_status, &cred); 71153838Sdfr return (0); 72153838Sdfr } 73153838Sdfr new_mc->gmc_mech = m; 74153838Sdfr new_mc->gmc_mech_oid = &m->gm_mech_oid; 75153838Sdfr new_mc->gmc_cred = cred; 76153838Sdfr 77153838Sdfr return (new_mc); 78153838Sdfr} 79153838Sdfr 80153838SdfrOM_uint32 81153838Sdfrgss_add_cred(OM_uint32 *minor_status, 82153838Sdfr const gss_cred_id_t input_cred_handle, 83153838Sdfr const gss_name_t desired_name, 84153838Sdfr const gss_OID desired_mech, 85153838Sdfr gss_cred_usage_t cred_usage, 86153838Sdfr OM_uint32 initiator_time_req, 87153838Sdfr OM_uint32 acceptor_time_req, 88153838Sdfr gss_cred_id_t *output_cred_handle, 89153838Sdfr gss_OID_set *actual_mechs, 90153838Sdfr OM_uint32 *initiator_time_rec, 91153838Sdfr OM_uint32 *acceptor_time_rec) 92153838Sdfr{ 93153838Sdfr OM_uint32 major_status; 94153838Sdfr struct _gss_mech_switch *m; 95153838Sdfr struct _gss_cred *cred = (struct _gss_cred *) input_cred_handle; 96153838Sdfr struct _gss_cred *new_cred; 97178828Sdfr gss_cred_id_t release_cred; 98153838Sdfr struct _gss_mechanism_cred *mc, *target_mc, *copy_mc; 99153838Sdfr struct _gss_mechanism_name *mn; 100178828Sdfr OM_uint32 junk; 101153838Sdfr 102153838Sdfr *minor_status = 0; 103178828Sdfr *output_cred_handle = GSS_C_NO_CREDENTIAL; 104178828Sdfr if (initiator_time_rec) 105178828Sdfr *initiator_time_rec = 0; 106178828Sdfr if (acceptor_time_rec) 107178828Sdfr *acceptor_time_rec = 0; 108178828Sdfr if (actual_mechs) 109178828Sdfr *actual_mechs = GSS_C_NO_OID_SET; 110153838Sdfr 111153838Sdfr new_cred = malloc(sizeof(struct _gss_cred)); 112153838Sdfr if (!new_cred) { 113153838Sdfr *minor_status = ENOMEM; 114153838Sdfr return (GSS_S_FAILURE); 115153838Sdfr } 116153838Sdfr SLIST_INIT(&new_cred->gc_mc); 117153838Sdfr 118153838Sdfr /* 119153838Sdfr * We go through all the mc attached to the input_cred_handle 120153838Sdfr * and check the mechanism. If it matches, we call 121153838Sdfr * gss_add_cred for that mechanism, otherwise we copy the mc 122153838Sdfr * to new_cred. 123153838Sdfr */ 124298314Spfg target_mc = NULL; 125153838Sdfr if (cred) { 126153838Sdfr SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { 127178828Sdfr if (gss_oid_equal(mc->gmc_mech_oid, desired_mech)) { 128153838Sdfr target_mc = mc; 129153838Sdfr } 130153838Sdfr copy_mc = _gss_copy_cred(mc); 131153838Sdfr if (!copy_mc) { 132178828Sdfr release_cred = (gss_cred_id_t) new_cred; 133178828Sdfr gss_release_cred(&junk, &release_cred); 134153838Sdfr *minor_status = ENOMEM; 135153838Sdfr return (GSS_S_FAILURE); 136153838Sdfr } 137153838Sdfr SLIST_INSERT_HEAD(&new_cred->gc_mc, copy_mc, gmc_link); 138153838Sdfr } 139153838Sdfr } 140153838Sdfr 141153838Sdfr /* 142153838Sdfr * Figure out a suitable mn, if any. 143153838Sdfr */ 144153838Sdfr if (desired_name) { 145178828Sdfr major_status = _gss_find_mn(minor_status, 146178828Sdfr (struct _gss_name *) desired_name, 147178828Sdfr desired_mech, 148178828Sdfr &mn); 149178828Sdfr if (major_status != GSS_S_COMPLETE) { 150153838Sdfr free(new_cred); 151178828Sdfr return (major_status); 152153838Sdfr } 153153838Sdfr } else { 154298314Spfg mn = NULL; 155153838Sdfr } 156153838Sdfr 157153838Sdfr m = _gss_find_mech_switch(desired_mech); 158153838Sdfr 159153838Sdfr mc = malloc(sizeof(struct _gss_mechanism_cred)); 160153838Sdfr if (!mc) { 161178828Sdfr release_cred = (gss_cred_id_t) new_cred; 162178828Sdfr gss_release_cred(&junk, &release_cred); 163153838Sdfr *minor_status = ENOMEM; 164153838Sdfr return (GSS_S_FAILURE); 165153838Sdfr } 166153838Sdfr mc->gmc_mech = m; 167153838Sdfr mc->gmc_mech_oid = &m->gm_mech_oid; 168153838Sdfr 169153838Sdfr major_status = m->gm_add_cred(minor_status, 170153838Sdfr target_mc ? target_mc->gmc_cred : GSS_C_NO_CREDENTIAL, 171153838Sdfr desired_name ? mn->gmn_name : GSS_C_NO_NAME, 172153838Sdfr desired_mech, 173153838Sdfr cred_usage, 174153838Sdfr initiator_time_req, 175153838Sdfr acceptor_time_req, 176153838Sdfr &mc->gmc_cred, 177153838Sdfr actual_mechs, 178153838Sdfr initiator_time_rec, 179153838Sdfr acceptor_time_rec); 180153838Sdfr 181153838Sdfr if (major_status) { 182178828Sdfr _gss_mg_error(m, major_status, *minor_status); 183178828Sdfr release_cred = (gss_cred_id_t) new_cred; 184178828Sdfr gss_release_cred(&junk, &release_cred); 185153838Sdfr free(mc); 186153838Sdfr return (major_status); 187153838Sdfr } 188153838Sdfr SLIST_INSERT_HEAD(&new_cred->gc_mc, mc, gmc_link); 189153838Sdfr *output_cred_handle = (gss_cred_id_t) new_cred; 190153838Sdfr 191153838Sdfr return (GSS_S_COMPLETE); 192153838Sdfr} 193153838Sdfr 194