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:
		| @@ -369,7 +369,8 @@ verify_mechlist_mic | ||||
| } | ||||
|  | ||||
| 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]; | ||||
|     size_t mech_len; | ||||
| @@ -416,7 +417,7 @@ select_mech(OM_uint32 *minor_status, MechType *mechType, gss_OID *mech_p) | ||||
| 				mech_p); | ||||
|     } | ||||
|  | ||||
|     { | ||||
|     if (verify_p) { | ||||
| 	gss_name_t name = GSS_C_NO_NAME; | ||||
| 	gss_buffer_desc namebuf; | ||||
| 	char *str = NULL, *host, hostname[MAXHOSTNAMELEN]; | ||||
| @@ -544,14 +545,14 @@ acceptor_start | ||||
|     int i; | ||||
|     gss_buffer_desc data; | ||||
|     size_t len, taglen; | ||||
|     unsigned int negResult = accept_incomplete; | ||||
|     gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; | ||||
|     gss_buffer_desc mech_output_token; | ||||
|     gss_buffer_desc mech_buf; | ||||
|     gss_OID preferred_mech_type = GSS_C_NO_OID; | ||||
|     gssspnego_ctx ctx; | ||||
|     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.length = 0; | ||||
| @@ -564,8 +565,7 @@ acceptor_start | ||||
| 	    return ret; | ||||
|  | ||||
| 	if (input_token_buffer->length == 0) { | ||||
| 	    return send_supported_mechs (minor_status, | ||||
| 					 output_token); | ||||
| 	    return send_supported_mechs (minor_status, output_token); | ||||
| 	} | ||||
|     } | ||||
|  | ||||
| @@ -602,148 +602,158 @@ acceptor_start | ||||
| 	return GSS_S_DEFECTIVE_TOKEN; | ||||
|     } | ||||
|  | ||||
|     /* Call glue layer to find first mech we support */ | ||||
|     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) { | ||||
|     if (ni.mechTypes.len < 1) { | ||||
| 	free_NegTokenInit(&ni); | ||||
| 	return GSS_S_BAD_MECH; | ||||
| 	*minor_status = 0; | ||||
| 	return GSS_S_DEFECTIVE_TOKEN; | ||||
|     } | ||||
|  | ||||
|     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); | ||||
|  | ||||
|     ctx->preferred_mech_type = preferred_mech_type; | ||||
|     ctx->negotiated_mech_type = preferred_mech_type; | ||||
|     ctx->initiator_mech_types.len = ni.mechTypes.len; | ||||
|     ctx->initiator_mech_types.val = ni.mechTypes.val; | ||||
|     ni.mechTypes.len = 0; | ||||
|     ni.mechTypes.val = NULL; | ||||
|  | ||||
|     { | ||||
| 	gss_buffer_desc ibuf; | ||||
| 	int get_mic = 0; | ||||
| 	int require_response; | ||||
|  | ||||
| 	if (ni.mechToken != NULL && first_mech) { | ||||
| 	    ibuf.length = ni.mechToken->length; | ||||
| 	    ibuf.value = ni.mechToken->data; | ||||
| 	    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) | ||||
| 		mech_cred = acceptor_cred->negotiated_cred_id; | ||||
| 	    else | ||||
| 		mech_cred = GSS_C_NO_CREDENTIAL; | ||||
|  | ||||
| 	    if (ctx->mech_src_name != GSS_C_NO_NAME) | ||||
| 		gss_release_name(&minor, &ctx->mech_src_name); | ||||
|  | ||||
| 	    if (ctx->delegated_cred_id != GSS_C_NO_CREDENTIAL) | ||||
| 		_gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); | ||||
|  | ||||
| 	    ret = gss_accept_sec_context(&minor, | ||||
| 					 &ctx->negotiated_ctx_id, | ||||
| 					 mech_cred, | ||||
| 					 mech_input_token, | ||||
| 					 input_chan_bindings, | ||||
| 					 &ctx->mech_src_name, | ||||
| 					 &ctx->negotiated_mech_type, | ||||
| 					 &mech_output_token, | ||||
| 					 &ctx->mech_flags, | ||||
| 					 &ctx->mech_time_rec, | ||||
| 					 &mech_delegated_cred); | ||||
| 	    if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { | ||||
| 		if (delegated_cred_handle) { | ||||
| 		    ret = _gss_spnego_alloc_cred(minor_status, | ||||
| 						 mech_delegated_cred, | ||||
| 						 delegated_cred_handle); | ||||
|  | ||||
| 		} else { | ||||
| 		    gss_release_cred(&ret2, &mech_delegated_cred); | ||||
| 		} | ||||
| 	    } | ||||
| 	    if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { | ||||
| 		free_NegTokenInit(&ni); | ||||
| 		send_reject (minor_status, output_token); | ||||
| 		HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); | ||||
| 		return ret; | ||||
| 	    } | ||||
| 	    if (ret == GSS_S_COMPLETE) { | ||||
| 		ctx->open = 1; | ||||
| 		ret = acceptor_complete(minor_status, | ||||
| 					ctx, | ||||
| 					&get_mic, | ||||
| 					&mech_buf, | ||||
| 					mech_input_token, | ||||
| 					&mech_output_token, | ||||
| 					ni.mechListMIC, | ||||
| 					output_token); | ||||
| 	    } | ||||
| 	} else | ||||
| 	    ret = GSS_S_COMPLETE; | ||||
|  | ||||
| 	if (ctx->mech_flags & GSS_C_DCE_STYLE) | ||||
| 	    require_response = (negResult != accept_completed); | ||||
| 	else | ||||
| 	    require_response = 0; | ||||
|  | ||||
| 	/* | ||||
| 	 * Check whether we need to send a result: there should be only | ||||
| 	 * one accept_completed response sent in the entire negotiation | ||||
| 	 */ | ||||
| 	if ((mech_output_token.length != 0) | ||||
| 	    || (ctx->open && negResult == accept_incomplete) | ||||
| 	    || require_response | ||||
| 	    || get_mic | ||||
| 	    || !first_mech) { | ||||
| 	    ret2 = send_accept (minor_status, | ||||
| 				ctx, | ||||
| 				&mech_output_token, | ||||
| 				1, | ||||
| 				get_mic ? &mech_buf : NULL, | ||||
| 				output_token); | ||||
| 	    if (ret2) { | ||||
| 		ret = ret2; | ||||
| 		goto out; | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
|      out: | ||||
| 	if (mech_output_token.value != NULL) | ||||
| 	    gss_release_buffer(&minor, &mech_output_token); | ||||
| 	if (mech_buf.value != NULL) | ||||
| 	    free(mech_buf.value); | ||||
|     ret = copy_MechTypeList(&ni.mechTypes, &ctx->initiator_mech_types); | ||||
|     if (ret) { | ||||
| 	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); | ||||
| 	free_NegTokenInit(&ni); | ||||
| 	*minor_status = ret; | ||||
| 	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; | ||||
|  | ||||
| 	ibuf.length = ni.mechToken->length; | ||||
| 	ibuf.value = ni.mechToken->data; | ||||
| 	mech_input_token = &ibuf; | ||||
|  | ||||
| 	if (acceptor_cred != NULL) | ||||
| 	    mech_cred = acceptor_cred->negotiated_cred_id; | ||||
| 	else | ||||
| 	    mech_cred = GSS_C_NO_CREDENTIAL; | ||||
| 	 | ||||
| 	if (ctx->mech_src_name != GSS_C_NO_NAME) | ||||
| 	    gss_release_name(&minor, &ctx->mech_src_name); | ||||
| 	 | ||||
| 	if (ctx->delegated_cred_id != GSS_C_NO_CREDENTIAL) | ||||
| 	    _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); | ||||
| 	 | ||||
| 	ret = gss_accept_sec_context(&minor, | ||||
| 				     &ctx->negotiated_ctx_id, | ||||
| 				     mech_cred, | ||||
| 				     mech_input_token, | ||||
| 				     input_chan_bindings, | ||||
| 				     &ctx->mech_src_name, | ||||
| 				     &ctx->negotiated_mech_type, | ||||
| 				     &mech_output_token, | ||||
| 				     &ctx->mech_flags, | ||||
| 				     &ctx->mech_time_rec, | ||||
| 				     &mech_delegated_cred); | ||||
| 	if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { | ||||
| 	    if (delegated_cred_handle) | ||||
| 		ret = _gss_spnego_alloc_cred(minor_status, | ||||
| 					     mech_delegated_cred, | ||||
| 					     delegated_cred_handle); | ||||
| 	    else | ||||
| 		gss_release_cred(&ret2, &mech_delegated_cred); | ||||
|  | ||||
| 	    ctx->preferred_mech_type = preferred_mech_type; | ||||
| 	    ctx->negotiated_mech_type = preferred_mech_type; | ||||
| 	    if (ret == GSS_S_COMPLETE) | ||||
| 		ctx->open = 1; | ||||
|  | ||||
| 	    ret = acceptor_complete(minor_status, | ||||
| 				    ctx, | ||||
| 				    &get_mic, | ||||
| 				    &mech_buf, | ||||
| 				    mech_input_token, | ||||
| 				    &mech_output_token, | ||||
| 				    ni.mechListMIC, | ||||
| 				    output_token); | ||||
| 	    if (ret != GSS_S_COMPLETE) | ||||
| 		goto out; | ||||
|  | ||||
| 	    first_ok = 1; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * If opportunistic token failed, lets try the other mechs. | ||||
|      */ | ||||
|  | ||||
|     if (!first_ok) { | ||||
|  | ||||
| 	/* Call glue layer to find first mech we support */ | ||||
| 	for (i = 1; i < ni.mechTypes.len; ++i) { | ||||
| 	    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, | ||||
| 		       &mech_output_token, | ||||
| 		       1, | ||||
| 		       get_mic ? &mech_buf : NULL, | ||||
| 		       output_token); | ||||
|     if (ret) | ||||
| 	goto out; | ||||
|      | ||||
| out: | ||||
|     if (mech_output_token.value != NULL) | ||||
| 	gss_release_buffer(&minor, &mech_output_token); | ||||
|     if (mech_buf.value != NULL) { | ||||
| 	free(mech_buf.value); | ||||
| 	mech_buf.value = NULL; | ||||
|     } | ||||
|     free_NegTokenInit(&ni); | ||||
|  | ||||
|     if (ret == GSS_S_COMPLETE) { | ||||
| 	if (src_name != NULL && ctx->mech_src_name != NULL) { | ||||
| 	    ret2 = gss_duplicate_name(minor_status, | ||||
| 				      ctx->mech_src_name, | ||||
| 				      src_name); | ||||
| 	    if (ret2 != GSS_S_COMPLETE) | ||||
| 		ret = ret2; | ||||
| 	    spnego_name name; | ||||
|  | ||||
| 	    name = calloc(1, sizeof(*name)); | ||||
| 	    if (name) { | ||||
| 		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) { | ||||
| 	    *delegated_cred_handle = ctx->delegated_cred_id; | ||||
| 	    ctx->delegated_cred_id = GSS_C_NO_CREDENTIAL; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|      | ||||
|     if (mech_type != NULL) | ||||
| 	*mech_type = ctx->negotiated_mech_type; | ||||
|     if (ret_flags != NULL) | ||||
| @@ -757,8 +767,8 @@ acceptor_start | ||||
|     } | ||||
|  | ||||
|     _gss_spnego_internal_delete_sec_context(&minor, context_handle, | ||||
| 				   GSS_C_NO_BUFFER); | ||||
|  | ||||
| 					    GSS_C_NO_BUFFER); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Love Hörnquist Åstrand
					Love Hörnquist Åstrand