/*
- * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
+ * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
*
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
-
-RCSID("$Id: init_sec_context.c 23422 2008-07-26 18:38:29Z lha $");
+#include "gsskrb5_locl.h"
/*
* copy the addresses from `input_chan_bindings' (if any) to
static OM_uint32
set_addresses (krb5_context context,
krb5_auth_context ac,
- const gss_channel_bindings_t input_chan_bindings)
+ const gss_channel_bindings_t input_chan_bindings)
{
- /* Port numbers are expected to be in application_data.value,
- * initator's port first */
+ /* Port numbers are expected to be in application_data.value,
+ * initator's port first */
krb5_address initiator_addr, acceptor_addr;
krb5_error_code kret;
-
+
if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS
|| input_chan_bindings->application_data.length !=
2 * sizeof(ac->local_port))
memset(&initiator_addr, 0, sizeof(initiator_addr));
memset(&acceptor_addr, 0, sizeof(acceptor_addr));
-
+
ac->local_port =
*(int16_t *) input_chan_bindings->application_data.value;
-
+
ac->remote_port =
*((int16_t *) input_chan_bindings->application_data.value + 1);
-
+
kret = _gsskrb5i_address_to_krb5addr(context,
input_chan_bindings->acceptor_addrtype,
&input_chan_bindings->acceptor_address,
&acceptor_addr);
if (kret)
return kret;
-
+
kret = _gsskrb5i_address_to_krb5addr(context,
input_chan_bindings->initiator_addrtype,
&input_chan_bindings->initiator_address,
krb5_free_address (context, &acceptor_addr);
return kret;
}
-
+
kret = krb5_auth_con_setaddrs(context,
ac,
&initiator_addr, /* local address */
&acceptor_addr); /* remote address */
-
+
krb5_free_address (context, &initiator_addr);
krb5_free_address (context, &acceptor_addr);
-
+
#if 0
free(input_chan_bindings->application_data.value);
input_chan_bindings->application_data.value = NULL;
krb5_data_zero(&ctx->fwd_data);
ctx->lifetime = GSS_C_INDEFINITE;
ctx->order = NULL;
+ ctx->crypto = NULL;
HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex);
kret = krb5_auth_con_init (context, &ctx->auth_context);
krb5_context context,
krb5_ccache ccache,
gsskrb5_ctx ctx,
- krb5_const_principal target_name,
+ const gss_name_t target_name,
+ int use_dns,
OM_uint32 time_req,
OM_uint32 * time_rec,
krb5_creds ** cred)
*cred = NULL;
+ if (ctx->target) {
+ krb5_free_principal(context, ctx->target);
+ ctx->target = NULL;
+ }
+
+ ret = _gsskrb5_canon_name(minor_status, context, use_dns,
+ ctx->source, target_name, &ctx->target);
+ if (ret)
+ return ret;
+
memset(&this_cred, 0, sizeof(this_cred));
this_cred.client = ctx->source;
this_cred.server = ctx->target;
int32_t seq_number;
int is_cfx = 0;
OM_uint32 flags = ctx->flags;
-
+
krb5_free_creds(context, ctx->kcred);
ctx->kcred = NULL;
ctx->ccache = NULL;
krb5_auth_getremoteseqnumber (context, ctx->auth_context, &seq_number);
-
- _gsskrb5i_is_cfx(ctx, &is_cfx);
-
+
+ _gsskrb5i_is_cfx(context, ctx, 0);
+ is_cfx = (ctx->more_flags & IS_CFX);
+
ret = _gssapi_msg_order_create(minor_status,
&ctx->order,
_gssapi_msg_order_f(flags),
seq_number, 0, is_cfx);
if (ret) return ret;
-
+
ctx->state = INITIATOR_READY;
ctx->more_flags |= OPEN;
-
+
return GSS_S_COMPLETE;
}
krb5_creds *cred,
krb5_const_principal name,
krb5_data *fwd_data,
+ uint32_t flagmask,
uint32_t *flags)
{
krb5_creds creds;
KDCOptions fwd_flags;
krb5_error_code kret;
-
+
memset (&creds, 0, sizeof(creds));
krb5_data_zero (fwd_data);
-
+
kret = krb5_cc_get_principal(context, ccache, &creds.client);
- if (kret)
+ if (kret)
goto out;
-
+
kret = krb5_build_principal(context,
&creds.server,
strlen(creds.client->realm),
creds.client->realm,
NULL);
if (kret)
- goto out;
-
+ goto out;
+
creds.times.endtime = 0;
-
+
memset(&fwd_flags, 0, sizeof(fwd_flags));
fwd_flags.forwarded = 1;
fwd_flags.forwardable = 1;
-
+
if ( /*target_name->name.name_type != KRB5_NT_SRV_HST ||*/
- name->name.name_string.len < 2)
+ name->name.name_string.len < 2)
goto out;
-
+
kret = krb5_get_forwarded_creds(context,
ac,
ccache,
name->name.name_string.val[1],
&creds,
fwd_data);
-
+
out:
if (kret)
- *flags &= ~GSS_C_DELEG_FLAG;
+ *flags &= ~flagmask;
else
- *flags |= GSS_C_DELEG_FLAG;
-
+ *flags |= flagmask;
+
if (creds.client)
krb5_free_principal(context, creds.client);
if (creds.server)
gsskrb5_cred cred,
gsskrb5_ctx ctx,
krb5_context context,
- krb5_const_principal name,
+ gss_name_t name,
const gss_OID mech_type,
OM_uint32 req_flags,
OM_uint32 time_req,
krb5_data outbuf;
krb5_data fwd_data;
OM_uint32 lifetime_rec;
+ int allow_dns = 1;
krb5_data_zero(&outbuf);
krb5_data_zero(&fwd_data);
goto failure;
}
- kret = krb5_copy_principal (context, name, &ctx->target);
- if (kret) {
- *minor_status = kret;
- ret = GSS_S_FAILURE;
- goto failure;
- }
-
ret = _gss_DES3_get_mic_compat(minor_status, ctx, context);
if (ret)
goto failure;
krb5_set_default_in_tkt_etypes(context, enctypes);
}
- ret = gsskrb5_get_creds(minor_status,
- context,
- ctx->ccache,
- ctx,
- ctx->target,
- time_req,
- time_rec,
- &ctx->kcred);
+ /* canon name if needed for client + target realm */
+ kret = krb5_cc_get_config(context, ctx->ccache, NULL,
+ "realm-config", &outbuf);
+ if (kret == 0) {
+ /* XXX 2 is no server canon */
+ if (outbuf.length < 1 || ((((unsigned char *)outbuf.data)[0]) & 2))
+ allow_dns = 0;
+ krb5_data_free(&outbuf);
+ }
+
+ /*
+ * First we try w/o dns, hope that the KDC have register alias
+ * (and referrals if cross realm) for this principal. If that
+ * fails and if we are allowed to using this realm try again with
+ * DNS canonicalizion.
+ */
+ ret = gsskrb5_get_creds(minor_status, context, ctx->ccache,
+ ctx, name, 0, time_req,
+ time_rec, &ctx->kcred);
+ if (ret && allow_dns)
+ ret = gsskrb5_get_creds(minor_status, context, ctx->ccache,
+ ctx, name, 1, time_req,
+ time_rec, &ctx->kcred);
if (ret)
goto failure;
context,
ctx->lifetime,
&lifetime_rec);
- if (ret) {
+ if (ret)
goto failure;
- }
if (lifetime_rec == 0) {
*minor_status = 0;
goto failure;
}
- krb5_auth_con_setkey(context,
- ctx->auth_context,
+ krb5_auth_con_setkey(context,
+ ctx->auth_context,
&ctx->kcred->session);
- kret = krb5_auth_con_generatelocalsubkey(context,
+ kret = krb5_auth_con_generatelocalsubkey(context,
ctx->auth_context,
&ctx->kcred->session);
if(kret) {
krb5_enctype enctype;
krb5_data fwd_data, timedata;
int32_t offset = 0, oldoffset;
+ uint32_t flagmask;
krb5_data_zero(&outbuf);
krb5_data_zero(&fwd_data);
*minor_status = 0;
- /*
- * If the credential doesn't have ok-as-delegate, check what local
- * policy say about ok-as-delegate, default is FALSE that makes
- * code ignore the KDC setting and follow what the application
- * requested. If it is TRUE, strip of the GSS_C_DELEG_FLAG if the
- * KDC doesn't set ok-as-delegate.
+ /*
+ * If the credential doesn't have ok-as-delegate, check if there
+ * is a realm setting and use that.
*/
if (!ctx->kcred->flags.b.ok_as_delegate) {
- krb5_boolean delegate, realm_setting;
krb5_data data;
-
- realm_setting = FALSE;
-
+
ret = krb5_cc_get_config(context, ctx->ccache, NULL,
"realm-config", &data);
if (ret == 0) {
/* XXX 1 is use ok-as-delegate */
- if (data.length > 0 && (((unsigned char *)data.data)[0]) & 1)
- realm_setting = TRUE;
+ if (data.length < 1 || ((((unsigned char *)data.data)[0]) & 1) == 0)
+ req_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG);
krb5_data_free(&data);
}
-
- krb5_appdefault_boolean(context, "gssapi", ctx->target->realm,
- "ok-as-delegate", realm_setting,
- &delegate);
- if (delegate)
- req_flags &= ~GSS_C_DELEG_FLAG;
}
+ flagmask = 0;
+
+ /* if we used GSS_C_DELEG_POLICY_FLAG, trust KDC */
+ if ((req_flags & GSS_C_DELEG_POLICY_FLAG)
+ && ctx->kcred->flags.b.ok_as_delegate)
+ flagmask |= GSS_C_DELEG_FLAG | GSS_C_DELEG_POLICY_FLAG;
+ /* if there still is a GSS_C_DELEG_FLAG, use that */
+ if (req_flags & GSS_C_DELEG_FLAG)
+ flagmask |= GSS_C_DELEG_FLAG;
+
+
flags = 0;
ap_options = 0;
- if (req_flags & GSS_C_DELEG_FLAG)
+ if (flagmask & GSS_C_DELEG_FLAG) {
do_delegation (context,
ctx->auth_context,
ctx->ccache, ctx->kcred, ctx->target,
- &fwd_data, &flags);
-
+ &fwd_data, flagmask, &flags);
+ }
+
if (req_flags & GSS_C_MUTUAL_FLAG) {
flags |= GSS_C_MUTUAL_FLAG;
ap_options |= AP_OPTS_MUTUAL_REQUIRED;
}
-
+
if (req_flags & GSS_C_REPLAY_FLAG)
flags |= GSS_C_REPLAY_FLAG;
if (req_flags & GSS_C_SEQUENCE_FLAG)
flags |= GSS_C_SEQUENCE_FLAG;
+#if 0
if (req_flags & GSS_C_ANON_FLAG)
; /* XXX */
+#endif
if (req_flags & GSS_C_DCE_STYLE) {
/* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */
flags |= GSS_C_DCE_STYLE | GSS_C_MUTUAL_FLAG;
flags |= GSS_C_INTEG_FLAG;
}
flags |= GSS_C_TRANS_FLAG;
-
+
if (ret_flags)
*ret_flags = flags;
ctx->flags = flags;
ctx->more_flags |= LOCAL;
-
+
ret = _gsskrb5_create_8003_checksum (minor_status,
input_chan_bindings,
flags,
krb5_error_code kret;
krb5_data indata;
krb5_ap_rep_enc_part *repl;
- int is_cfx = 0;
output_token->length = 0;
output_token->value = NULL;
if (actual_mech_type)
*actual_mech_type = GSS_KRB5_MECHANISM;
- if (ctx->flags & GSS_C_DCE_STYLE) {
+ if (IS_DCE_STYLE(ctx)) {
/* There is no OID wrapping. */
indata.length = input_token->length;
indata.data = input_token->value;
}
krb5_free_ap_rep_enc_part (context,
repl);
-
- _gsskrb5i_is_cfx(ctx, &is_cfx);
- if (is_cfx) {
- krb5_keyblock *key = NULL;
-
- kret = krb5_auth_con_getremotesubkey(context,
- ctx->auth_context,
- &key);
- if (kret == 0 && key != NULL) {
- ctx->more_flags |= ACCEPTOR_SUBKEY;
- krb5_free_keyblock (context, key);
- }
- }
-
*minor_status = 0;
if (time_rec) {
{
krb5_context context;
gsskrb5_cred cred = (gsskrb5_cred)cred_handle;
- krb5_const_principal name = (krb5_const_principal)target_name;
gsskrb5_ctx ctx;
OM_uint32 ret;
return GSS_S_BAD_NAME;
}
- if (mech_type != GSS_C_NO_OID &&
+ if (mech_type != GSS_C_NO_OID &&
!gss_oid_equal(mech_type, GSS_KRB5_MECHANISM))
return GSS_S_BAD_MECH;
*minor_status = 0;
return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE;
}
-
+
ret = _gsskrb5_create_ctx(minor_status,
context_handle,
context,
cred,
ctx,
context,
- name,
+ target_name,
mech_type,
req_flags,
time_req,
ret_flags,
time_rec);
if (ret != GSS_S_COMPLETE)
- break;
+ break;
/* FALL THOUGH */
case INITIATOR_RESTART:
ret = init_auth_restart(minor_status,
goto again;
break;
case INITIATOR_READY:
- /*
+ /*
* If we get there, the caller have called
* gss_init_sec_context() one time too many.
*/
- *minor_status = 0;
+ _gsskrb5_set_status(EINVAL, "init_sec_context "
+ "called one time too many");
+ *minor_status = EINVAL;
ret = GSS_S_BAD_STATUS;
break;
default:
- *minor_status = 0;
+ _gsskrb5_set_status(EINVAL, "init_sec_context "
+ "invalid state %d for client",
+ (int)ctx->state);
+ *minor_status = EINVAL;
ret = GSS_S_BAD_STATUS;
break;
}