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"
38 krb5_keytab gssapi_krb5_keytab
;
41 gsskrb5_register_acceptor_identity (const char *identity
)
46 ret
= gssapi_krb5_init();
50 if(gssapi_krb5_keytab
!= NULL
) {
51 krb5_kt_close(gssapi_krb5_context
, gssapi_krb5_keytab
);
52 gssapi_krb5_keytab
= NULL
;
54 asprintf(&p
, "FILE:%s", identity
);
57 ret
= krb5_kt_resolve(gssapi_krb5_context
, p
, &gssapi_krb5_keytab
);
61 return GSS_S_COMPLETE
;
65 gss_accept_sec_context
66 (OM_uint32
* minor_status
,
67 gss_ctx_id_t
* context_handle
,
68 const gss_cred_id_t acceptor_cred_handle
,
69 const gss_buffer_t input_token_buffer
,
70 const gss_channel_bindings_t input_chan_bindings
,
71 gss_name_t
* src_name
,
73 gss_buffer_t output_token
,
74 OM_uint32
* ret_flags
,
76 gss_cred_id_t
* delegated_cred_handle
80 OM_uint32 ret
= GSS_S_COMPLETE
;
82 krb5_flags ap_options
;
84 krb5_ticket
*ticket
= NULL
;
85 krb5_keytab keytab
= NULL
;
91 krb5_data_zero (&fwd_data
);
92 output_token
->length
= 0;
93 output_token
->value
= NULL
;
98 *mech_type
= GSS_KRB5_MECHANISM
;
100 if (*context_handle
== GSS_C_NO_CONTEXT
) {
101 *context_handle
= malloc(sizeof(**context_handle
));
102 if (*context_handle
== GSS_C_NO_CONTEXT
) {
103 *minor_status
= ENOMEM
;
104 return GSS_S_FAILURE
;
108 (*context_handle
)->auth_context
= NULL
;
109 (*context_handle
)->source
= NULL
;
110 (*context_handle
)->target
= NULL
;
111 (*context_handle
)->flags
= 0;
112 (*context_handle
)->more_flags
= 0;
113 (*context_handle
)->ticket
= NULL
;
114 (*context_handle
)->lifetime
= GSS_C_INDEFINITE
;
116 kret
= krb5_auth_con_init (gssapi_krb5_context
,
117 &(*context_handle
)->auth_context
);
120 *minor_status
= kret
;
121 gssapi_krb5_set_error_string ();
125 if (input_chan_bindings
!= GSS_C_NO_CHANNEL_BINDINGS
126 && input_chan_bindings
->application_data
.length
==
127 2 * sizeof((*context_handle
)->auth_context
->local_port
)
130 /* Port numbers are expected to be in application_data.value,
131 * initator's port first */
133 krb5_address initiator_addr
, acceptor_addr
;
135 memset(&initiator_addr
, 0, sizeof(initiator_addr
));
136 memset(&acceptor_addr
, 0, sizeof(acceptor_addr
));
138 (*context_handle
)->auth_context
->remote_port
=
139 *(int16_t *) input_chan_bindings
->application_data
.value
;
141 (*context_handle
)->auth_context
->local_port
=
142 *((int16_t *) input_chan_bindings
->application_data
.value
+ 1);
145 kret
= gss_address_to_krb5addr(input_chan_bindings
->acceptor_addrtype
,
146 &input_chan_bindings
->acceptor_address
,
147 (*context_handle
)->auth_context
->local_port
,
150 gssapi_krb5_set_error_string ();
151 ret
= GSS_S_BAD_BINDINGS
;
152 *minor_status
= kret
;
156 kret
= gss_address_to_krb5addr(input_chan_bindings
->initiator_addrtype
,
157 &input_chan_bindings
->initiator_address
,
158 (*context_handle
)->auth_context
->remote_port
,
161 krb5_free_address (gssapi_krb5_context
, &acceptor_addr
);
162 gssapi_krb5_set_error_string ();
163 ret
= GSS_S_BAD_BINDINGS
;
164 *minor_status
= kret
;
168 kret
= krb5_auth_con_setaddrs(gssapi_krb5_context
,
169 (*context_handle
)->auth_context
,
170 &acceptor_addr
, /* local address */
171 &initiator_addr
); /* remote address */
173 krb5_free_address (gssapi_krb5_context
, &initiator_addr
);
174 krb5_free_address (gssapi_krb5_context
, &acceptor_addr
);
177 free(input_chan_bindings
->application_data
.value
);
178 input_chan_bindings
->application_data
.value
= NULL
;
179 input_chan_bindings
->application_data
.length
= 0;
183 gssapi_krb5_set_error_string ();
184 ret
= GSS_S_BAD_BINDINGS
;
185 *minor_status
= kret
;
195 krb5_auth_con_getflags(gssapi_krb5_context
,
196 (*context_handle
)->auth_context
,
198 tmp
|= KRB5_AUTH_CONTEXT_DO_SEQUENCE
;
199 krb5_auth_con_setflags(gssapi_krb5_context
,
200 (*context_handle
)->auth_context
,
204 ret
= gssapi_krb5_decapsulate (minor_status
,
211 if (acceptor_cred_handle
== GSS_C_NO_CREDENTIAL
) {
212 if (gssapi_krb5_keytab
!= NULL
) {
213 keytab
= gssapi_krb5_keytab
;
215 } else if (acceptor_cred_handle
->keytab
!= NULL
) {
216 keytab
= acceptor_cred_handle
->keytab
;
219 kret
= krb5_rd_req (gssapi_krb5_context
,
220 &(*context_handle
)->auth_context
,
222 (acceptor_cred_handle
== GSS_C_NO_CREDENTIAL
) ? NULL
223 : acceptor_cred_handle
->principal
,
229 *minor_status
= kret
;
230 gssapi_krb5_set_error_string ();
234 kret
= krb5_copy_principal (gssapi_krb5_context
,
236 &(*context_handle
)->source
);
239 *minor_status
= kret
;
240 gssapi_krb5_set_error_string ();
244 kret
= krb5_copy_principal (gssapi_krb5_context
,
246 &(*context_handle
)->target
);
249 *minor_status
= kret
;
250 gssapi_krb5_set_error_string ();
254 ret
= _gss_DES3_get_mic_compat(minor_status
, *context_handle
);
258 if (src_name
!= NULL
) {
259 kret
= krb5_copy_principal (gssapi_krb5_context
,
264 *minor_status
= kret
;
265 gssapi_krb5_set_error_string ();
271 krb5_authenticator authenticator
;
273 kret
= krb5_auth_con_getauthenticator(gssapi_krb5_context
,
274 (*context_handle
)->auth_context
,
278 *minor_status
= kret
;
279 gssapi_krb5_set_error_string ();
283 ret
= gssapi_krb5_verify_8003_checksum(minor_status
,
285 authenticator
->cksum
,
288 krb5_free_authenticator(gssapi_krb5_context
, &authenticator
);
293 if (fwd_data
.length
> 0 && (flags
& GSS_C_DELEG_FLAG
)) {
297 if (delegated_cred_handle
== NULL
)
298 /* XXX Create a new delegated_cred_handle? */
299 kret
= krb5_cc_default (gssapi_krb5_context
, &ccache
);
300 else if (*delegated_cred_handle
== NULL
) {
301 if ((*delegated_cred_handle
=
302 calloc(1, sizeof(**delegated_cred_handle
))) == NULL
) {
304 *minor_status
= ENOMEM
;
305 krb5_set_error_string(gssapi_krb5_context
, "out of memory");
306 gssapi_krb5_set_error_string();
309 if ((ret
= gss_duplicate_name(minor_status
, ticket
->client
,
310 &(*delegated_cred_handle
)->principal
)) != 0) {
311 flags
&= ~GSS_C_DELEG_FLAG
;
312 free(*delegated_cred_handle
);
313 *delegated_cred_handle
= NULL
;
317 if (delegated_cred_handle
!= NULL
&&
318 (*delegated_cred_handle
)->ccache
== NULL
) {
319 kret
= krb5_cc_gen_new (gssapi_krb5_context
,
321 &(*delegated_cred_handle
)->ccache
);
322 ccache
= (*delegated_cred_handle
)->ccache
;
324 if (delegated_cred_handle
!= NULL
&&
325 (*delegated_cred_handle
)->mechanisms
== NULL
) {
326 ret
= gss_create_empty_oid_set(minor_status
,
327 &(*delegated_cred_handle
)->mechanisms
);
330 ret
= gss_add_oid_set_member(minor_status
, GSS_KRB5_MECHANISM
,
331 &(*delegated_cred_handle
)->mechanisms
);
337 flags
&= ~GSS_C_DELEG_FLAG
;
341 kret
= krb5_cc_initialize(gssapi_krb5_context
,
345 flags
&= ~GSS_C_DELEG_FLAG
;
349 krb5_auth_con_getflags(gssapi_krb5_context
,
350 (*context_handle
)->auth_context
,
352 krb5_auth_con_setflags(gssapi_krb5_context
,
353 (*context_handle
)->auth_context
,
354 ac_flags
& ~KRB5_AUTH_CONTEXT_DO_TIME
);
355 kret
= krb5_rd_cred2(gssapi_krb5_context
,
356 (*context_handle
)->auth_context
,
359 krb5_auth_con_setflags(gssapi_krb5_context
,
360 (*context_handle
)->auth_context
,
363 flags
&= ~GSS_C_DELEG_FLAG
;
372 flags
|= GSS_C_TRANS_FLAG
;
376 (*context_handle
)->lifetime
= ticket
->ticket
.endtime
;
377 (*context_handle
)->flags
= flags
;
378 (*context_handle
)->more_flags
|= OPEN
;
381 *mech_type
= GSS_KRB5_MECHANISM
;
384 ret
= gssapi_lifetime_left(minor_status
,
385 (*context_handle
)->lifetime
,
391 if(flags
& GSS_C_MUTUAL_FLAG
) {
394 kret
= krb5_mk_rep (gssapi_krb5_context
,
395 (*context_handle
)->auth_context
,
399 *minor_status
= kret
;
400 gssapi_krb5_set_error_string ();
403 ret
= gssapi_krb5_encapsulate (minor_status
,
407 krb5_data_free (&outbuf
);
411 output_token
->length
= 0;
412 output_token
->value
= NULL
;
415 (*context_handle
)->ticket
= ticket
;
419 krb5_free_ticket (context
, ticket
);
423 return GSS_S_COMPLETE
;
426 if (fwd_data
.length
> 0)
429 krb5_free_ticket (gssapi_krb5_context
, ticket
);
430 krb5_auth_con_free (gssapi_krb5_context
,
431 (*context_handle
)->auth_context
);
432 if((*context_handle
)->source
)
433 krb5_free_principal (gssapi_krb5_context
,
434 (*context_handle
)->source
);
435 if((*context_handle
)->target
)
436 krb5_free_principal (gssapi_krb5_context
,
437 (*context_handle
)->target
);
438 free (*context_handle
);
439 if (src_name
!= NULL
) {
440 gss_release_name (&minor
, src_name
);
443 *context_handle
= GSS_C_NO_CONTEXT
;