static int nla_decode_ts_request(rdpNla* nla, wStream* s)
{
	WinPrAsn1Decoder dec, dec2, dec3;
	BOOL error;
	WinPrAsn1_tagId tag;
	WinPrAsn1_OctetString octet_string;
	WinPrAsn1_INTEGER val;
	UINT32 version = 0;
	char buffer[1024];

	WINPR_ASSERT(nla);
	WINPR_ASSERT(s);

	WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);

	WLog_DBG(TAG, "<<----- receiving...");

	/* TSRequest */
	if (!WinPrAsn1DecReadSequence(&dec, &dec2))
		return -1;
	dec = dec2;

	/* version [0] INTEGER */
	if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val))
		return -1;
	version = (UINT)val;
	WLog_DBG(TAG, "   <<----- protocol version %" PRIu32, version);

	if (nla->peerVersion == 0)
		nla->peerVersion = version;

	/* if the peer suddenly changed its version - kick it */
	if (nla->peerVersion != version)
	{
		WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
		         nla->peerVersion, version);
		return -1;
	}

	while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2))
	{
		switch (tag)
		{
			case 1:
				WLog_DBG(TAG, "   <<----- nego token");
				/* negoTokens [1] SEQUENCE OF SEQUENCE */
				if (!WinPrAsn1DecReadSequence(&dec2, &dec3) ||
				    !WinPrAsn1DecReadSequence(&dec3, &dec2))
					return -1;
				/* negoToken [0] OCTET STRING */
				if (!WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
				                                           FALSE) &&
				    error)
					return -1;
				if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
				                                    octet_string.len))
					return -1;
				break;
			case 2:
				WLog_DBG(TAG, "   <<----- auth info");
				/* authInfo [2] OCTET STRING */
				if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
					return -1;
				if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
				                                    octet_string.len))
					return -1;
				break;
			case 3:
				WLog_DBG(TAG, "   <<----- public key info");
				/* pubKeyAuth [3] OCTET STRING */
				if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
					return -1;
				if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
				                                    octet_string.len))
					return -1;
				break;
			case 4:
				/* errorCode [4] INTEGER */
				if (!WinPrAsn1DecReadInteger(&dec2, &val))
					return -1;
				nla->errorCode = (UINT)val;
				WLog_DBG(TAG, "   <<----- error code %s 0x%08" PRIx32,
				         winpr_strerror(nla->errorCode, buffer, sizeof(buffer)), nla->errorCode);
				break;
			case 5:
				WLog_DBG(TAG, "   <<----- client nonce");
				/* clientNonce [5] OCTET STRING */
				if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
					return -1;
				if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
				                                    octet_string.len))
					return -1;
				break;
			default:
				return -1;
		}
	}

	return 1;
}
static int nla_decode_ts_request(rdpNla* nla, wStream* s)
{
	WinPrAsn1Decoder dec, dec2, dec3;
	BOOL error;
	WinPrAsn1_tagId tag;
	WinPrAsn1_OctetString octet_string;
	WinPrAsn1_INTEGER val;
	UINT32 version = 0;
	char buffer[1024];

	WINPR_ASSERT(nla);
	WINPR_ASSERT(s);

	WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);

	WLog_DBG(TAG, "<<----- receiving...");

	 
	if (!WinPrAsn1DecReadSequence(&dec, &dec2))
		return -1;
	dec = dec2;

	 
	if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val))
		return -1;
	version = (UINT)val;
	WLog_DBG(TAG, "   <<----- protocol version %" PRIu32, version);

	if (nla->peerVersion == 0)
		nla->peerVersion = version;

	 
	if (nla->peerVersion != version)
	{
		WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
		         nla->peerVersion, version);
		return -1;
	}

	while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2))
	{
		switch (tag)
		{
			case 1:
				WLog_DBG(TAG, "   <<----- nego token");
				 
				if (!WinPrAsn1DecReadSequence(&dec2, &dec3) ||
				    !WinPrAsn1DecReadSequence(&dec3, &dec2))
					return -1;
				 
				if (!WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
				                                           FALSE) &&
				    error)
					return -1;
				if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
				                                    octet_string.len))
					return -1;
				break;
			case 2:
				WLog_DBG(TAG, "   <<----- auth info");
				 
				if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
					return -1;
				if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
				                                    octet_string.len))
					return -1;
				break;
			case 3:
				WLog_DBG(TAG, "   <<----- public key info");
				 
				if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
					return -1;
				if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
				                                    octet_string.len))
					return -1;
				break;
			case 4:
				 
				if (!WinPrAsn1DecReadInteger(&dec2, &val))
					return -1;
				nla->errorCode = (UINT)val;
				WLog_DBG(TAG, "   <<----- error code %s 0x%08" PRIx32,
				         winpr_strerror(nla->errorCode, buffer, sizeof(buffer)), nla->errorCode);
				break;
			case 5:
				WLog_DBG(TAG, "   <<----- client nonce");
				 
				if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
					return -1;
				if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
				                                    octet_string.len))
					return -1;
				break;
			default:
				return -1;
		}
	}

	return 1;
}