2 * Copyright (c) 1997 - 2000 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_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
;
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 *minor_status
= kret
;
236 kret
= set_addresses ((*context_handle
)->auth_context
,
237 input_chan_bindings
);
239 *minor_status
= kret
;
240 ret
= GSS_S_BAD_BINDINGS
;
247 krb5_auth_con_getflags(gssapi_krb5_context
,
248 (*context_handle
)->auth_context
,
250 tmp
|= KRB5_AUTH_CONTEXT_DO_SEQUENCE
;
251 krb5_auth_con_setflags(gssapi_krb5_context
,
252 (*context_handle
)->auth_context
,
256 if (actual_mech_type
)
257 *actual_mech_type
= GSS_KRB5_MECHANISM
;
259 kret
= krb5_cc_default (gssapi_krb5_context
, &ccache
);
261 *minor_status
= kret
;
266 kret
= krb5_cc_get_principal (gssapi_krb5_context
,
268 &(*context_handle
)->source
);
270 *minor_status
= kret
;
275 kret
= krb5_copy_principal (gssapi_krb5_context
,
277 &(*context_handle
)->target
);
279 *minor_status
= kret
;
284 memset(&this_cred
, 0, sizeof(this_cred
));
285 this_cred
.client
= (*context_handle
)->source
;
286 this_cred
.server
= (*context_handle
)->target
;
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 *minor_status
= kret
;
308 krb5_auth_con_setkey(gssapi_krb5_context
,
309 (*context_handle
)->auth_context
,
314 if (req_flags
& GSS_C_DELEG_FLAG
)
315 do_delegation ((*context_handle
)->auth_context
,
316 ccache
, cred
, target_name
, &fwd_data
, &flags
);
318 if (req_flags
& GSS_C_MUTUAL_FLAG
) {
319 flags
|= GSS_C_MUTUAL_FLAG
;
320 ap_options
|= AP_OPTS_MUTUAL_REQUIRED
;
323 if (req_flags
& GSS_C_REPLAY_FLAG
)
325 if (req_flags
& GSS_C_SEQUENCE_FLAG
)
327 if (req_flags
& GSS_C_ANON_FLAG
)
329 flags
|= GSS_C_CONF_FLAG
;
330 flags
|= GSS_C_INTEG_FLAG
;
331 flags
|= GSS_C_SEQUENCE_FLAG
;
332 flags
|= GSS_C_TRANS_FLAG
;
336 (*context_handle
)->flags
= flags
;
337 (*context_handle
)->more_flags
= LOCAL
;
339 kret
= gssapi_krb5_create_8003_checksum (input_chan_bindings
,
343 krb5_data_free (&fwd_data
);
345 *minor_status
= kret
;
351 enctype
= (*context_handle
)->auth_context
->keyblock
->keytype
;
353 if ((*context_handle
)->auth_context
->enctype
)
354 enctype
= (*context_handle
)->auth_context
->enctype
;
356 kret
= krb5_keytype_to_enctype(gssapi_krb5_context
,
357 (*context_handle
)->auth_context
->keyblock
->keytype
,
364 kret
= krb5_build_authenticator (gssapi_krb5_context
,
365 (*context_handle
)->auth_context
,
373 *minor_status
= kret
;
378 kret
= krb5_build_ap_req (gssapi_krb5_context
,
386 *minor_status
= kret
;
391 ret
= gssapi_krb5_encapsulate (&outbuf
, output_token
, "\x01\x00");
393 *minor_status
= kret
;
397 krb5_data_free (&outbuf
);
399 if (flags
& GSS_C_MUTUAL_FLAG
) {
400 return GSS_S_CONTINUE_NEEDED
;
402 (*context_handle
)->more_flags
|= OPEN
;
403 return GSS_S_COMPLETE
;
407 krb5_auth_con_free (gssapi_krb5_context
,
408 (*context_handle
)->auth_context
);
409 if((*context_handle
)->source
)
410 krb5_free_principal (gssapi_krb5_context
,
411 (*context_handle
)->source
);
412 if((*context_handle
)->target
)
413 krb5_free_principal (gssapi_krb5_context
,
414 (*context_handle
)->target
);
415 free (*context_handle
);
416 krb5_data_free (&outbuf
);
417 *context_handle
= GSS_C_NO_CONTEXT
;
423 (OM_uint32
* minor_status
,
424 const gss_cred_id_t initiator_cred_handle
,
425 gss_ctx_id_t
* context_handle
,
426 const gss_name_t target_name
,
427 const gss_OID mech_type
,
430 const gss_channel_bindings_t input_chan_bindings
,
431 const gss_buffer_t input_token
,
432 gss_OID
* actual_mech_type
,
433 gss_buffer_t output_token
,
434 OM_uint32
* ret_flags
,
439 krb5_error_code kret
;
441 krb5_ap_rep_enc_part
*repl
;
443 ret
= gssapi_krb5_decapsulate (input_token
, &indata
, "\x02\x00");
445 /* XXX - Handle AP_ERROR */
446 return GSS_S_FAILURE
;
449 kret
= krb5_rd_rep (gssapi_krb5_context
,
450 (*context_handle
)->auth_context
,
454 return GSS_S_FAILURE
;
455 krb5_free_ap_rep_enc_part (gssapi_krb5_context
,
458 output_token
->length
= 0;
460 (*context_handle
)->more_flags
|= OPEN
;
462 return GSS_S_COMPLETE
;
466 * gss_init_sec_context
469 OM_uint32 gss_init_sec_context
470 (OM_uint32
* minor_status
,
471 const gss_cred_id_t initiator_cred_handle
,
472 gss_ctx_id_t
* context_handle
,
473 const gss_name_t target_name
,
474 const gss_OID mech_type
,
477 const gss_channel_bindings_t input_chan_bindings
,
478 const gss_buffer_t input_token
,
479 gss_OID
* actual_mech_type
,
480 gss_buffer_t output_token
,
481 OM_uint32
* ret_flags
,
487 if (input_token
== GSS_C_NO_BUFFER
|| input_token
->length
== 0)
488 return init_auth (minor_status
,
489 initiator_cred_handle
,
502 return repl_mutual(minor_status
,
503 initiator_cred_handle
,