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