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" 30 31 static gss_cred_id_t 32 _gss_mech_cred_find(gss_cred_id_t cred_handle, gss_OID mech_type) 33 { 34 struct _gss_cred *cred = (struct _gss_cred *)cred_handle; 35 struct _gss_mechanism_cred *mc; 36 37 if (cred == NULL) 38 return GSS_C_NO_CREDENTIAL; 39 40 HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { 41 if (gss_oid_equal(mech_type, mc->gmc_mech_oid)) 42 return mc->gmc_cred; 43 } 44 return GSS_C_NO_CREDENTIAL; 45 } 46 47 /** 48 * As the initiator build a context with an acceptor. 49 * 50 * Returns in the major 51 * - GSS_S_COMPLETE - if the context if build 52 * - GSS_S_CONTINUE_NEEDED - if the caller needs to continue another 53 * round of gss_i nit_sec_context 54 * - error code - any other error code 55 * 56 * @param minor_status minor status code. 57 * 58 * @param initiator_cred_handle the credential to use when building 59 * the context, if GSS_C_NO_CREDENTIAL is passed, the default 60 * credential for the mechanism will be used. 61 * 62 * @param context_handle a pointer to a context handle, will be 63 * returned as long as there is not an error. 64 * 65 * @param target_name the target name of acceptor, created using 66 * gss_import_name(). The name is can be of any name types the 67 * mechanism supports, check supported name types with 68 * gss_inquire_names_for_mech(). 69 * 70 * @param input_mech_type mechanism type to use, if GSS_C_NO_OID is 71 * used, Kerberos (GSS_KRB5_MECHANISM) will be tried. Other 72 * available mechanism are listed in the @ref gssapi_mechs_intro 73 * section. 74 * 75 * @param req_flags flags using when building the context, see @ref 76 * gssapi_context_flags 77 * 78 * @param time_req time requested this context should be valid in 79 * seconds, common used value is GSS_C_INDEFINITE 80 * 81 * @param input_chan_bindings Channel bindings used, if not exepected 82 * otherwise, used GSS_C_NO_CHANNEL_BINDINGS 83 * 84 * @param input_token input token sent from the acceptor, for the 85 * initial packet the buffer of { NULL, 0 } should be used. 86 * 87 * @param actual_mech_type the actual mech used, MUST NOT be freed 88 * since it pointing to static memory. 89 * 90 * @param output_token if there is an output token, regardless of 91 * complete, continue_needed, or error it should be sent to the 92 * acceptor 93 * 94 * @param ret_flags return what flags was negotitated, caller should 95 * check if they are accetable. For example, if 96 * GSS_C_MUTUAL_FLAG was negotiated with the acceptor or not. 97 * 98 * @param time_rec amount of time this context is valid for 99 * 100 * @returns a gss_error code, see gss_display_status() about printing 101 * the error code. 102 * 103 * @ingroup gssapi 104 */ 105 106 107 108 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 109 gss_init_sec_context(OM_uint32 * minor_status, 110 const gss_cred_id_t initiator_cred_handle, 111 gss_ctx_id_t * context_handle, 112 const gss_name_t target_name, 113 const gss_OID input_mech_type, 114 OM_uint32 req_flags, 115 OM_uint32 time_req, 116 const gss_channel_bindings_t input_chan_bindings, 117 const gss_buffer_t input_token, 118 gss_OID * actual_mech_type, 119 gss_buffer_t output_token, 120 OM_uint32 * ret_flags, 121 OM_uint32 * time_rec) 122 { 123 OM_uint32 major_status; 124 gssapi_mech_interface m; 125 struct _gss_name *name = (struct _gss_name *) target_name; 126 struct _gss_mechanism_name *mn; 127 struct _gss_context *ctx = (struct _gss_context *) *context_handle; 128 gss_cred_id_t cred_handle; 129 int allocated_ctx; 130 gss_OID mech_type = input_mech_type; 131 132 *minor_status = 0; 133 134 _mg_buffer_zero(output_token); 135 if (actual_mech_type) 136 *actual_mech_type = GSS_C_NO_OID; 137 if (ret_flags) 138 *ret_flags = 0; 139 if (time_rec) 140 *time_rec = 0; 141 142 /* 143 * If we haven't allocated a context yet, do so now and lookup 144 * the mechanism switch table. If we have one already, make 145 * sure we use the same mechanism switch as before. 146 */ 147 if (!ctx) { 148 if (mech_type == NULL) 149 mech_type = GSS_KRB5_MECHANISM; 150 151 ctx = malloc(sizeof(struct _gss_context)); 152 if (!ctx) { 153 *minor_status = ENOMEM; 154 return (GSS_S_FAILURE); 155 } 156 memset(ctx, 0, sizeof(struct _gss_context)); 157 m = ctx->gc_mech = __gss_get_mechanism(mech_type); 158 if (!m) { 159 free(ctx); 160 return (GSS_S_BAD_MECH); 161 } 162 allocated_ctx = 1; 163 } else { 164 m = ctx->gc_mech; 165 mech_type = &ctx->gc_mech->gm_mech_oid; 166 allocated_ctx = 0; 167 } 168 169 /* 170 * Find the MN for this mechanism. 171 */ 172 major_status = _gss_find_mn(minor_status, name, mech_type, &mn); 173 if (major_status != GSS_S_COMPLETE) { 174 if (allocated_ctx) 175 free(ctx); 176 return major_status; 177 } 178 179 /* 180 * If we have a cred, find the cred for this mechanism. 181 */ 182 if (m->gm_flags & GM_USE_MG_CRED) 183 cred_handle = initiator_cred_handle; 184 else 185 cred_handle = _gss_mech_cred_find(initiator_cred_handle, mech_type); 186 187 major_status = m->gm_init_sec_context(minor_status, 188 cred_handle, 189 &ctx->gc_ctx, 190 mn->gmn_name, 191 mech_type, 192 req_flags, 193 time_req, 194 input_chan_bindings, 195 input_token, 196 actual_mech_type, 197 output_token, 198 ret_flags, 199 time_rec); 200 201 if (major_status != GSS_S_COMPLETE 202 && major_status != GSS_S_CONTINUE_NEEDED) { 203 if (allocated_ctx) 204 free(ctx); 205 _mg_buffer_zero(output_token); 206 _gss_mg_error(m, major_status, *minor_status); 207 } else { 208 *context_handle = (gss_ctx_id_t) ctx; 209 } 210 211 return (major_status); 212 } 213