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_init_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ 27 */ 28 29#include "mech_locl.h" 30RCSID("$Id: gss_init_sec_context.c,v 1.1.1.1 2011/06/10 09:34:42 andrew Exp $"); 31 32static gss_cred_id_t 33_gss_mech_cred_find(gss_cred_id_t cred_handle, gss_OID mech_type) 34{ 35 struct _gss_cred *cred = (struct _gss_cred *)cred_handle; 36 struct _gss_mechanism_cred *mc; 37 38 if (cred == NULL) 39 return GSS_C_NO_CREDENTIAL; 40 41 SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { 42 if (gss_oid_equal(mech_type, mc->gmc_mech_oid)) 43 return mc->gmc_cred; 44 } 45 return GSS_C_NO_CREDENTIAL; 46} 47 48OM_uint32 GSSAPI_LIB_FUNCTION 49gss_init_sec_context(OM_uint32 * minor_status, 50 const gss_cred_id_t initiator_cred_handle, 51 gss_ctx_id_t * context_handle, 52 const gss_name_t target_name, 53 const gss_OID input_mech_type, 54 OM_uint32 req_flags, 55 OM_uint32 time_req, 56 const gss_channel_bindings_t input_chan_bindings, 57 const gss_buffer_t input_token, 58 gss_OID * actual_mech_type, 59 gss_buffer_t output_token, 60 OM_uint32 * ret_flags, 61 OM_uint32 * time_rec) 62{ 63 OM_uint32 major_status; 64 gssapi_mech_interface m; 65 struct _gss_name *name = (struct _gss_name *) target_name; 66 struct _gss_mechanism_name *mn; 67 struct _gss_context *ctx = (struct _gss_context *) *context_handle; 68 gss_cred_id_t cred_handle; 69 int allocated_ctx; 70 gss_OID mech_type = input_mech_type; 71 72 *minor_status = 0; 73 74 _mg_buffer_zero(output_token); 75 if (actual_mech_type) 76 *actual_mech_type = GSS_C_NO_OID; 77 if (ret_flags) 78 *ret_flags = 0; 79 if (time_rec) 80 *time_rec = 0; 81 82 /* 83 * If we haven't allocated a context yet, do so now and lookup 84 * the mechanism switch table. If we have one already, make 85 * sure we use the same mechanism switch as before. 86 */ 87 if (!ctx) { 88 if (mech_type == NULL) 89 mech_type = GSS_KRB5_MECHANISM; 90 91 ctx = malloc(sizeof(struct _gss_context)); 92 if (!ctx) { 93 *minor_status = ENOMEM; 94 return (GSS_S_FAILURE); 95 } 96 memset(ctx, 0, sizeof(struct _gss_context)); 97 m = ctx->gc_mech = __gss_get_mechanism(mech_type); 98 if (!m) { 99 free(ctx); 100 return (GSS_S_BAD_MECH); 101 } 102 allocated_ctx = 1; 103 } else { 104 m = ctx->gc_mech; 105 mech_type = &ctx->gc_mech->gm_mech_oid; 106 allocated_ctx = 0; 107 } 108 109 /* 110 * Find the MN for this mechanism. 111 */ 112 major_status = _gss_find_mn(minor_status, name, mech_type, &mn); 113 if (major_status != GSS_S_COMPLETE) { 114 if (allocated_ctx) 115 free(ctx); 116 return major_status; 117 } 118 119 /* 120 * If we have a cred, find the cred for this mechanism. 121 */ 122 cred_handle = _gss_mech_cred_find(initiator_cred_handle, mech_type); 123 124 major_status = m->gm_init_sec_context(minor_status, 125 cred_handle, 126 &ctx->gc_ctx, 127 mn->gmn_name, 128 mech_type, 129 req_flags, 130 time_req, 131 input_chan_bindings, 132 input_token, 133 actual_mech_type, 134 output_token, 135 ret_flags, 136 time_rec); 137 138 if (major_status != GSS_S_COMPLETE 139 && major_status != GSS_S_CONTINUE_NEEDED) { 140 if (allocated_ctx) 141 free(ctx); 142 _mg_buffer_zero(output_token); 143 _gss_mg_error(m, major_status, *minor_status); 144 } else { 145 *context_handle = (gss_ctx_id_t) ctx; 146 } 147 148 return (major_status); 149} 150