try using gss_accept_sec_context() on the opportunistic token instead

of guessing the acceptor name and do gss_acquire_cred, this make
SPNEGO work like before.


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@19435 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2006-12-19 12:10:35 +00:00
parent f220c91612
commit 3c9d3266f4

View File

@@ -369,7 +369,8 @@ verify_mechlist_mic
} }
static OM_uint32 static OM_uint32
select_mech(OM_uint32 *minor_status, MechType *mechType, gss_OID *mech_p) select_mech(OM_uint32 *minor_status, MechType *mechType, int verify_p,
gss_OID *mech_p)
{ {
char mechbuf[64]; char mechbuf[64];
size_t mech_len; size_t mech_len;
@@ -416,7 +417,7 @@ select_mech(OM_uint32 *minor_status, MechType *mechType, gss_OID *mech_p)
mech_p); mech_p);
} }
{ if (verify_p) {
gss_name_t name = GSS_C_NO_NAME; gss_name_t name = GSS_C_NO_NAME;
gss_buffer_desc namebuf; gss_buffer_desc namebuf;
char *str = NULL, *host, hostname[MAXHOSTNAMELEN]; char *str = NULL, *host, hostname[MAXHOSTNAMELEN];
@@ -544,14 +545,14 @@ acceptor_start
int i; int i;
gss_buffer_desc data; gss_buffer_desc data;
size_t len, taglen; size_t len, taglen;
unsigned int negResult = accept_incomplete;
gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; gss_buffer_t mech_input_token = GSS_C_NO_BUFFER;
gss_buffer_desc mech_output_token; gss_buffer_desc mech_output_token;
gss_buffer_desc mech_buf; gss_buffer_desc mech_buf;
gss_OID preferred_mech_type = GSS_C_NO_OID; gss_OID preferred_mech_type = GSS_C_NO_OID;
gssspnego_ctx ctx; gssspnego_ctx ctx;
gssspnego_cred acceptor_cred = (gssspnego_cred)acceptor_cred_handle; gssspnego_cred acceptor_cred = (gssspnego_cred)acceptor_cred_handle;
int first_mech = 0; int get_mic = 0;
int first_ok = 0;
mech_output_token.value = NULL; mech_output_token.value = NULL;
mech_output_token.length = 0; mech_output_token.length = 0;
@@ -564,8 +565,7 @@ acceptor_start
return ret; return ret;
if (input_token_buffer->length == 0) { if (input_token_buffer->length == 0) {
return send_supported_mechs (minor_status, return send_supported_mechs (minor_status, output_token);
output_token);
} }
} }
@@ -602,47 +602,42 @@ acceptor_start
return GSS_S_DEFECTIVE_TOKEN; return GSS_S_DEFECTIVE_TOKEN;
} }
/* Call glue layer to find first mech we support */ if (ni.mechTypes.len < 1) {
for (i = 0; i < ni.mechTypes.len; ++i) {
ret = select_mech(minor_status,
&ni.mechTypes.val[i],
&preferred_mech_type);
if (ret == 0)
break;
}
if (i == 0)
first_mech = 1;
if (preferred_mech_type == GSS_C_NO_OID) {
free_NegTokenInit(&ni); free_NegTokenInit(&ni);
return GSS_S_BAD_MECH; *minor_status = 0;
return GSS_S_DEFECTIVE_TOKEN;
} }
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
ctx->preferred_mech_type = preferred_mech_type; ret = copy_MechTypeList(&ni.mechTypes, &ctx->initiator_mech_types);
ctx->negotiated_mech_type = preferred_mech_type; if (ret) {
ctx->initiator_mech_types.len = ni.mechTypes.len; HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
ctx->initiator_mech_types.val = ni.mechTypes.val; free_NegTokenInit(&ni);
ni.mechTypes.len = 0; *minor_status = ret;
ni.mechTypes.val = NULL; return GSS_S_FAILURE;
}
{ /*
* First we try the opportunistic token if we have support for it,
* don't try to verify we have credential for the token,
* gss_accept_sec_context will (hopefully) tell us that.
* If that failes,
*/
ret = select_mech(minor_status,
&ni.mechTypes.val[0],
0,
&preferred_mech_type);
if (ret == 0 && ni.mechToken != NULL) {
gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL;
gss_cred_id_t mech_cred;
gss_buffer_desc ibuf; gss_buffer_desc ibuf;
int get_mic = 0;
int require_response;
if (ni.mechToken != NULL && first_mech) {
ibuf.length = ni.mechToken->length; ibuf.length = ni.mechToken->length;
ibuf.value = ni.mechToken->data; ibuf.value = ni.mechToken->data;
mech_input_token = &ibuf; mech_input_token = &ibuf;
} else {
ibuf.value = NULL;
ibuf.length = 0;
}
if (mech_input_token != GSS_C_NO_BUFFER) {
gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL;
gss_cred_id_t mech_cred;
if (acceptor_cred != NULL) if (acceptor_cred != NULL)
mech_cred = acceptor_cred->negotiated_cred_id; mech_cred = acceptor_cred->negotiated_cred_id;
@@ -667,23 +662,18 @@ acceptor_start
&ctx->mech_time_rec, &ctx->mech_time_rec,
&mech_delegated_cred); &mech_delegated_cred);
if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) {
if (delegated_cred_handle) { if (delegated_cred_handle)
ret = _gss_spnego_alloc_cred(minor_status, ret = _gss_spnego_alloc_cred(minor_status,
mech_delegated_cred, mech_delegated_cred,
delegated_cred_handle); delegated_cred_handle);
else
} else {
gss_release_cred(&ret2, &mech_delegated_cred); gss_release_cred(&ret2, &mech_delegated_cred);
}
} ctx->preferred_mech_type = preferred_mech_type;
if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { ctx->negotiated_mech_type = preferred_mech_type;
free_NegTokenInit(&ni); if (ret == GSS_S_COMPLETE)
send_reject (minor_status, output_token);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
return ret;
}
if (ret == GSS_S_COMPLETE) {
ctx->open = 1; ctx->open = 1;
ret = acceptor_complete(minor_status, ret = acceptor_complete(minor_status,
ctx, ctx,
&get_mic, &get_mic,
@@ -692,51 +682,71 @@ acceptor_start
&mech_output_token, &mech_output_token,
ni.mechListMIC, ni.mechListMIC,
output_token); output_token);
} if (ret != GSS_S_COMPLETE)
} else goto out;
ret = GSS_S_COMPLETE;
if (ctx->mech_flags & GSS_C_DCE_STYLE) first_ok = 1;
require_response = (negResult != accept_completed); }
else }
require_response = 0;
/* /*
* Check whether we need to send a result: there should be only * If opportunistic token failed, lets try the other mechs.
* one accept_completed response sent in the entire negotiation
*/ */
if ((mech_output_token.length != 0)
|| (ctx->open && negResult == accept_incomplete) if (!first_ok) {
|| require_response
|| get_mic /* Call glue layer to find first mech we support */
|| !first_mech) { for (i = 1; i < ni.mechTypes.len; ++i) {
ret2 = send_accept (minor_status, ret = select_mech(minor_status,
&ni.mechTypes.val[i],
1,
&preferred_mech_type);
if (ret == 0)
break;
}
if (preferred_mech_type == GSS_C_NO_OID) {
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
free_NegTokenInit(&ni);
return GSS_S_BAD_MECH;
}
ctx->preferred_mech_type = preferred_mech_type;
ctx->negotiated_mech_type = preferred_mech_type;
}
/*
* The initial token always have a response
*/
ret = send_accept (minor_status,
ctx, ctx,
&mech_output_token, &mech_output_token,
1, 1,
get_mic ? &mech_buf : NULL, get_mic ? &mech_buf : NULL,
output_token); output_token);
if (ret2) { if (ret)
ret = ret2;
goto out; goto out;
}
}
out: out:
if (mech_output_token.value != NULL) if (mech_output_token.value != NULL)
gss_release_buffer(&minor, &mech_output_token); gss_release_buffer(&minor, &mech_output_token);
if (mech_buf.value != NULL) if (mech_buf.value != NULL) {
free(mech_buf.value); free(mech_buf.value);
free_NegTokenInit(&ni); mech_buf.value = NULL;
} }
free_NegTokenInit(&ni);
if (ret == GSS_S_COMPLETE) { if (ret == GSS_S_COMPLETE) {
if (src_name != NULL && ctx->mech_src_name != NULL) { if (src_name != NULL && ctx->mech_src_name != NULL) {
ret2 = gss_duplicate_name(minor_status, spnego_name name;
ctx->mech_src_name,
src_name); name = calloc(1, sizeof(*name));
if (ret2 != GSS_S_COMPLETE) if (name) {
ret = ret2; name->mech = ctx->mech_src_name;
ctx->mech_src_name = NULL;
*src_name = (gss_name_t)name;
} else
*src_name = GSS_C_NO_NAME;
} }
if (delegated_cred_handle != NULL) { if (delegated_cred_handle != NULL) {
*delegated_cred_handle = ctx->delegated_cred_id; *delegated_cred_handle = ctx->delegated_cred_id;