2 * Copyright (c) 1997 - 2003 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.36.2.1 2003/08/15 14:21:18 lha 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_error_code kret;
116 memset (&creds, 0, sizeof(creds));
117 krb5_data_zero (fwd_data);
119 kret = krb5_cc_get_principal(gssapi_krb5_context, ccache, &creds.client);
123 kret = krb5_build_principal(gssapi_krb5_context,
125 strlen(creds.client->realm),
133 creds.times.endtime = 0;
136 fwd_flags.b.forwarded = 1;
137 fwd_flags.b.forwardable = 1;
139 if ( /*target_name->name.name_type != KRB5_NT_SRV_HST ||*/
140 target_name->name.name_string.len < 2)
143 kret = krb5_get_forwarded_creds(gssapi_krb5_context,
147 target_name->name.name_string.val[1],
153 *flags &= ~GSS_C_DELEG_FLAG;
155 *flags |= GSS_C_DELEG_FLAG;
158 krb5_free_principal(gssapi_krb5_context, creds.client);
160 krb5_free_principal(gssapi_krb5_context, creds.server);
164 * first stage of init-sec-context
169 (OM_uint32 * minor_status,
170 const gss_cred_id_t initiator_cred_handle,
171 gss_ctx_id_t * context_handle,
172 const gss_name_t target_name,
173 const gss_OID mech_type,
176 const gss_channel_bindings_t input_chan_bindings,
177 const gss_buffer_t input_token,
178 gss_OID * actual_mech_type,
179 gss_buffer_t output_token,
180 OM_uint32 * ret_flags,
184 OM_uint32 ret = GSS_S_FAILURE;
185 krb5_error_code kret;
186 krb5_flags ap_options;
187 krb5_creds this_cred, *cred;
192 krb5_data authenticator;
194 krb5_enctype enctype;
196 OM_uint32 lifetime_rec;
198 krb5_data_zero(&outbuf);
199 krb5_data_zero(&fwd_data);
203 *context_handle = malloc(sizeof(**context_handle));
204 if (*context_handle == NULL) {
205 *minor_status = ENOMEM;
206 return GSS_S_FAILURE;
209 (*context_handle)->auth_context = NULL;
210 (*context_handle)->source = NULL;
211 (*context_handle)->target = NULL;
212 (*context_handle)->flags = 0;
213 (*context_handle)->more_flags = 0;
214 (*context_handle)->ticket = NULL;
215 (*context_handle)->lifetime = GSS_C_INDEFINITE;
217 kret = krb5_auth_con_init (gssapi_krb5_context,
218 &(*context_handle)->auth_context);
220 gssapi_krb5_set_error_string ();
221 *minor_status = kret;
226 kret = set_addresses ((*context_handle)->auth_context,
227 input_chan_bindings);
229 *minor_status = kret;
230 ret = GSS_S_BAD_BINDINGS;
237 krb5_auth_con_getflags(gssapi_krb5_context,
238 (*context_handle)->auth_context,
240 tmp |= KRB5_AUTH_CONTEXT_DO_SEQUENCE;
241 krb5_auth_con_setflags(gssapi_krb5_context,
242 (*context_handle)->auth_context,
246 if (actual_mech_type)
247 *actual_mech_type = GSS_KRB5_MECHANISM;
249 if (initiator_cred_handle == GSS_C_NO_CREDENTIAL) {
250 kret = krb5_cc_default (gssapi_krb5_context, &ccache);
252 gssapi_krb5_set_error_string ();
253 *minor_status = kret;
258 ccache = initiator_cred_handle->ccache;
260 kret = krb5_cc_get_principal (gssapi_krb5_context,
262 &(*context_handle)->source);
264 gssapi_krb5_set_error_string ();
265 *minor_status = kret;
270 kret = krb5_copy_principal (gssapi_krb5_context,
272 &(*context_handle)->target);
274 gssapi_krb5_set_error_string ();
275 *minor_status = kret;
280 ret = _gss_DES3_get_mic_compat(minor_status, *context_handle);
285 memset(&this_cred, 0, sizeof(this_cred));
286 this_cred.client = (*context_handle)->source;
287 this_cred.server = (*context_handle)->target;
288 if (time_req && time_req != GSS_C_INDEFINITE) {
291 krb5_timeofday (gssapi_krb5_context, &ts);
292 this_cred.times.endtime = ts + time_req;
294 this_cred.times.endtime = 0;
295 this_cred.session.keytype = 0;
297 kret = krb5_get_credentials (gssapi_krb5_context,
298 KRB5_TC_MATCH_KEYTYPE,
304 gssapi_krb5_set_error_string ();
305 *minor_status = kret;
310 (*context_handle)->lifetime = cred->times.endtime;
312 ret = gssapi_lifetime_left(minor_status,
313 (*context_handle)->lifetime,
319 if (lifetime_rec == 0) {
321 ret = GSS_S_CONTEXT_EXPIRED;
325 krb5_auth_con_setkey(gssapi_krb5_context,
326 (*context_handle)->auth_context,
329 kret = krb5_auth_con_generatelocalsubkey(gssapi_krb5_context,
330 (*context_handle)->auth_context,
333 gssapi_krb5_set_error_string ();
334 *minor_status = kret;
341 if (req_flags & GSS_C_DELEG_FLAG)
342 do_delegation ((*context_handle)->auth_context,
343 ccache, cred, target_name, &fwd_data, &flags);
345 if (req_flags & GSS_C_MUTUAL_FLAG) {
346 flags |= GSS_C_MUTUAL_FLAG;
347 ap_options |= AP_OPTS_MUTUAL_REQUIRED;
350 if (req_flags & GSS_C_REPLAY_FLAG)
352 if (req_flags & GSS_C_SEQUENCE_FLAG)
354 if (req_flags & GSS_C_ANON_FLAG)
356 flags |= GSS_C_CONF_FLAG;
357 flags |= GSS_C_INTEG_FLAG;
358 flags |= GSS_C_SEQUENCE_FLAG;
359 flags |= GSS_C_TRANS_FLAG;
363 (*context_handle)->flags = flags;
364 (*context_handle)->more_flags |= LOCAL;
366 ret = gssapi_krb5_create_8003_checksum (minor_status,
371 krb5_data_free (&fwd_data);
376 enctype = (*context_handle)->auth_context->keyblock->keytype;
378 if ((*context_handle)->auth_context->enctype)
379 enctype = (*context_handle)->auth_context->enctype;
381 kret = krb5_keytype_to_enctype(gssapi_krb5_context,
382 (*context_handle)->auth_context->keyblock->keytype,
389 kret = krb5_build_authenticator (gssapi_krb5_context,
390 (*context_handle)->auth_context,
396 KRB5_KU_AP_REQ_AUTH);
399 gssapi_krb5_set_error_string ();
400 *minor_status = kret;
405 kret = krb5_build_ap_req (gssapi_krb5_context,
413 gssapi_krb5_set_error_string ();
414 *minor_status = kret;
419 ret = gssapi_krb5_encapsulate (minor_status, &outbuf, output_token,
424 krb5_data_free (&outbuf);
426 if (flags & GSS_C_MUTUAL_FLAG) {
427 return GSS_S_CONTINUE_NEEDED;
430 *time_rec = lifetime_rec;
432 (*context_handle)->more_flags |= OPEN;
433 return GSS_S_COMPLETE;
437 krb5_auth_con_free (gssapi_krb5_context,
438 (*context_handle)->auth_context);
439 if((*context_handle)->source)
440 krb5_free_principal (gssapi_krb5_context,
441 (*context_handle)->source);
442 if((*context_handle)->target)
443 krb5_free_principal (gssapi_krb5_context,
444 (*context_handle)->target);
445 free (*context_handle);
446 krb5_data_free (&outbuf);
447 *context_handle = GSS_C_NO_CONTEXT;
453 (OM_uint32 * minor_status,
454 const gss_cred_id_t initiator_cred_handle,
455 gss_ctx_id_t * context_handle,
456 const gss_name_t target_name,
457 const gss_OID mech_type,
460 const gss_channel_bindings_t input_chan_bindings,
461 const gss_buffer_t input_token,
462 gss_OID * actual_mech_type,
463 gss_buffer_t output_token,
464 OM_uint32 * ret_flags,
469 krb5_error_code kret;
471 krb5_ap_rep_enc_part *repl;
473 output_token->length = 0;
474 output_token->value = NULL;
476 if (actual_mech_type)
477 *actual_mech_type = GSS_KRB5_MECHANISM;
479 ret = gssapi_krb5_decapsulate (minor_status, input_token, &indata,
482 /* XXX - Handle AP_ERROR */
485 kret = krb5_rd_rep (gssapi_krb5_context,
486 (*context_handle)->auth_context,
490 gssapi_krb5_set_error_string ();
491 *minor_status = kret;
492 return GSS_S_FAILURE;
494 krb5_free_ap_rep_enc_part (gssapi_krb5_context,
497 (*context_handle)->more_flags |= OPEN;
501 ret = gssapi_lifetime_left(minor_status,
502 (*context_handle)->lifetime,
505 ret = GSS_S_COMPLETE;
508 *ret_flags = (*context_handle)->flags;
514 * gss_init_sec_context
517 OM_uint32 gss_init_sec_context
518 (OM_uint32 * minor_status,
519 const gss_cred_id_t initiator_cred_handle,
520 gss_ctx_id_t * context_handle,
521 const gss_name_t target_name,
522 const gss_OID mech_type,
525 const gss_channel_bindings_t input_chan_bindings,
526 const gss_buffer_t input_token,
527 gss_OID * actual_mech_type,
528 gss_buffer_t output_token,
529 OM_uint32 * ret_flags,
535 output_token->length = 0;
536 output_token->value = NULL;
543 if (target_name == GSS_C_NO_NAME) {
544 if (actual_mech_type)
545 *actual_mech_type = GSS_C_NO_OID;
547 return GSS_S_BAD_NAME;
550 if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
551 return init_auth (minor_status,
552 initiator_cred_handle,
565 return repl_mutual(minor_status,
566 initiator_cred_handle,