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"
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
;
197 krb5_data_zero(&outbuf
);
198 krb5_data_zero(&fwd_data
);
202 *context_handle
= malloc(sizeof(**context_handle
));
203 if (*context_handle
== NULL
) {
204 *minor_status
= ENOMEM
;
205 return GSS_S_FAILURE
;
208 (*context_handle
)->auth_context
= NULL
;
209 (*context_handle
)->source
= NULL
;
210 (*context_handle
)->target
= NULL
;
211 (*context_handle
)->flags
= 0;
212 (*context_handle
)->more_flags
= 0;
213 (*context_handle
)->ticket
= NULL
;
214 (*context_handle
)->lifetime
= GSS_C_INDEFINITE
;
216 kret
= krb5_auth_con_init (gssapi_krb5_context
,
217 &(*context_handle
)->auth_context
);
219 gssapi_krb5_set_error_string ();
220 *minor_status
= kret
;
225 kret
= set_addresses ((*context_handle
)->auth_context
,
226 input_chan_bindings
);
228 *minor_status
= kret
;
229 ret
= GSS_S_BAD_BINDINGS
;
236 krb5_auth_con_getflags(gssapi_krb5_context
,
237 (*context_handle
)->auth_context
,
239 tmp
|= KRB5_AUTH_CONTEXT_DO_SEQUENCE
;
240 krb5_auth_con_setflags(gssapi_krb5_context
,
241 (*context_handle
)->auth_context
,
245 if (actual_mech_type
)
246 *actual_mech_type
= GSS_KRB5_MECHANISM
;
248 if (initiator_cred_handle
== GSS_C_NO_CREDENTIAL
) {
249 kret
= krb5_cc_default (gssapi_krb5_context
, &ccache
);
251 gssapi_krb5_set_error_string ();
252 *minor_status
= kret
;
257 ccache
= initiator_cred_handle
->ccache
;
259 kret
= krb5_cc_get_principal (gssapi_krb5_context
,
261 &(*context_handle
)->source
);
263 gssapi_krb5_set_error_string ();
264 *minor_status
= kret
;
269 kret
= krb5_copy_principal (gssapi_krb5_context
,
271 &(*context_handle
)->target
);
273 gssapi_krb5_set_error_string ();
274 *minor_status
= kret
;
279 ret
= _gss_DES3_get_mic_compat(minor_status
, *context_handle
);
284 memset(&this_cred
, 0, sizeof(this_cred
));
285 this_cred
.client
= (*context_handle
)->source
;
286 this_cred
.server
= (*context_handle
)->target
;
287 if (time_req
&& time_req
!= GSS_C_INDEFINITE
) {
290 krb5_timeofday (gssapi_krb5_context
, &ts
);
291 this_cred
.times
.endtime
= ts
+ time_req
;
293 this_cred
.times
.endtime
= 0;
294 this_cred
.session
.keytype
= 0;
296 kret
= krb5_get_credentials (gssapi_krb5_context
,
297 KRB5_TC_MATCH_KEYTYPE
,
303 gssapi_krb5_set_error_string ();
304 *minor_status
= kret
;
309 (*context_handle
)->lifetime
= cred
->times
.endtime
;
311 krb5_auth_con_setkey(gssapi_krb5_context
,
312 (*context_handle
)->auth_context
,
315 kret
= krb5_auth_con_generatelocalsubkey(gssapi_krb5_context
,
316 (*context_handle
)->auth_context
,
319 gssapi_krb5_set_error_string ();
320 *minor_status
= kret
;
327 if (req_flags
& GSS_C_DELEG_FLAG
)
328 do_delegation ((*context_handle
)->auth_context
,
329 ccache
, cred
, target_name
, &fwd_data
, &flags
);
331 if (req_flags
& GSS_C_MUTUAL_FLAG
) {
332 flags
|= GSS_C_MUTUAL_FLAG
;
333 ap_options
|= AP_OPTS_MUTUAL_REQUIRED
;
336 if (req_flags
& GSS_C_REPLAY_FLAG
)
338 if (req_flags
& GSS_C_SEQUENCE_FLAG
)
340 if (req_flags
& GSS_C_ANON_FLAG
)
342 flags
|= GSS_C_CONF_FLAG
;
343 flags
|= GSS_C_INTEG_FLAG
;
344 flags
|= GSS_C_SEQUENCE_FLAG
;
345 flags
|= GSS_C_TRANS_FLAG
;
349 (*context_handle
)->flags
= flags
;
350 (*context_handle
)->more_flags
|= LOCAL
;
352 ret
= gssapi_krb5_create_8003_checksum (minor_status
,
357 krb5_data_free (&fwd_data
);
362 enctype
= (*context_handle
)->auth_context
->keyblock
->keytype
;
364 if ((*context_handle
)->auth_context
->enctype
)
365 enctype
= (*context_handle
)->auth_context
->enctype
;
367 kret
= krb5_keytype_to_enctype(gssapi_krb5_context
,
368 (*context_handle
)->auth_context
->keyblock
->keytype
,
375 kret
= krb5_build_authenticator (gssapi_krb5_context
,
376 (*context_handle
)->auth_context
,
382 KRB5_KU_AP_REQ_AUTH
);
385 gssapi_krb5_set_error_string ();
386 *minor_status
= kret
;
391 kret
= krb5_build_ap_req (gssapi_krb5_context
,
399 gssapi_krb5_set_error_string ();
400 *minor_status
= kret
;
405 ret
= gssapi_krb5_encapsulate (minor_status
, &outbuf
, output_token
,
410 krb5_data_free (&outbuf
);
412 if (flags
& GSS_C_MUTUAL_FLAG
) {
413 return GSS_S_CONTINUE_NEEDED
;
416 *time_rec
= (*context_handle
)->lifetime
;
418 (*context_handle
)->more_flags
|= OPEN
;
419 return GSS_S_COMPLETE
;
423 krb5_auth_con_free (gssapi_krb5_context
,
424 (*context_handle
)->auth_context
);
425 if((*context_handle
)->source
)
426 krb5_free_principal (gssapi_krb5_context
,
427 (*context_handle
)->source
);
428 if((*context_handle
)->target
)
429 krb5_free_principal (gssapi_krb5_context
,
430 (*context_handle
)->target
);
431 free (*context_handle
);
432 krb5_data_free (&outbuf
);
433 *context_handle
= GSS_C_NO_CONTEXT
;
439 (OM_uint32
* minor_status
,
440 const gss_cred_id_t initiator_cred_handle
,
441 gss_ctx_id_t
* context_handle
,
442 const gss_name_t target_name
,
443 const gss_OID mech_type
,
446 const gss_channel_bindings_t input_chan_bindings
,
447 const gss_buffer_t input_token
,
448 gss_OID
* actual_mech_type
,
449 gss_buffer_t output_token
,
450 OM_uint32
* ret_flags
,
455 krb5_error_code kret
;
457 krb5_ap_rep_enc_part
*repl
;
459 output_token
->length
= 0;
460 output_token
->value
= NULL
;
462 if (actual_mech_type
)
463 *actual_mech_type
= GSS_KRB5_MECHANISM
;
465 ret
= gssapi_krb5_decapsulate (minor_status
, input_token
, &indata
,
468 /* XXX - Handle AP_ERROR */
471 kret
= krb5_rd_rep (gssapi_krb5_context
,
472 (*context_handle
)->auth_context
,
476 gssapi_krb5_set_error_string ();
477 *minor_status
= kret
;
478 return GSS_S_FAILURE
;
480 krb5_free_ap_rep_enc_part (gssapi_krb5_context
,
483 (*context_handle
)->more_flags
|= OPEN
;
486 *time_rec
= (*context_handle
)->lifetime
;
488 *ret_flags
= (*context_handle
)->flags
;
491 return GSS_S_COMPLETE
;
495 * gss_init_sec_context
498 OM_uint32 gss_init_sec_context
499 (OM_uint32
* minor_status
,
500 const gss_cred_id_t initiator_cred_handle
,
501 gss_ctx_id_t
* context_handle
,
502 const gss_name_t target_name
,
503 const gss_OID mech_type
,
506 const gss_channel_bindings_t input_chan_bindings
,
507 const gss_buffer_t input_token
,
508 gss_OID
* actual_mech_type
,
509 gss_buffer_t output_token
,
510 OM_uint32
* ret_flags
,
516 output_token
->length
= 0;
517 output_token
->value
= NULL
;
524 if (target_name
== GSS_C_NO_NAME
) {
525 if (actual_mech_type
)
526 *actual_mech_type
= GSS_C_NO_OID
;
528 return GSS_S_BAD_NAME
;
531 if (input_token
== GSS_C_NO_BUFFER
|| input_token
->length
== 0)
532 return init_auth (minor_status
,
533 initiator_cred_handle
,
546 return repl_mutual(minor_status
,
547 initiator_cred_handle
,