static int nla_client_recv_nego_token(rdpNla* nla)
{
	int rc = -1;
	SECURITY_STATUS status;
	SecBuffer inputBuffer = { 0 };
	SecBuffer outputBuffer = { 0 };
	SecBufferDesc inputBufferDesc = { 0 };
	SecBufferDesc outputBufferDesc = { 0 };

	WINPR_ASSERT(nla);

	inputBufferDesc.ulVersion = SECBUFFER_VERSION;
	inputBufferDesc.cBuffers = 1;
	inputBufferDesc.pBuffers = &inputBuffer;
	if (!nla_sec_buffer_alloc_from_buffer(&inputBuffer, &nla->negoToken, 0))
		goto fail;

	outputBufferDesc.ulVersion = SECBUFFER_VERSION;
	outputBufferDesc.cBuffers = 1;
	outputBufferDesc.pBuffers = &outputBuffer;
	if (!nla_sec_buffer_alloc(&outputBuffer, nla->cbMaxToken))
		goto fail;

	nla->status = nla_initialize_security_context(nla, FALSE, &inputBufferDesc, &outputBufferDesc);

	switch (nla->status)
	{
		case SEC_I_COMPLETE_AND_CONTINUE:
			if (!nla_complete_auth(nla, &outputBufferDesc))
				goto fail;
			if (!nla_client_send_token(nla, &outputBufferDesc))
				goto fail;
			break;
		case SEC_I_COMPLETE_NEEDED: /* CompleteAuthToken -> finish */
			if (!nla_complete_auth(nla, &outputBufferDesc))
				goto fail;
			nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
			break;
		case SEC_E_OK: /* completed */
			nla->havePubKeyAuth = TRUE;
			status = nla_query_context_sizes(nla);

			if (status != SEC_E_OK)
				goto fail;

			if (nla->peerVersion < 5)
				status = nla_encrypt_public_key_echo(nla);
			else
				status = nla_encrypt_public_key_hash(nla);

			if (status != SEC_E_OK)
				goto fail;

			if (!nla_client_send_token(nla, &outputBufferDesc))
				goto fail;
			nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
			break;

		case SEC_I_CONTINUE_NEEDED: /* send -> retry */
			if (!nla_client_send_token(nla, &outputBufferDesc))
				goto fail;
			nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
			break;

		default:
			WLog_ERR(TAG, "Unexpected NLA return %s", GetSecurityStatusString(nla->status));
			goto fail;
	}

	rc = 1;
fail:
	sspi_SecBufferFree(&inputBuffer);
	sspi_SecBufferFree(&outputBuffer);
	return rc;
}
static int nla_client_recv_nego_token(rdpNla* nla)
{
	int rc = -1;
	SECURITY_STATUS status;
	SecBuffer inputBuffer = { 0 };
	SecBuffer outputBuffer = { 0 };
	SecBufferDesc inputBufferDesc = { 0 };
	SecBufferDesc outputBufferDesc = { 0 };

	WINPR_ASSERT(nla);

	inputBufferDesc.ulVersion = SECBUFFER_VERSION;
	inputBufferDesc.cBuffers = 1;
	inputBufferDesc.pBuffers = &inputBuffer;
	if (!nla_sec_buffer_alloc_from_buffer(&inputBuffer, &nla->negoToken, 0))
		goto fail;

	outputBufferDesc.ulVersion = SECBUFFER_VERSION;
	outputBufferDesc.cBuffers = 1;
	outputBufferDesc.pBuffers = &outputBuffer;
	if (!nla_sec_buffer_alloc(&outputBuffer, nla->cbMaxToken))
		goto fail;

	nla->status = nla_initialize_security_context(nla, FALSE, &inputBufferDesc, &outputBufferDesc);

	switch (nla->status)
	{
		case SEC_I_COMPLETE_AND_CONTINUE:
			if (!nla_complete_auth(nla, &outputBufferDesc))
				goto fail;
			if (!nla_client_send_token(nla, &outputBufferDesc))
				goto fail;
			break;
		case SEC_I_COMPLETE_NEEDED:  
			if (!nla_complete_auth(nla, &outputBufferDesc))
				goto fail;
			nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
			break;
		case SEC_E_OK:  
			nla->havePubKeyAuth = TRUE;
			status = nla_query_context_sizes(nla);

			if (status != SEC_E_OK)
				goto fail;

			if (nla->peerVersion < 5)
				status = nla_encrypt_public_key_echo(nla);
			else
				status = nla_encrypt_public_key_hash(nla);

			if (status != SEC_E_OK)
				goto fail;

			if (!nla_client_send_token(nla, &outputBufferDesc))
				goto fail;
			nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
			break;

		case SEC_I_CONTINUE_NEEDED:  
			if (!nla_client_send_token(nla, &outputBufferDesc))
				goto fail;
			nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
			break;

		default:
			WLog_ERR(TAG, "Unexpected NLA return %s", GetSecurityStatusString(nla->status));
			goto fail;
	}

	rc = 1;
fail:
	sspi_SecBufferFree(&inputBuffer);
	sspi_SecBufferFree(&outputBuffer);
	return rc;
}