2 * Copyright (c) 1997 - 2001 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.27 2001/05/11 09:16:46 assar 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 kret = gssapi_krb5_create_8003_checksum (input_chan_bindings,
351 krb5_data_free (&fwd_data);
353 gssapi_krb5_set_error_string ();
354 *minor_status = kret;
360 enctype = (*context_handle)->auth_context->keyblock->keytype;
362 if ((*context_handle)->auth_context->enctype)
363 enctype = (*context_handle)->auth_context->enctype;
365 kret = krb5_keytype_to_enctype(gssapi_krb5_context,
366 (*context_handle)->auth_context->keyblock->keytype,
373 kret = krb5_build_authenticator (gssapi_krb5_context,
374 (*context_handle)->auth_context,
380 KRB5_KU_AP_REQ_AUTH);
383 gssapi_krb5_set_error_string ();
384 *minor_status = kret;
389 kret = krb5_build_ap_req (gssapi_krb5_context,
397 gssapi_krb5_set_error_string ();
398 *minor_status = kret;
403 ret = gssapi_krb5_encapsulate (&outbuf, output_token, "\x01\x00");
405 *minor_status = kret;
409 krb5_data_free (&outbuf);
411 if (flags & GSS_C_MUTUAL_FLAG) {
412 return GSS_S_CONTINUE_NEEDED;
414 (*context_handle)->more_flags |= OPEN;
415 return GSS_S_COMPLETE;
419 krb5_auth_con_free (gssapi_krb5_context,
420 (*context_handle)->auth_context);
421 if((*context_handle)->source)
422 krb5_free_principal (gssapi_krb5_context,
423 (*context_handle)->source);
424 if((*context_handle)->target)
425 krb5_free_principal (gssapi_krb5_context,
426 (*context_handle)->target);
427 free (*context_handle);
428 krb5_data_free (&outbuf);
429 *context_handle = GSS_C_NO_CONTEXT;
435 (OM_uint32 * minor_status,
436 const gss_cred_id_t initiator_cred_handle,
437 gss_ctx_id_t * context_handle,
438 const gss_name_t target_name,
439 const gss_OID mech_type,
442 const gss_channel_bindings_t input_chan_bindings,
443 const gss_buffer_t input_token,
444 gss_OID * actual_mech_type,
445 gss_buffer_t output_token,
446 OM_uint32 * ret_flags,
451 krb5_error_code kret;
453 krb5_ap_rep_enc_part *repl;
455 ret = gssapi_krb5_decapsulate (input_token, &indata, "\x02\x00");
457 /* XXX - Handle AP_ERROR */
459 return GSS_S_FAILURE;
462 kret = krb5_rd_rep (gssapi_krb5_context,
463 (*context_handle)->auth_context,
467 gssapi_krb5_set_error_string ();
468 *minor_status = kret;
469 return GSS_S_FAILURE;
471 krb5_free_ap_rep_enc_part (gssapi_krb5_context,
474 output_token->length = 0;
476 (*context_handle)->more_flags |= OPEN;
478 return GSS_S_COMPLETE;
482 * gss_init_sec_context
485 OM_uint32 gss_init_sec_context
486 (OM_uint32 * minor_status,
487 const gss_cred_id_t initiator_cred_handle,
488 gss_ctx_id_t * context_handle,
489 const gss_name_t target_name,
490 const gss_OID mech_type,
493 const gss_channel_bindings_t input_chan_bindings,
494 const gss_buffer_t input_token,
495 gss_OID * actual_mech_type,
496 gss_buffer_t output_token,
497 OM_uint32 * ret_flags,
503 if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
504 return init_auth (minor_status,
505 initiator_cred_handle,
518 return repl_mutual(minor_status,
519 initiator_cred_handle,