1 /* 2 * Copyright (c) 2004, PADL Software Pty Ltd. 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 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 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 * 3. Neither the name of PADL Software nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include "spnego/spnego_locl.h" 34 35 RCSID("$Id: cred_stubs.c 20619 2007-05-08 13:43:45Z lha $"); 36 37 OM_uint32 38 _gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) 39 { 40 gssspnego_cred cred; 41 OM_uint32 ret; 42 43 *minor_status = 0; 44 45 if (*cred_handle == GSS_C_NO_CREDENTIAL) { 46 return GSS_S_COMPLETE; 47 } 48 cred = (gssspnego_cred)*cred_handle; 49 50 ret = gss_release_cred(minor_status, &cred->negotiated_cred_id); 51 52 free(cred); 53 *cred_handle = GSS_C_NO_CREDENTIAL; 54 55 return ret; 56 } 57 58 OM_uint32 59 _gss_spnego_alloc_cred(OM_uint32 *minor_status, 60 gss_cred_id_t mech_cred_handle, 61 gss_cred_id_t *cred_handle) 62 { 63 gssspnego_cred cred; 64 65 if (*cred_handle != GSS_C_NO_CREDENTIAL) { 66 *minor_status = EINVAL; 67 return GSS_S_FAILURE; 68 } 69 70 cred = calloc(1, sizeof(*cred)); 71 if (cred == NULL) { 72 *cred_handle = GSS_C_NO_CREDENTIAL; 73 *minor_status = ENOMEM; 74 return GSS_S_FAILURE; 75 } 76 77 cred->negotiated_cred_id = mech_cred_handle; 78 79 *cred_handle = (gss_cred_id_t)cred; 80 81 return GSS_S_COMPLETE; 82 } 83 84 /* 85 * For now, just a simple wrapper that avoids recursion. When 86 * we support gss_{get,set}_neg_mechs() we will need to expose 87 * more functionality. 88 */ 89 OM_uint32 _gss_spnego_acquire_cred 90 (OM_uint32 *minor_status, 91 const gss_name_t desired_name, 92 OM_uint32 time_req, 93 const gss_OID_set desired_mechs, 94 gss_cred_usage_t cred_usage, 95 gss_cred_id_t * output_cred_handle, 96 gss_OID_set * actual_mechs, 97 OM_uint32 * time_rec 98 ) 99 { 100 const spnego_name dname = (const spnego_name)desired_name; 101 gss_name_t name = GSS_C_NO_NAME; 102 OM_uint32 ret, tmp; 103 gss_OID_set_desc actual_desired_mechs; 104 gss_OID_set mechs; 105 int i, j; 106 gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL; 107 gssspnego_cred cred; 108 109 *output_cred_handle = GSS_C_NO_CREDENTIAL; 110 111 if (dname) { 112 ret = gss_import_name(minor_status, &dname->value, &dname->type, &name); 113 if (ret) { 114 return ret; 115 } 116 } 117 118 ret = gss_indicate_mechs(minor_status, &mechs); 119 if (ret != GSS_S_COMPLETE) { 120 gss_release_name(minor_status, &name); 121 return ret; 122 } 123 124 /* Remove ourselves from this list */ 125 actual_desired_mechs.count = mechs->count; 126 actual_desired_mechs.elements = malloc(actual_desired_mechs.count * 127 sizeof(gss_OID_desc)); 128 if (actual_desired_mechs.elements == NULL) { 129 *minor_status = ENOMEM; 130 ret = GSS_S_FAILURE; 131 goto out; 132 } 133 134 for (i = 0, j = 0; i < mechs->count; i++) { 135 if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM)) 136 continue; 137 138 actual_desired_mechs.elements[j] = mechs->elements[i]; 139 j++; 140 } 141 actual_desired_mechs.count = j; 142 143 ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, 144 &cred_handle); 145 if (ret != GSS_S_COMPLETE) 146 goto out; 147 148 cred = (gssspnego_cred)cred_handle; 149 ret = gss_acquire_cred(minor_status, name, 150 time_req, &actual_desired_mechs, 151 cred_usage, 152 &cred->negotiated_cred_id, 153 actual_mechs, time_rec); 154 if (ret != GSS_S_COMPLETE) 155 goto out; 156 157 *output_cred_handle = cred_handle; 158 159 out: 160 gss_release_name(minor_status, &name); 161 gss_release_oid_set(&tmp, &mechs); 162 if (actual_desired_mechs.elements != NULL) { 163 free(actual_desired_mechs.elements); 164 } 165 if (ret != GSS_S_COMPLETE) { 166 _gss_spnego_release_cred(&tmp, &cred_handle); 167 } 168 169 return ret; 170 } 171 172 OM_uint32 _gss_spnego_inquire_cred 173 (OM_uint32 * minor_status, 174 const gss_cred_id_t cred_handle, 175 gss_name_t * name, 176 OM_uint32 * lifetime, 177 gss_cred_usage_t * cred_usage, 178 gss_OID_set * mechanisms 179 ) 180 { 181 gssspnego_cred cred; 182 spnego_name sname = NULL; 183 OM_uint32 ret; 184 185 if (cred_handle == GSS_C_NO_CREDENTIAL) { 186 *minor_status = 0; 187 return GSS_S_NO_CRED; 188 } 189 190 if (name) { 191 sname = calloc(1, sizeof(*sname)); 192 if (sname == NULL) { 193 *minor_status = ENOMEM; 194 return GSS_S_FAILURE; 195 } 196 } 197 198 cred = (gssspnego_cred)cred_handle; 199 200 ret = gss_inquire_cred(minor_status, 201 cred->negotiated_cred_id, 202 sname ? &sname->mech : NULL, 203 lifetime, 204 cred_usage, 205 mechanisms); 206 if (ret) { 207 if (sname) 208 free(sname); 209 return ret; 210 } 211 if (name) 212 *name = (gss_name_t)sname; 213 214 return ret; 215 } 216 217 OM_uint32 _gss_spnego_add_cred ( 218 OM_uint32 * minor_status, 219 const gss_cred_id_t input_cred_handle, 220 const gss_name_t desired_name, 221 const gss_OID desired_mech, 222 gss_cred_usage_t cred_usage, 223 OM_uint32 initiator_time_req, 224 OM_uint32 acceptor_time_req, 225 gss_cred_id_t * output_cred_handle, 226 gss_OID_set * actual_mechs, 227 OM_uint32 * initiator_time_rec, 228 OM_uint32 * acceptor_time_rec 229 ) 230 { 231 gss_cred_id_t spnego_output_cred_handle = GSS_C_NO_CREDENTIAL; 232 OM_uint32 ret, tmp; 233 gssspnego_cred input_cred, output_cred; 234 235 *output_cred_handle = GSS_C_NO_CREDENTIAL; 236 237 ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, 238 &spnego_output_cred_handle); 239 if (ret) 240 return ret; 241 242 input_cred = (gssspnego_cred)input_cred_handle; 243 output_cred = (gssspnego_cred)spnego_output_cred_handle; 244 245 ret = gss_add_cred(minor_status, 246 input_cred->negotiated_cred_id, 247 desired_name, 248 desired_mech, 249 cred_usage, 250 initiator_time_req, 251 acceptor_time_req, 252 &output_cred->negotiated_cred_id, 253 actual_mechs, 254 initiator_time_rec, 255 acceptor_time_rec); 256 if (ret) { 257 _gss_spnego_release_cred(&tmp, &spnego_output_cred_handle); 258 return ret; 259 } 260 261 *output_cred_handle = spnego_output_cred_handle; 262 263 return GSS_S_COMPLETE; 264 } 265 266 OM_uint32 _gss_spnego_inquire_cred_by_mech ( 267 OM_uint32 * minor_status, 268 const gss_cred_id_t cred_handle, 269 const gss_OID mech_type, 270 gss_name_t * name, 271 OM_uint32 * initiator_lifetime, 272 OM_uint32 * acceptor_lifetime, 273 gss_cred_usage_t * cred_usage 274 ) 275 { 276 gssspnego_cred cred; 277 spnego_name sname = NULL; 278 OM_uint32 ret; 279 280 if (cred_handle == GSS_C_NO_CREDENTIAL) { 281 *minor_status = 0; 282 return GSS_S_NO_CRED; 283 } 284 285 if (name) { 286 sname = calloc(1, sizeof(*sname)); 287 if (sname == NULL) { 288 *minor_status = ENOMEM; 289 return GSS_S_FAILURE; 290 } 291 } 292 293 cred = (gssspnego_cred)cred_handle; 294 295 ret = gss_inquire_cred_by_mech(minor_status, 296 cred->negotiated_cred_id, 297 mech_type, 298 sname ? &sname->mech : NULL, 299 initiator_lifetime, 300 acceptor_lifetime, 301 cred_usage); 302 303 if (ret) { 304 if (sname) 305 free(sname); 306 return ret; 307 } 308 if (name) 309 *name = (gss_name_t)sname; 310 311 return GSS_S_COMPLETE; 312 } 313 314 OM_uint32 _gss_spnego_inquire_cred_by_oid 315 (OM_uint32 * minor_status, 316 const gss_cred_id_t cred_handle, 317 const gss_OID desired_object, 318 gss_buffer_set_t *data_set) 319 { 320 gssspnego_cred cred; 321 OM_uint32 ret; 322 323 if (cred_handle == GSS_C_NO_CREDENTIAL) { 324 *minor_status = 0; 325 return GSS_S_NO_CRED; 326 } 327 cred = (gssspnego_cred)cred_handle; 328 329 ret = gss_inquire_cred_by_oid(minor_status, 330 cred->negotiated_cred_id, 331 desired_object, 332 data_set); 333 334 return ret; 335 } 336 337