2 * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "gssapi_locl.h"
36 RCSID("$Id: init_sec_context.c,v 1.31 2002/09/02 17:16:12 joda Exp $");
39 * copy the addresses from `input_chan_bindings' (if any) to
40 * the auth context `ac'
44 set_addresses (krb5_auth_context ac,
45 const gss_channel_bindings_t input_chan_bindings)
47 /* Port numbers are expected to be in application_data.value,
48 * initator's port first */
50 krb5_address initiator_addr, acceptor_addr;
53 if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS
54 || input_chan_bindings->application_data.length !=
55 2 * sizeof(ac->local_port))
58 memset(&initiator_addr, 0, sizeof(initiator_addr));
59 memset(&acceptor_addr, 0, sizeof(acceptor_addr));
62 *(int16_t *) input_chan_bindings->application_data.value;
65 *((int16_t *) input_chan_bindings->application_data.value + 1);
67 kret = gss_address_to_krb5addr(input_chan_bindings->acceptor_addrtype,
68 &input_chan_bindings->acceptor_address,
74 kret = gss_address_to_krb5addr(input_chan_bindings->initiator_addrtype,
75 &input_chan_bindings->initiator_address,
79 krb5_free_address (gssapi_krb5_context, &acceptor_addr);
83 kret = krb5_auth_con_setaddrs(gssapi_krb5_context,
85 &initiator_addr, /* local address */
86 &acceptor_addr); /* remote address */
88 krb5_free_address (gssapi_krb5_context, &initiator_addr);
89 krb5_free_address (gssapi_krb5_context, &acceptor_addr);
92 free(input_chan_bindings->application_data.value);
93 input_chan_bindings->application_data.value = NULL;
94 input_chan_bindings->application_data.length = 0;
101 * handle delegated creds in init-sec-context
105 do_delegation (krb5_auth_context ac,
108 const gss_name_t target_name,
113 krb5_kdc_flags fwd_flags;
114 krb5_keyblock *subkey;
115 krb5_error_code kret;
117 memset (&creds, 0, sizeof(creds));
118 krb5_data_zero (fwd_data);
120 kret = krb5_generate_subkey (gssapi_krb5_context, &cred->session, &subkey);
124 kret = krb5_auth_con_setlocalsubkey(gssapi_krb5_context, ac, subkey);
125 krb5_free_keyblock (gssapi_krb5_context, subkey);
129 kret = krb5_cc_get_principal(gssapi_krb5_context, ccache, &creds.client);
133 kret = krb5_build_principal(gssapi_krb5_context,
135 strlen(creds.client->realm),
143 creds.times.endtime = 0;
146 fwd_flags.b.forwarded = 1;
147 fwd_flags.b.forwardable = 1;
149 if ( /*target_name->name.name_type != KRB5_NT_SRV_HST ||*/
150 target_name->name.name_string.len < 2)
153 kret = krb5_get_forwarded_creds(gssapi_krb5_context,
157 target_name->name.name_string.val[1],
163 *flags &= ~GSS_C_DELEG_FLAG;
165 *flags |= GSS_C_DELEG_FLAG;
168 krb5_free_principal(gssapi_krb5_context, creds.client);
170 krb5_free_principal(gssapi_krb5_context, creds.server);
174 * first stage of init-sec-context
179 (OM_uint32 * minor_status,
180 const gss_cred_id_t initiator_cred_handle,
181 gss_ctx_id_t * context_handle,
182 const gss_name_t target_name,
183 const gss_OID mech_type,
186 const gss_channel_bindings_t input_chan_bindings,
187 const gss_buffer_t input_token,
188 gss_OID * actual_mech_type,
189 gss_buffer_t output_token,
190 OM_uint32 * ret_flags,
194 OM_uint32 ret = GSS_S_FAILURE;
195 krb5_error_code kret;
196 krb5_flags ap_options;
197 krb5_creds this_cred, *cred;
202 krb5_data authenticator;
204 krb5_enctype enctype;
207 output_token->length = 0;
208 output_token->value = NULL;
210 krb5_data_zero(&outbuf);
211 krb5_data_zero(&fwd_data);
215 *context_handle = malloc(sizeof(**context_handle));
216 if (*context_handle == NULL) {
217 *minor_status = ENOMEM;
218 return GSS_S_FAILURE;
221 (*context_handle)->auth_context = NULL;
222 (*context_handle)->source = NULL;
223 (*context_handle)->target = NULL;
224 (*context_handle)->flags = 0;
225 (*context_handle)->more_flags = 0;
226 (*context_handle)->ticket = NULL;
228 kret = krb5_auth_con_init (gssapi_krb5_context,
229 &(*context_handle)->auth_context);
231 gssapi_krb5_set_error_string ();
232 *minor_status = kret;
237 kret = set_addresses ((*context_handle)->auth_context,
238 input_chan_bindings);
240 *minor_status = kret;
241 ret = GSS_S_BAD_BINDINGS;
248 krb5_auth_con_getflags(gssapi_krb5_context,
249 (*context_handle)->auth_context,
251 tmp |= KRB5_AUTH_CONTEXT_DO_SEQUENCE;
252 krb5_auth_con_setflags(gssapi_krb5_context,
253 (*context_handle)->auth_context,
257 if (actual_mech_type)
258 *actual_mech_type = GSS_KRB5_MECHANISM;
260 if (initiator_cred_handle == GSS_C_NO_CREDENTIAL) {
261 kret = krb5_cc_default (gssapi_krb5_context, &ccache);
263 gssapi_krb5_set_error_string ();
264 *minor_status = kret;
269 ccache = initiator_cred_handle->ccache;
271 kret = krb5_cc_get_principal (gssapi_krb5_context,
273 &(*context_handle)->source);
275 gssapi_krb5_set_error_string ();
276 *minor_status = kret;
281 kret = krb5_copy_principal (gssapi_krb5_context,
283 &(*context_handle)->target);
285 gssapi_krb5_set_error_string ();
286 *minor_status = kret;
291 memset(&this_cred, 0, sizeof(this_cred));
292 this_cred.client = (*context_handle)->source;
293 this_cred.server = (*context_handle)->target;
297 krb5_timeofday (gssapi_krb5_context, &ts);
298 this_cred.times.endtime = ts + time_req;
300 this_cred.times.endtime = 0;
301 this_cred.session.keytype = 0;
303 kret = krb5_get_credentials (gssapi_krb5_context,
304 KRB5_TC_MATCH_KEYTYPE,
310 gssapi_krb5_set_error_string ();
311 *minor_status = kret;
316 krb5_auth_con_setkey(gssapi_krb5_context,
317 (*context_handle)->auth_context,
322 if (req_flags & GSS_C_DELEG_FLAG)
323 do_delegation ((*context_handle)->auth_context,
324 ccache, cred, target_name, &fwd_data, &flags);
326 if (req_flags & GSS_C_MUTUAL_FLAG) {
327 flags |= GSS_C_MUTUAL_FLAG;
328 ap_options |= AP_OPTS_MUTUAL_REQUIRED;
331 if (req_flags & GSS_C_REPLAY_FLAG)
333 if (req_flags & GSS_C_SEQUENCE_FLAG)
335 if (req_flags & GSS_C_ANON_FLAG)
337 flags |= GSS_C_CONF_FLAG;
338 flags |= GSS_C_INTEG_FLAG;
339 flags |= GSS_C_SEQUENCE_FLAG;
340 flags |= GSS_C_TRANS_FLAG;
344 (*context_handle)->flags = flags;
345 (*context_handle)->more_flags = LOCAL;
347 ret = gssapi_krb5_create_8003_checksum (minor_status,
352 krb5_data_free (&fwd_data);
357 enctype = (*context_handle)->auth_context->keyblock->keytype;
359 if ((*context_handle)->auth_context->enctype)
360 enctype = (*context_handle)->auth_context->enctype;
362 kret = krb5_keytype_to_enctype(gssapi_krb5_context,
363 (*context_handle)->auth_context->keyblock->keytype,
370 kret = krb5_auth_con_generatelocalsubkey(gssapi_krb5_context,
371 (*context_handle)->auth_context,
374 gssapi_krb5_set_error_string ();
375 *minor_status = kret;
380 kret = krb5_build_authenticator (gssapi_krb5_context,
381 (*context_handle)->auth_context,
387 KRB5_KU_AP_REQ_AUTH);
390 gssapi_krb5_set_error_string ();
391 *minor_status = kret;
396 kret = krb5_build_ap_req (gssapi_krb5_context,
404 gssapi_krb5_set_error_string ();
405 *minor_status = kret;
410 ret = gssapi_krb5_encapsulate (minor_status, &outbuf, output_token,
415 krb5_data_free (&outbuf);
417 if (flags & GSS_C_MUTUAL_FLAG) {
418 return GSS_S_CONTINUE_NEEDED;
420 (*context_handle)->more_flags |= OPEN;
421 return GSS_S_COMPLETE;
425 krb5_auth_con_free (gssapi_krb5_context,
426 (*context_handle)->auth_context);
427 if((*context_handle)->source)
428 krb5_free_principal (gssapi_krb5_context,
429 (*context_handle)->source);
430 if((*context_handle)->target)
431 krb5_free_principal (gssapi_krb5_context,
432 (*context_handle)->target);
433 free (*context_handle);
434 krb5_data_free (&outbuf);
435 *context_handle = GSS_C_NO_CONTEXT;
441 (OM_uint32 * minor_status,
442 const gss_cred_id_t initiator_cred_handle,
443 gss_ctx_id_t * context_handle,
444 const gss_name_t target_name,
445 const gss_OID mech_type,
448 const gss_channel_bindings_t input_chan_bindings,
449 const gss_buffer_t input_token,
450 gss_OID * actual_mech_type,
451 gss_buffer_t output_token,
452 OM_uint32 * ret_flags,
457 krb5_error_code kret;
459 krb5_ap_rep_enc_part *repl;
461 ret = gssapi_krb5_decapsulate (minor_status, input_token, &indata,
464 /* XXX - Handle AP_ERROR */
467 kret = krb5_rd_rep (gssapi_krb5_context,
468 (*context_handle)->auth_context,
472 gssapi_krb5_set_error_string ();
473 *minor_status = kret;
474 return GSS_S_FAILURE;
476 krb5_free_ap_rep_enc_part (gssapi_krb5_context,
479 output_token->length = 0;
481 (*context_handle)->more_flags |= OPEN;
483 return GSS_S_COMPLETE;
487 * gss_init_sec_context
490 OM_uint32 gss_init_sec_context
491 (OM_uint32 * minor_status,
492 const gss_cred_id_t initiator_cred_handle,
493 gss_ctx_id_t * context_handle,
494 const gss_name_t target_name,
495 const gss_OID mech_type,
498 const gss_channel_bindings_t input_chan_bindings,
499 const gss_buffer_t input_token,
500 gss_OID * actual_mech_type,
501 gss_buffer_t output_token,
502 OM_uint32 * ret_flags,
508 if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
509 return init_auth (minor_status,
510 initiator_cred_handle,
523 return repl_mutual(minor_status,
524 initiator_cred_handle,