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