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_acquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ 27226031Sstas */ 28226031Sstas 29226031Sstas#include "mech_locl.h" 30226031Sstas 31226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 32226031Sstasgss_acquire_cred(OM_uint32 *minor_status, 33226031Sstas const gss_name_t desired_name, 34226031Sstas OM_uint32 time_req, 35226031Sstas const gss_OID_set desired_mechs, 36226031Sstas gss_cred_usage_t cred_usage, 37226031Sstas gss_cred_id_t *output_cred_handle, 38226031Sstas gss_OID_set *actual_mechs, 39226031Sstas OM_uint32 *time_rec) 40226031Sstas{ 41226031Sstas OM_uint32 major_status; 42226031Sstas gss_OID_set mechs = desired_mechs; 43226031Sstas gss_OID_set_desc set; 44226031Sstas struct _gss_name *name = (struct _gss_name *) desired_name; 45226031Sstas gssapi_mech_interface m; 46226031Sstas struct _gss_cred *cred; 47226031Sstas struct _gss_mechanism_cred *mc; 48226031Sstas OM_uint32 min_time, cred_time; 49226031Sstas size_t i; 50226031Sstas 51226031Sstas *minor_status = 0; 52226031Sstas if (output_cred_handle == NULL) 53226031Sstas return GSS_S_CALL_INACCESSIBLE_READ; 54226031Sstas if (actual_mechs) 55226031Sstas *actual_mechs = GSS_C_NO_OID_SET; 56226031Sstas if (time_rec) 57226031Sstas *time_rec = 0; 58226031Sstas 59226031Sstas _gss_load_mech(); 60226031Sstas 61226031Sstas /* 62226031Sstas * First make sure that at least one of the requested 63226031Sstas * mechanisms is one that we support. 64226031Sstas */ 65226031Sstas if (mechs) { 66226031Sstas for (i = 0; i < mechs->count; i++) { 67226031Sstas int t; 68226031Sstas gss_test_oid_set_member(minor_status, 69226031Sstas &mechs->elements[i], _gss_mech_oids, &t); 70226031Sstas if (t) 71226031Sstas break; 72226031Sstas } 73226031Sstas if (i == mechs->count) { 74226031Sstas *minor_status = 0; 75226031Sstas return (GSS_S_BAD_MECH); 76226031Sstas } 77226031Sstas } 78226031Sstas 79226031Sstas if (actual_mechs) { 80226031Sstas major_status = gss_create_empty_oid_set(minor_status, 81226031Sstas actual_mechs); 82226031Sstas if (major_status) 83226031Sstas return (major_status); 84226031Sstas } 85226031Sstas 86226031Sstas cred = malloc(sizeof(struct _gss_cred)); 87226031Sstas if (!cred) { 88226031Sstas if (actual_mechs) 89226031Sstas gss_release_oid_set(minor_status, actual_mechs); 90226031Sstas *minor_status = ENOMEM; 91226031Sstas return (GSS_S_FAILURE); 92226031Sstas } 93226031Sstas HEIM_SLIST_INIT(&cred->gc_mc); 94226031Sstas 95226031Sstas if (mechs == GSS_C_NO_OID_SET) 96226031Sstas mechs = _gss_mech_oids; 97226031Sstas 98226031Sstas set.count = 1; 99226031Sstas min_time = GSS_C_INDEFINITE; 100226031Sstas for (i = 0; i < mechs->count; i++) { 101226031Sstas struct _gss_mechanism_name *mn = NULL; 102226031Sstas 103226031Sstas m = __gss_get_mechanism(&mechs->elements[i]); 104226031Sstas if (!m) 105226031Sstas continue; 106226031Sstas 107226031Sstas if (desired_name != GSS_C_NO_NAME) { 108226031Sstas major_status = _gss_find_mn(minor_status, name, 109226031Sstas &mechs->elements[i], &mn); 110226031Sstas if (major_status != GSS_S_COMPLETE) 111226031Sstas continue; 112226031Sstas } 113226031Sstas 114226031Sstas mc = malloc(sizeof(struct _gss_mechanism_cred)); 115226031Sstas if (!mc) { 116226031Sstas continue; 117226031Sstas } 118226031Sstas mc->gmc_mech = m; 119226031Sstas mc->gmc_mech_oid = &m->gm_mech_oid; 120226031Sstas 121226031Sstas /* 122226031Sstas * XXX Probably need to do something with actual_mechs. 123226031Sstas */ 124226031Sstas set.elements = &mechs->elements[i]; 125226031Sstas major_status = m->gm_acquire_cred(minor_status, 126226031Sstas (desired_name != GSS_C_NO_NAME 127226031Sstas ? mn->gmn_name : GSS_C_NO_NAME), 128226031Sstas time_req, &set, cred_usage, 129226031Sstas &mc->gmc_cred, NULL, &cred_time); 130226031Sstas if (major_status) { 131226031Sstas free(mc); 132226031Sstas continue; 133226031Sstas } 134226031Sstas if (cred_time < min_time) 135226031Sstas min_time = cred_time; 136226031Sstas 137226031Sstas if (actual_mechs) { 138226031Sstas major_status = gss_add_oid_set_member(minor_status, 139226031Sstas mc->gmc_mech_oid, actual_mechs); 140226031Sstas if (major_status) { 141226031Sstas m->gm_release_cred(minor_status, 142226031Sstas &mc->gmc_cred); 143226031Sstas free(mc); 144226031Sstas continue; 145226031Sstas } 146226031Sstas } 147226031Sstas 148226031Sstas HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); 149226031Sstas } 150226031Sstas 151226031Sstas /* 152226031Sstas * If we didn't manage to create a single credential, return 153226031Sstas * an error. 154226031Sstas */ 155226031Sstas if (!HEIM_SLIST_FIRST(&cred->gc_mc)) { 156226031Sstas free(cred); 157226031Sstas if (actual_mechs) 158226031Sstas gss_release_oid_set(minor_status, actual_mechs); 159226031Sstas *minor_status = 0; 160226031Sstas return (GSS_S_NO_CRED); 161226031Sstas } 162226031Sstas 163226031Sstas if (time_rec) 164226031Sstas *time_rec = min_time; 165226031Sstas *output_cred_handle = (gss_cred_id_t) cred; 166226031Sstas *minor_status = 0; 167226031Sstas return (GSS_S_COMPLETE); 168226031Sstas} 169