1178825Sdfr/* 2178825Sdfr * Copyright (c) 2004, PADL Software Pty Ltd. 3178825Sdfr * All rights reserved. 4178825Sdfr * 5178825Sdfr * Redistribution and use in source and binary forms, with or without 6178825Sdfr * modification, are permitted provided that the following conditions 7178825Sdfr * are met: 8178825Sdfr * 9178825Sdfr * 1. Redistributions of source code must retain the above copyright 10178825Sdfr * notice, this list of conditions and the following disclaimer. 11178825Sdfr * 12178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 13178825Sdfr * notice, this list of conditions and the following disclaimer in the 14178825Sdfr * documentation and/or other materials provided with the distribution. 15178825Sdfr * 16178825Sdfr * 3. Neither the name of PADL Software nor the names of its contributors 17178825Sdfr * may be used to endorse or promote products derived from this software 18178825Sdfr * without specific prior written permission. 19178825Sdfr * 20178825Sdfr * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 21178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 24178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30178825Sdfr * SUCH DAMAGE. 31178825Sdfr */ 32178825Sdfr 33178825Sdfr#include "spnego/spnego_locl.h" 34178825Sdfr 35178825SdfrRCSID("$Id: cred_stubs.c 20619 2007-05-08 13:43:45Z lha $"); 36178825Sdfr 37178825SdfrOM_uint32 38178825Sdfr_gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) 39178825Sdfr{ 40178825Sdfr gssspnego_cred cred; 41178825Sdfr OM_uint32 ret; 42178825Sdfr 43178825Sdfr *minor_status = 0; 44178825Sdfr 45178825Sdfr if (*cred_handle == GSS_C_NO_CREDENTIAL) { 46178825Sdfr return GSS_S_COMPLETE; 47178825Sdfr } 48178825Sdfr cred = (gssspnego_cred)*cred_handle; 49178825Sdfr 50178825Sdfr ret = gss_release_cred(minor_status, &cred->negotiated_cred_id); 51178825Sdfr 52178825Sdfr free(cred); 53178825Sdfr *cred_handle = GSS_C_NO_CREDENTIAL; 54178825Sdfr 55178825Sdfr return ret; 56178825Sdfr} 57178825Sdfr 58178825SdfrOM_uint32 59178825Sdfr_gss_spnego_alloc_cred(OM_uint32 *minor_status, 60178825Sdfr gss_cred_id_t mech_cred_handle, 61178825Sdfr gss_cred_id_t *cred_handle) 62178825Sdfr{ 63178825Sdfr gssspnego_cred cred; 64178825Sdfr 65178825Sdfr if (*cred_handle != GSS_C_NO_CREDENTIAL) { 66178825Sdfr *minor_status = EINVAL; 67178825Sdfr return GSS_S_FAILURE; 68178825Sdfr } 69178825Sdfr 70178825Sdfr cred = calloc(1, sizeof(*cred)); 71178825Sdfr if (cred == NULL) { 72178825Sdfr *cred_handle = GSS_C_NO_CREDENTIAL; 73178825Sdfr *minor_status = ENOMEM; 74178825Sdfr return GSS_S_FAILURE; 75178825Sdfr } 76178825Sdfr 77178825Sdfr cred->negotiated_cred_id = mech_cred_handle; 78178825Sdfr 79178825Sdfr *cred_handle = (gss_cred_id_t)cred; 80178825Sdfr 81178825Sdfr return GSS_S_COMPLETE; 82178825Sdfr} 83178825Sdfr 84178825Sdfr/* 85178825Sdfr * For now, just a simple wrapper that avoids recursion. When 86178825Sdfr * we support gss_{get,set}_neg_mechs() we will need to expose 87178825Sdfr * more functionality. 88178825Sdfr */ 89178825SdfrOM_uint32 _gss_spnego_acquire_cred 90178825Sdfr(OM_uint32 *minor_status, 91178825Sdfr const gss_name_t desired_name, 92178825Sdfr OM_uint32 time_req, 93178825Sdfr const gss_OID_set desired_mechs, 94178825Sdfr gss_cred_usage_t cred_usage, 95178825Sdfr gss_cred_id_t * output_cred_handle, 96178825Sdfr gss_OID_set * actual_mechs, 97178825Sdfr OM_uint32 * time_rec 98178825Sdfr ) 99178825Sdfr{ 100178825Sdfr const spnego_name dname = (const spnego_name)desired_name; 101178825Sdfr gss_name_t name = GSS_C_NO_NAME; 102178825Sdfr OM_uint32 ret, tmp; 103178825Sdfr gss_OID_set_desc actual_desired_mechs; 104178825Sdfr gss_OID_set mechs; 105178825Sdfr int i, j; 106178825Sdfr gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL; 107178825Sdfr gssspnego_cred cred; 108178825Sdfr 109178825Sdfr *output_cred_handle = GSS_C_NO_CREDENTIAL; 110178825Sdfr 111178825Sdfr if (dname) { 112178825Sdfr ret = gss_import_name(minor_status, &dname->value, &dname->type, &name); 113178825Sdfr if (ret) { 114178825Sdfr return ret; 115178825Sdfr } 116178825Sdfr } 117178825Sdfr 118178825Sdfr ret = gss_indicate_mechs(minor_status, &mechs); 119178825Sdfr if (ret != GSS_S_COMPLETE) { 120178825Sdfr gss_release_name(minor_status, &name); 121178825Sdfr return ret; 122178825Sdfr } 123178825Sdfr 124178825Sdfr /* Remove ourselves from this list */ 125178825Sdfr actual_desired_mechs.count = mechs->count; 126178825Sdfr actual_desired_mechs.elements = malloc(actual_desired_mechs.count * 127178825Sdfr sizeof(gss_OID_desc)); 128178825Sdfr if (actual_desired_mechs.elements == NULL) { 129178825Sdfr *minor_status = ENOMEM; 130178825Sdfr ret = GSS_S_FAILURE; 131178825Sdfr goto out; 132178825Sdfr } 133178825Sdfr 134178825Sdfr for (i = 0, j = 0; i < mechs->count; i++) { 135178825Sdfr if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM)) 136178825Sdfr continue; 137178825Sdfr 138178825Sdfr actual_desired_mechs.elements[j] = mechs->elements[i]; 139178825Sdfr j++; 140178825Sdfr } 141178825Sdfr actual_desired_mechs.count = j; 142178825Sdfr 143178825Sdfr ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, 144178825Sdfr &cred_handle); 145178825Sdfr if (ret != GSS_S_COMPLETE) 146178825Sdfr goto out; 147178825Sdfr 148178825Sdfr cred = (gssspnego_cred)cred_handle; 149178825Sdfr ret = gss_acquire_cred(minor_status, name, 150178825Sdfr time_req, &actual_desired_mechs, 151178825Sdfr cred_usage, 152178825Sdfr &cred->negotiated_cred_id, 153178825Sdfr actual_mechs, time_rec); 154178825Sdfr if (ret != GSS_S_COMPLETE) 155178825Sdfr goto out; 156178825Sdfr 157178825Sdfr *output_cred_handle = cred_handle; 158178825Sdfr 159178825Sdfrout: 160178825Sdfr gss_release_name(minor_status, &name); 161178825Sdfr gss_release_oid_set(&tmp, &mechs); 162178825Sdfr if (actual_desired_mechs.elements != NULL) { 163178825Sdfr free(actual_desired_mechs.elements); 164178825Sdfr } 165178825Sdfr if (ret != GSS_S_COMPLETE) { 166178825Sdfr _gss_spnego_release_cred(&tmp, &cred_handle); 167178825Sdfr } 168178825Sdfr 169178825Sdfr return ret; 170178825Sdfr} 171178825Sdfr 172178825SdfrOM_uint32 _gss_spnego_inquire_cred 173178825Sdfr (OM_uint32 * minor_status, 174178825Sdfr const gss_cred_id_t cred_handle, 175178825Sdfr gss_name_t * name, 176178825Sdfr OM_uint32 * lifetime, 177178825Sdfr gss_cred_usage_t * cred_usage, 178178825Sdfr gss_OID_set * mechanisms 179178825Sdfr ) 180178825Sdfr{ 181178825Sdfr gssspnego_cred cred; 182178825Sdfr spnego_name sname = NULL; 183178825Sdfr OM_uint32 ret; 184178825Sdfr 185178825Sdfr if (cred_handle == GSS_C_NO_CREDENTIAL) { 186178825Sdfr *minor_status = 0; 187178825Sdfr return GSS_S_NO_CRED; 188178825Sdfr } 189178825Sdfr 190178825Sdfr if (name) { 191178825Sdfr sname = calloc(1, sizeof(*sname)); 192178825Sdfr if (sname == NULL) { 193178825Sdfr *minor_status = ENOMEM; 194178825Sdfr return GSS_S_FAILURE; 195178825Sdfr } 196178825Sdfr } 197178825Sdfr 198178825Sdfr cred = (gssspnego_cred)cred_handle; 199178825Sdfr 200178825Sdfr ret = gss_inquire_cred(minor_status, 201178825Sdfr cred->negotiated_cred_id, 202178825Sdfr sname ? &sname->mech : NULL, 203178825Sdfr lifetime, 204178825Sdfr cred_usage, 205178825Sdfr mechanisms); 206178825Sdfr if (ret) { 207178825Sdfr if (sname) 208178825Sdfr free(sname); 209178825Sdfr return ret; 210178825Sdfr } 211178825Sdfr if (name) 212178825Sdfr *name = (gss_name_t)sname; 213178825Sdfr 214178825Sdfr return ret; 215178825Sdfr} 216178825Sdfr 217178825SdfrOM_uint32 _gss_spnego_add_cred ( 218178825Sdfr OM_uint32 * minor_status, 219178825Sdfr const gss_cred_id_t input_cred_handle, 220178825Sdfr const gss_name_t desired_name, 221178825Sdfr const gss_OID desired_mech, 222178825Sdfr gss_cred_usage_t cred_usage, 223178825Sdfr OM_uint32 initiator_time_req, 224178825Sdfr OM_uint32 acceptor_time_req, 225178825Sdfr gss_cred_id_t * output_cred_handle, 226178825Sdfr gss_OID_set * actual_mechs, 227178825Sdfr OM_uint32 * initiator_time_rec, 228178825Sdfr OM_uint32 * acceptor_time_rec 229178825Sdfr ) 230178825Sdfr{ 231178825Sdfr gss_cred_id_t spnego_output_cred_handle = GSS_C_NO_CREDENTIAL; 232178825Sdfr OM_uint32 ret, tmp; 233178825Sdfr gssspnego_cred input_cred, output_cred; 234178825Sdfr 235178825Sdfr *output_cred_handle = GSS_C_NO_CREDENTIAL; 236178825Sdfr 237178825Sdfr ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, 238178825Sdfr &spnego_output_cred_handle); 239178825Sdfr if (ret) 240178825Sdfr return ret; 241178825Sdfr 242178825Sdfr input_cred = (gssspnego_cred)input_cred_handle; 243178825Sdfr output_cred = (gssspnego_cred)spnego_output_cred_handle; 244178825Sdfr 245178825Sdfr ret = gss_add_cred(minor_status, 246178825Sdfr input_cred->negotiated_cred_id, 247178825Sdfr desired_name, 248178825Sdfr desired_mech, 249178825Sdfr cred_usage, 250178825Sdfr initiator_time_req, 251178825Sdfr acceptor_time_req, 252178825Sdfr &output_cred->negotiated_cred_id, 253178825Sdfr actual_mechs, 254178825Sdfr initiator_time_rec, 255178825Sdfr acceptor_time_rec); 256178825Sdfr if (ret) { 257178825Sdfr _gss_spnego_release_cred(&tmp, &spnego_output_cred_handle); 258178825Sdfr return ret; 259178825Sdfr } 260178825Sdfr 261178825Sdfr *output_cred_handle = spnego_output_cred_handle; 262178825Sdfr 263178825Sdfr return GSS_S_COMPLETE; 264178825Sdfr} 265178825Sdfr 266178825SdfrOM_uint32 _gss_spnego_inquire_cred_by_mech ( 267178825Sdfr OM_uint32 * minor_status, 268178825Sdfr const gss_cred_id_t cred_handle, 269178825Sdfr const gss_OID mech_type, 270178825Sdfr gss_name_t * name, 271178825Sdfr OM_uint32 * initiator_lifetime, 272178825Sdfr OM_uint32 * acceptor_lifetime, 273178825Sdfr gss_cred_usage_t * cred_usage 274178825Sdfr ) 275178825Sdfr{ 276178825Sdfr gssspnego_cred cred; 277178825Sdfr spnego_name sname = NULL; 278178825Sdfr OM_uint32 ret; 279178825Sdfr 280178825Sdfr if (cred_handle == GSS_C_NO_CREDENTIAL) { 281178825Sdfr *minor_status = 0; 282178825Sdfr return GSS_S_NO_CRED; 283178825Sdfr } 284178825Sdfr 285178825Sdfr if (name) { 286178825Sdfr sname = calloc(1, sizeof(*sname)); 287178825Sdfr if (sname == NULL) { 288178825Sdfr *minor_status = ENOMEM; 289178825Sdfr return GSS_S_FAILURE; 290178825Sdfr } 291178825Sdfr } 292178825Sdfr 293178825Sdfr cred = (gssspnego_cred)cred_handle; 294178825Sdfr 295178825Sdfr ret = gss_inquire_cred_by_mech(minor_status, 296178825Sdfr cred->negotiated_cred_id, 297178825Sdfr mech_type, 298178825Sdfr sname ? &sname->mech : NULL, 299178825Sdfr initiator_lifetime, 300178825Sdfr acceptor_lifetime, 301178825Sdfr cred_usage); 302178825Sdfr 303178825Sdfr if (ret) { 304178825Sdfr if (sname) 305178825Sdfr free(sname); 306178825Sdfr return ret; 307178825Sdfr } 308178825Sdfr if (name) 309178825Sdfr *name = (gss_name_t)sname; 310178825Sdfr 311178825Sdfr return GSS_S_COMPLETE; 312178825Sdfr} 313178825Sdfr 314178825SdfrOM_uint32 _gss_spnego_inquire_cred_by_oid 315178825Sdfr (OM_uint32 * minor_status, 316178825Sdfr const gss_cred_id_t cred_handle, 317178825Sdfr const gss_OID desired_object, 318178825Sdfr gss_buffer_set_t *data_set) 319178825Sdfr{ 320178825Sdfr gssspnego_cred cred; 321178825Sdfr OM_uint32 ret; 322178825Sdfr 323178825Sdfr if (cred_handle == GSS_C_NO_CREDENTIAL) { 324178825Sdfr *minor_status = 0; 325178825Sdfr return GSS_S_NO_CRED; 326178825Sdfr } 327178825Sdfr cred = (gssspnego_cred)cred_handle; 328178825Sdfr 329178825Sdfr ret = gss_inquire_cred_by_oid(minor_status, 330178825Sdfr cred->negotiated_cred_id, 331178825Sdfr desired_object, 332178825Sdfr data_set); 333178825Sdfr 334178825Sdfr return ret; 335178825Sdfr} 336178825Sdfr 337