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> 30153838Sdfr#include <stdlib.h> 31153838Sdfr#include <errno.h> 32153838Sdfr 33153838Sdfr#include "mech_switch.h" 34153838Sdfr#include "name.h" 35153838Sdfr#include "cred.h" 36153838Sdfr 37153838SdfrOM_uint32 38153838Sdfrgss_acquire_cred(OM_uint32 *minor_status, 39153838Sdfr const gss_name_t desired_name, 40153838Sdfr OM_uint32 time_req, 41153838Sdfr const gss_OID_set desired_mechs, 42153838Sdfr gss_cred_usage_t cred_usage, 43153838Sdfr gss_cred_id_t *output_cred_handle, 44153838Sdfr gss_OID_set *actual_mechs, 45153838Sdfr OM_uint32 *time_rec) 46153838Sdfr{ 47153838Sdfr OM_uint32 major_status; 48153838Sdfr gss_OID_set mechs = desired_mechs; 49153838Sdfr gss_OID_set_desc set; 50153838Sdfr struct _gss_name *name = (struct _gss_name *) desired_name; 51153838Sdfr struct _gss_mech_switch *m; 52153838Sdfr struct _gss_cred *cred; 53153838Sdfr struct _gss_mechanism_cred *mc; 54153838Sdfr struct _gss_mechanism_name *mn; 55178828Sdfr OM_uint32 min_time, cred_time; 56178828Sdfr size_t i; 57153838Sdfr 58178828Sdfr *minor_status = 0; 59178828Sdfr if (output_cred_handle) 60178828Sdfr *output_cred_handle = GSS_C_NO_CREDENTIAL; 61178828Sdfr if (actual_mechs) 62178828Sdfr *actual_mechs = GSS_C_NO_OID_SET; 63178828Sdfr if (time_rec) 64178828Sdfr *time_rec = 0; 65178828Sdfr 66178828Sdfr _gss_load_mech(); 67178828Sdfr 68153838Sdfr /* 69153838Sdfr * First make sure that at least one of the requested 70153838Sdfr * mechanisms is one that we support. 71153838Sdfr */ 72153838Sdfr if (mechs) { 73153838Sdfr for (i = 0; i < mechs->count; i++) { 74153838Sdfr int t; 75153838Sdfr gss_test_oid_set_member(minor_status, 76153838Sdfr &mechs->elements[i], _gss_mech_oids, &t); 77153838Sdfr if (t) 78153838Sdfr break; 79153838Sdfr } 80153838Sdfr if (i == mechs->count) { 81153838Sdfr *minor_status = 0; 82153838Sdfr return (GSS_S_BAD_MECH); 83153838Sdfr } 84174013Sdfr } else { 85174013Sdfr mechs = _gss_mech_oids; 86153838Sdfr } 87153838Sdfr 88153838Sdfr if (actual_mechs) { 89153838Sdfr major_status = gss_create_empty_oid_set(minor_status, 90153838Sdfr actual_mechs); 91153838Sdfr if (major_status) 92153838Sdfr return (major_status); 93153838Sdfr } 94153838Sdfr 95153838Sdfr cred = malloc(sizeof(struct _gss_cred)); 96153838Sdfr if (!cred) { 97153838Sdfr if (actual_mechs) 98153838Sdfr gss_release_oid_set(minor_status, actual_mechs); 99153838Sdfr *minor_status = ENOMEM; 100153838Sdfr return (GSS_S_FAILURE); 101153838Sdfr } 102153838Sdfr SLIST_INIT(&cred->gc_mc); 103153838Sdfr 104153838Sdfr set.count = 1; 105153838Sdfr min_time = GSS_C_INDEFINITE; 106153838Sdfr for (i = 0; i < mechs->count; i++) { 107153838Sdfr m = _gss_find_mech_switch(&mechs->elements[i]); 108153838Sdfr if (!m) 109153838Sdfr continue; 110153838Sdfr 111153838Sdfr if (desired_name != GSS_C_NO_NAME) { 112178828Sdfr major_status = _gss_find_mn(minor_status, name, 113178828Sdfr &mechs->elements[i], &mn); 114178828Sdfr if (major_status != GSS_S_COMPLETE) 115153838Sdfr continue; 116153838Sdfr } 117153838Sdfr 118153838Sdfr mc = malloc(sizeof(struct _gss_mechanism_cred)); 119153838Sdfr if (!mc) { 120153838Sdfr continue; 121153838Sdfr } 122153838Sdfr mc->gmc_mech = m; 123153838Sdfr mc->gmc_mech_oid = &m->gm_mech_oid; 124153838Sdfr 125153838Sdfr /* 126153838Sdfr * XXX Probably need to do something with actual_mechs. 127153838Sdfr */ 128153838Sdfr set.elements = &mechs->elements[i]; 129153838Sdfr major_status = m->gm_acquire_cred(minor_status, 130153838Sdfr (desired_name != GSS_C_NO_NAME 131153838Sdfr ? mn->gmn_name : GSS_C_NO_NAME), 132153838Sdfr time_req, &set, cred_usage, 133178828Sdfr &mc->gmc_cred, NULL, &cred_time); 134153838Sdfr if (major_status) { 135153838Sdfr free(mc); 136153838Sdfr continue; 137153838Sdfr } 138178828Sdfr if (cred_time < min_time) 139178828Sdfr min_time = cred_time; 140153838Sdfr 141153838Sdfr if (actual_mechs) { 142153838Sdfr major_status = gss_add_oid_set_member(minor_status, 143153838Sdfr mc->gmc_mech_oid, actual_mechs); 144153838Sdfr if (major_status) { 145153838Sdfr m->gm_release_cred(minor_status, 146153838Sdfr &mc->gmc_cred); 147153838Sdfr free(mc); 148153838Sdfr continue; 149153838Sdfr } 150153838Sdfr } 151153838Sdfr 152153838Sdfr SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); 153153838Sdfr } 154153838Sdfr 155153838Sdfr /* 156153838Sdfr * If we didn't manage to create a single credential, return 157153838Sdfr * an error. 158153838Sdfr */ 159153838Sdfr if (!SLIST_FIRST(&cred->gc_mc)) { 160153838Sdfr free(cred); 161153838Sdfr if (actual_mechs) 162153838Sdfr gss_release_oid_set(minor_status, actual_mechs); 163153838Sdfr *minor_status = 0; 164153838Sdfr return (GSS_S_NO_CRED); 165153838Sdfr } 166153838Sdfr 167153838Sdfr if (time_rec) 168153838Sdfr *time_rec = min_time; 169153838Sdfr *output_cred_handle = (gss_cred_id_t) cred; 170153838Sdfr *minor_status = 0; 171153838Sdfr return (GSS_S_COMPLETE); 172153838Sdfr} 173