1 /*- 2 * Copyright (c) 2005 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/lib/libgssapi/gss_acquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ 27 */ 28 29 #include "mech_locl.h" 30 31 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 32 gss_acquire_cred(OM_uint32 *minor_status, 33 const gss_name_t desired_name, 34 OM_uint32 time_req, 35 const gss_OID_set desired_mechs, 36 gss_cred_usage_t cred_usage, 37 gss_cred_id_t *output_cred_handle, 38 gss_OID_set *actual_mechs, 39 OM_uint32 *time_rec) 40 { 41 OM_uint32 major_status; 42 gss_OID_set mechs = desired_mechs; 43 gss_OID_set_desc set; 44 struct _gss_name *name = (struct _gss_name *) desired_name; 45 gssapi_mech_interface m; 46 struct _gss_cred *cred; 47 struct _gss_mechanism_cred *mc; 48 OM_uint32 min_time, cred_time; 49 size_t i; 50 51 *minor_status = 0; 52 if (output_cred_handle == NULL) 53 return GSS_S_CALL_INACCESSIBLE_READ; 54 if (actual_mechs) 55 *actual_mechs = GSS_C_NO_OID_SET; 56 if (time_rec) 57 *time_rec = 0; 58 59 _gss_load_mech(); 60 61 /* 62 * First make sure that at least one of the requested 63 * mechanisms is one that we support. 64 */ 65 if (mechs) { 66 for (i = 0; i < mechs->count; i++) { 67 int t; 68 gss_test_oid_set_member(minor_status, 69 &mechs->elements[i], _gss_mech_oids, &t); 70 if (t) 71 break; 72 } 73 if (i == mechs->count) { 74 *minor_status = 0; 75 return (GSS_S_BAD_MECH); 76 } 77 } 78 79 if (actual_mechs) { 80 major_status = gss_create_empty_oid_set(minor_status, 81 actual_mechs); 82 if (major_status) 83 return (major_status); 84 } 85 86 cred = malloc(sizeof(struct _gss_cred)); 87 if (!cred) { 88 if (actual_mechs) 89 gss_release_oid_set(minor_status, actual_mechs); 90 *minor_status = ENOMEM; 91 return (GSS_S_FAILURE); 92 } 93 HEIM_SLIST_INIT(&cred->gc_mc); 94 95 if (mechs == GSS_C_NO_OID_SET) 96 mechs = _gss_mech_oids; 97 98 set.count = 1; 99 min_time = GSS_C_INDEFINITE; 100 for (i = 0; i < mechs->count; i++) { 101 struct _gss_mechanism_name *mn = NULL; 102 103 m = __gss_get_mechanism(&mechs->elements[i]); 104 if (!m) 105 continue; 106 107 if (desired_name != GSS_C_NO_NAME) { 108 major_status = _gss_find_mn(minor_status, name, 109 &mechs->elements[i], &mn); 110 if (major_status != GSS_S_COMPLETE) 111 continue; 112 } 113 114 mc = malloc(sizeof(struct _gss_mechanism_cred)); 115 if (!mc) { 116 continue; 117 } 118 mc->gmc_mech = m; 119 mc->gmc_mech_oid = &m->gm_mech_oid; 120 121 /* 122 * XXX Probably need to do something with actual_mechs. 123 */ 124 set.elements = &mechs->elements[i]; 125 major_status = m->gm_acquire_cred(minor_status, 126 (desired_name != GSS_C_NO_NAME 127 ? mn->gmn_name : GSS_C_NO_NAME), 128 time_req, &set, cred_usage, 129 &mc->gmc_cred, NULL, &cred_time); 130 if (major_status) { 131 free(mc); 132 continue; 133 } 134 if (cred_time < min_time) 135 min_time = cred_time; 136 137 if (actual_mechs) { 138 major_status = gss_add_oid_set_member(minor_status, 139 mc->gmc_mech_oid, actual_mechs); 140 if (major_status) { 141 m->gm_release_cred(minor_status, 142 &mc->gmc_cred); 143 free(mc); 144 continue; 145 } 146 } 147 148 HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); 149 } 150 151 /* 152 * If we didn't manage to create a single credential, return 153 * an error. 154 */ 155 if (!HEIM_SLIST_FIRST(&cred->gc_mc)) { 156 free(cred); 157 if (actual_mechs) 158 gss_release_oid_set(minor_status, actual_mechs); 159 *minor_status = 0; 160 return (GSS_S_NO_CRED); 161 } 162 163 if (time_rec) 164 *time_rec = min_time; 165 *output_cred_handle = (gss_cred_id_t) cred; 166 *minor_status = 0; 167 return (GSS_S_COMPLETE); 168 } 169