gss: pass mechanism error tokens through SPNEGO
Fix for issue #486 based on a patch by Nico Williams. A GSS-API acceptor can return an error token to be sent to the initiator. Our SPNEGO implementation discarded these when sending a SPNEGO reject response. This patch fixes the SPNEGO acceptor to convey those in the SPNEGO response. The SPNEGO initiator is also updated to not bail out early on receiving a SPNEGO reject response from the acceptor, but instead pass the response token (if any) to gss_init_sec_context(). A reject response with no response token will continue to return an error.
This commit is contained in:
@@ -35,10 +35,12 @@
|
||||
|
||||
static OM_uint32
|
||||
send_reject (OM_uint32 *minor_status,
|
||||
gss_buffer_t mech_token,
|
||||
gss_buffer_t output_token)
|
||||
{
|
||||
NegotiationToken nt;
|
||||
size_t size;
|
||||
heim_octet_string responseToken;
|
||||
|
||||
nt.element = choice_NegotiationToken_negTokenResp;
|
||||
|
||||
@@ -50,6 +52,13 @@ send_reject (OM_uint32 *minor_status,
|
||||
*(nt.u.negTokenResp.negState) = reject;
|
||||
nt.u.negTokenResp.supportedMech = NULL;
|
||||
nt.u.negTokenResp.responseToken = NULL;
|
||||
|
||||
if (mech_token != GSS_C_NO_BUFFER && mech_token->value != NULL) {
|
||||
responseToken.length = mech_token->length;
|
||||
responseToken.data = mech_token->value;
|
||||
nt.u.negTokenResp.responseToken = &responseToken;
|
||||
} else
|
||||
nt.u.negTokenResp.responseToken = NULL;
|
||||
nt.u.negTokenResp.mechListMIC = NULL;
|
||||
|
||||
ASN1_MALLOC_ENCODE(NegotiationToken,
|
||||
@@ -513,7 +522,7 @@ acceptor_complete(OM_uint32 * minor_status,
|
||||
ret = _gss_spnego_verify_mechtypes_mic(minor_status, ctx, mic);
|
||||
if (ret) {
|
||||
if (*get_mic)
|
||||
send_reject(minor_status, output_token);
|
||||
send_reject(minor_status, GSS_C_NO_BUFFER, output_token);
|
||||
if (buf.value)
|
||||
free(buf.value);
|
||||
return ret;
|
||||
@@ -888,12 +897,11 @@ acceptor_continue
|
||||
input_chan_bindings,
|
||||
&obuf,
|
||||
delegated_cred_handle);
|
||||
if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) {
|
||||
mech_output_token = &obuf;
|
||||
}
|
||||
mech_output_token = &obuf;
|
||||
if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
|
||||
free_NegotiationToken(&nt);
|
||||
send_reject(&junk, output_token);
|
||||
send_reject(&junk, mech_output_token, output_token);
|
||||
gss_release_buffer(&junk, mech_output_token);
|
||||
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user