Blame SOURCES/Implement-missing-TSG-debug-functions.patch

35d644
From ea20ba13ec764b30d6642cd570929e71e97d00f1 Mon Sep 17 00:00:00 2001
35d644
From: akallabeth <akallabeth@posteo.net>
35d644
Date: Tue, 12 Oct 2021 13:33:41 +0200
35d644
Subject: [PATCH] Implemented missing TSG debug functions
35d644
35d644
(cherry picked from commit c06c4638061b0305a269dbb8f7c87009cf886f02)
35d644
---
35d644
 libfreerdp/core/gateway/tsg.c | 330 ++++++++++++++++++++++++++++++++--
35d644
 1 file changed, 313 insertions(+), 17 deletions(-)
35d644
35d644
diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c
35d644
index 1626b91..3376fb0 100644
35d644
--- a/libfreerdp/core/gateway/tsg.c
35d644
+++ b/libfreerdp/core/gateway/tsg.c
35d644
@@ -24,6 +24,7 @@
35d644
 #include "config.h"
35d644
 #endif
35d644
 
35d644
+#include <winpr/assert.h>
35d644
 #include <winpr/crt.h>
35d644
 #include <winpr/ndr.h>
35d644
 #include <winpr/error.h>
35d644
@@ -39,13 +40,14 @@
35d644
 
35d644
 #define TAG FREERDP_TAG("core.gateway.tsg")
35d644
 
35d644
+#define TSG_CAPABILITY_TYPE_NAP 0x00000001
35d644
+
35d644
 #define TSG_PACKET_TYPE_HEADER 0x00004844
35d644
 #define TSG_PACKET_TYPE_VERSIONCAPS 0x00005643
35d644
 #define TSG_PACKET_TYPE_QUARCONFIGREQUEST 0x00005143
35d644
 #define TSG_PACKET_TYPE_QUARREQUEST 0x00005152
35d644
 #define TSG_PACKET_TYPE_RESPONSE 0x00005052
35d644
 #define TSG_PACKET_TYPE_QUARENC_RESPONSE 0x00004552
35d644
-#define TSG_CAPABILITY_TYPE_NAP 0x00000001
35d644
 #define TSG_PACKET_TYPE_CAPS_RESPONSE 0x00004350
35d644
 #define TSG_PACKET_TYPE_MSGREQUEST_PACKET 0x00004752
35d644
 #define TSG_PACKET_TYPE_MESSAGE_PACKET 0x00004750
35d644
@@ -308,16 +310,35 @@ static BOOL tsg_print(char** buffer, size_t* len, const char* fmt, ...)
35d644
 static BOOL tsg_packet_header_to_string(char** buffer, size_t* length,
35d644
                                         const TSG_PACKET_HEADER* header)
35d644
 {
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(header);
35d644
+
35d644
 	return tsg_print(buffer, length,
35d644
 	                 "header { ComponentId=0x%04" PRIx16 ", PacketId=0x%04" PRIx16 " }",
35d644
 	                 header->ComponentId, header->PacketId);
35d644
 }
35d644
 
35d644
+static BOOL tsg_type_capability_nap_to_string(char** buffer, size_t* length,
35d644
+                                              const TSG_CAPABILITY_NAP* cur)
35d644
+{
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(cur);
35d644
+
35d644
+	return tsg_print(buffer, length, "%s { capabilities=0x%08" PRIx32 " }",
35d644
+	                 tsg_packet_id_to_string(TSG_CAPABILITY_TYPE_NAP), cur->capabilities);
35d644
+}
35d644
+
35d644
 static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length,
35d644
                                               const TSG_PACKET_CAPABILITIES* caps, UINT32 numCaps)
35d644
 {
35d644
 	UINT32 x;
35d644
 
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
 	if (!tsg_print(buffer, length, "capabilities { "))
35d644
 		return FALSE;
35d644
 
35d644
@@ -327,9 +348,7 @@ static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length,
35d644
 		switch (cur->capabilityType)
35d644
 		{
35d644
 			case TSG_CAPABILITY_TYPE_NAP:
35d644
-				if (!tsg_print(buffer, length, "%s { capabilities=0x%08" PRIx32 " }",
35d644
-				               tsg_packet_id_to_string(cur->capabilityType),
35d644
-				               cur->tsgPacket.tsgCapNap.capabilities))
35d644
+				if (!tsg_type_capability_nap_to_string(buffer, length, &cur->tsgPacket.tsgCapNap))
35d644
 					return FALSE;
35d644
 				break;
35d644
 			default:
35d644
@@ -344,6 +363,10 @@ static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length,
35d644
 static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length,
35d644
                                              const TSG_PACKET_VERSIONCAPS* caps)
35d644
 {
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
 	if (!tsg_print(buffer, length, "versioncaps { "))
35d644
 		return FALSE;
35d644
 	if (!tsg_packet_header_to_string(buffer, length, &caps->tsgHeader))
35d644
@@ -365,6 +388,277 @@ static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length,
35d644
 	return tsg_print(buffer, length, " }");
35d644
 }
35d644
 
35d644
+static BOOL tsg_packet_quarconfigrequest_to_string(char** buffer, size_t* length,
35d644
+                                                   const TSG_PACKET_QUARCONFIGREQUEST* caps)
35d644
+{
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
+	if (!tsg_print(buffer, length, "quarconfigrequest { "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_print(buffer, length, " "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_print(buffer, length, " flags=0x%08" PRIx32, caps->flags))
35d644
+		return FALSE;
35d644
+
35d644
+	return tsg_print(buffer, length, " }");
35d644
+}
35d644
+
35d644
+static BOOL tsg_packet_quarrequest_to_string(char** buffer, size_t* length,
35d644
+                                             const TSG_PACKET_QUARREQUEST* caps)
35d644
+{
35d644
+	BOOL rc = FALSE;
35d644
+	char* name = NULL;
35d644
+	char* strdata = NULL;
35d644
+
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
+	if (!tsg_print(buffer, length, "quarrequest { "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_print(buffer, length, " "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (caps->nameLength > 0)
35d644
+	{
35d644
+		if (ConvertFromUnicode(CP_UTF8, 0, caps->machineName, caps->nameLength, &name, 0, NULL,
35d644
+		                       NULL) < 0)
35d644
+			return FALSE;
35d644
+	}
35d644
+
35d644
+	strdata = winpr_BinToHexString(caps->data, caps->dataLen, TRUE);
35d644
+	if (strdata || (caps->dataLen == 0))
35d644
+		rc = tsg_print(buffer, length,
35d644
+		               " flags=0x%08" PRIx32 ", machineName=%s [%" PRIu32 "], data[%" PRIu32 "]=%s",
35d644
+		               caps->flags, name, caps->nameLength, caps->dataLen, strdata);
35d644
+	free(name);
35d644
+	free(strdata);
35d644
+	if (!rc)
35d644
+		return FALSE;
35d644
+
35d644
+	return tsg_print(buffer, length, " }");
35d644
+}
35d644
+
35d644
+static const char* tsg_bool_to_string(BOOL val)
35d644
+{
35d644
+	if (val)
35d644
+		return "true";
35d644
+	return "false";
35d644
+}
35d644
+
35d644
+static const char* tsg_redirection_flags_to_string(char* buffer, size_t size,
35d644
+                                                   const TSG_REDIRECTION_FLAGS* flags)
35d644
+{
35d644
+	WINPR_ASSERT(buffer || (size == 0));
35d644
+	WINPR_ASSERT(flags);
35d644
+
35d644
+	_snprintf(buffer, size,
35d644
+	          "enableAllRedirections=%s,  disableAllRedirections=%s, driveRedirectionDisabled=%s, "
35d644
+	          "printerRedirectionDisabled=%s, portRedirectionDisabled=%s, reserved=%s, "
35d644
+	          "clipboardRedirectionDisabled=%s, pnpRedirectionDisabled=%s",
35d644
+	          tsg_bool_to_string(flags->enableAllRedirections),
35d644
+	          tsg_bool_to_string(flags->disableAllRedirections),
35d644
+	          tsg_bool_to_string(flags->driveRedirectionDisabled),
35d644
+	          tsg_bool_to_string(flags->printerRedirectionDisabled),
35d644
+	          tsg_bool_to_string(flags->portRedirectionDisabled),
35d644
+	          tsg_bool_to_string(flags->reserved),
35d644
+	          tsg_bool_to_string(flags->clipboardRedirectionDisabled),
35d644
+	          tsg_bool_to_string(flags->pnpRedirectionDisabled));
35d644
+	return buffer;
35d644
+}
35d644
+
35d644
+static BOOL tsg_packet_response_to_string(char** buffer, size_t* length,
35d644
+                                          const TSG_PACKET_RESPONSE* caps)
35d644
+{
35d644
+	BOOL rc = FALSE;
35d644
+	char* strdata = NULL;
35d644
+	char tbuffer[8192] = { 0 };
35d644
+
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
+	if (!tsg_print(buffer, length, "response { "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_print(buffer, length, " "))
35d644
+		return FALSE;
35d644
+
35d644
+	strdata = winpr_BinToHexString(caps->responseData, caps->responseDataLen, TRUE);
35d644
+	if (strdata || (caps->responseDataLen == 0))
35d644
+		rc = tsg_print(
35d644
+		    buffer, length,
35d644
+		    " flags=0x%08" PRIx32 ", reserved=0x%08" PRIx32 ", responseData[%" PRIu32
35d644
+		    "]=%s, redirectionFlags={ %s }",
35d644
+		    caps->flags, caps->reserved, caps->responseDataLen, strdata,
35d644
+		    tsg_redirection_flags_to_string(tbuffer, ARRAYSIZE(tbuffer), &caps->redirectionFlags));
35d644
+	free(strdata);
35d644
+	if (!rc)
35d644
+		return FALSE;
35d644
+
35d644
+	return tsg_print(buffer, length, " }");
35d644
+}
35d644
+
35d644
+static BOOL tsg_packet_quarenc_response_to_string(char** buffer, size_t* length,
35d644
+                                                  const TSG_PACKET_QUARENC_RESPONSE* caps)
35d644
+{
35d644
+	BOOL rc = FALSE;
35d644
+	char* strdata = NULL;
35d644
+	RPC_CSTR uuid;
35d644
+	char tbuffer[8192] = { 0 };
35d644
+	size_t size = ARRAYSIZE(tbuffer);
35d644
+	char* ptbuffer = tbuffer;
35d644
+
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
+	if (!tsg_print(buffer, length, "quarenc_response { "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_print(buffer, length, " "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (caps->certChainLen > 0)
35d644
+	{
35d644
+		if (ConvertFromUnicode(CP_UTF8, 0, caps->certChainData, caps->certChainLen, &strdata, 0,
35d644
+		                       NULL, NULL) <= 0)
35d644
+			return FALSE;
35d644
+	}
35d644
+
35d644
+	tsg_packet_versioncaps_to_string(&ptbuffer, &size, caps->versionCaps);
35d644
+	UuidToStringA(&caps->nonce, &uuid);
35d644
+	if (strdata || (caps->certChainLen == 0))
35d644
+		rc =
35d644
+		    tsg_print(buffer, length,
35d644
+		              " flags=0x%08" PRIx32 ", certChain[%" PRIu32 "]=%s, nonce=%s, versionCaps=%s",
35d644
+		              caps->flags, caps->certChainLen, strdata, uuid, tbuffer);
35d644
+	free(strdata);
35d644
+	free(uuid);
35d644
+	if (!rc)
35d644
+		return FALSE;
35d644
+
35d644
+	return tsg_print(buffer, length, " }");
35d644
+}
35d644
+
35d644
+static BOOL tsg_packet_message_response_to_string(char** buffer, size_t* length,
35d644
+                                                  const TSG_PACKET_MSG_RESPONSE* caps)
35d644
+{
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
+	if (!tsg_print(buffer, length, "msg_response { "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_print(buffer, length,
35d644
+	               " msgID=0x%08" PRIx32 ", msgType=0x%08" PRIx32 ", isMsgPresent=%" PRId32,
35d644
+	               caps->msgID, caps->msgType, caps->isMsgPresent))
35d644
+		return FALSE;
35d644
+
35d644
+	return tsg_print(buffer, length, " }");
35d644
+}
35d644
+
35d644
+static BOOL tsg_packet_caps_response_to_string(char** buffer, size_t* length,
35d644
+                                               const TSG_PACKET_CAPS_RESPONSE* caps)
35d644
+{
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
+	if (!tsg_print(buffer, length, "caps_response { "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_packet_quarenc_response_to_string(buffer, length, &caps->pktQuarEncResponse))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_packet_message_response_to_string(buffer, length, &caps->pktConsentMessage))
35d644
+		return FALSE;
35d644
+
35d644
+	return tsg_print(buffer, length, " }");
35d644
+}
35d644
+
35d644
+static BOOL tsg_packet_message_request_to_string(char** buffer, size_t* length,
35d644
+                                                 const TSG_PACKET_MSG_REQUEST* caps)
35d644
+{
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
+	if (!tsg_print(buffer, length, "caps_message_request { "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_print(buffer, length, " maxMessagesPerBatch=%" PRIu32, caps->maxMessagesPerBatch))
35d644
+		return FALSE;
35d644
+
35d644
+	return tsg_print(buffer, length, " }");
35d644
+}
35d644
+
35d644
+static BOOL tsg_packet_auth_to_string(char** buffer, size_t* length, const TSG_PACKET_AUTH* caps)
35d644
+{
35d644
+	BOOL rc = FALSE;
35d644
+	char* strdata = NULL;
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
+	if (!tsg_print(buffer, length, "caps_message_request { "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_packet_versioncaps_to_string(buffer, length, &caps->tsgVersionCaps))
35d644
+		return FALSE;
35d644
+
35d644
+	strdata = winpr_BinToHexString(caps->cookie, caps->cookieLen, TRUE);
35d644
+	if (strdata || (caps->cookieLen == 0))
35d644
+		rc = tsg_print(buffer, length, " cookie[%" PRIu32 "]=%s", caps->cookieLen, strdata);
35d644
+	free(strdata);
35d644
+	if (!rc)
35d644
+		return FALSE;
35d644
+
35d644
+	return tsg_print(buffer, length, " }");
35d644
+}
35d644
+
35d644
+static BOOL tsg_packet_reauth_to_string(char** buffer, size_t* length,
35d644
+                                        const TSG_PACKET_REAUTH* caps)
35d644
+{
35d644
+	BOOL rc = FALSE;
35d644
+	WINPR_ASSERT(buffer);
35d644
+	WINPR_ASSERT(length);
35d644
+	WINPR_ASSERT(caps);
35d644
+
35d644
+	if (!tsg_print(buffer, length, "caps_message_request { "))
35d644
+		return FALSE;
35d644
+
35d644
+	if (!tsg_print(buffer, length, " tunnelContext=0x%08" PRIx32 ", packetId=%s [0x%08" PRIx32 "]",
35d644
+	               caps->tunnelContext, tsg_packet_id_to_string(caps->packetId), caps->packetId))
35d644
+		return FALSE;
35d644
+
35d644
+	switch (caps->packetId)
35d644
+	{
35d644
+		case TSG_PACKET_TYPE_VERSIONCAPS:
35d644
+			rc = tsg_packet_versioncaps_to_string(buffer, length,
35d644
+			                                      caps->tsgInitialPacket.packetVersionCaps);
35d644
+			break;
35d644
+		case TSG_PACKET_TYPE_AUTH:
35d644
+			rc = tsg_packet_auth_to_string(buffer, length, caps->tsgInitialPacket.packetAuth);
35d644
+			break;
35d644
+		default:
35d644
+			rc = tsg_print(buffer, length, "TODO: Unhandled packet type %s [0x%08" PRIx32 "]",
35d644
+			               tsg_packet_id_to_string(caps->packetId), caps->packetId);
35d644
+			break;
35d644
+	}
35d644
+
35d644
+	if (!rc)
35d644
+		return FALSE;
35d644
+
35d644
+	return tsg_print(buffer, length, " }");
35d644
+}
35d644
+
35d644
 static const char* tsg_packet_to_string(const TSG_PACKET* packet)
35d644
 {
35d644
 	size_t len = 8192;
35d644
@@ -387,43 +681,45 @@ static const char* tsg_packet_to_string(const TSG_PACKET* packet)
35d644
 				goto fail;
35d644
 			break;
35d644
 		case TSG_PACKET_TYPE_QUARCONFIGREQUEST:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
+			if (!tsg_packet_quarconfigrequest_to_string(&buffer, &len,
35d644
+			                                            packet->tsgPacket.packetQuarConfigRequest))
35d644
 				goto fail;
35d644
 			break;
35d644
 		case TSG_PACKET_TYPE_QUARREQUEST:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
+			if (!tsg_packet_quarrequest_to_string(&buffer, &len,
35d644
+			                                      packet->tsgPacket.packetQuarRequest))
35d644
 				goto fail;
35d644
 			break;
35d644
 		case TSG_PACKET_TYPE_RESPONSE:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
+			if (!tsg_packet_response_to_string(&buffer, &len, packet->tsgPacket.packetResponse))
35d644
 				goto fail;
35d644
 			break;
35d644
 		case TSG_PACKET_TYPE_QUARENC_RESPONSE:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
-				goto fail;
35d644
-			break;
35d644
-		case TSG_CAPABILITY_TYPE_NAP:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
+			if (!tsg_packet_quarenc_response_to_string(&buffer, &len,
35d644
+			                                           packet->tsgPacket.packetQuarEncResponse))
35d644
 				goto fail;
35d644
 			break;
35d644
 		case TSG_PACKET_TYPE_CAPS_RESPONSE:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
+			if (!tsg_packet_caps_response_to_string(&buffer, &len,
35d644
+			                                        packet->tsgPacket.packetCapsResponse))
35d644
 				goto fail;
35d644
 			break;
35d644
 		case TSG_PACKET_TYPE_MSGREQUEST_PACKET:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
+			if (!tsg_packet_message_request_to_string(&buffer, &len,
35d644
+			                                          packet->tsgPacket.packetMsgRequest))
35d644
 				goto fail;
35d644
 			break;
35d644
 		case TSG_PACKET_TYPE_MESSAGE_PACKET:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
+			if (!tsg_packet_message_response_to_string(&buffer, &len,
35d644
+			                                           packet->tsgPacket.packetMsgResponse))
35d644
 				goto fail;
35d644
 			break;
35d644
 		case TSG_PACKET_TYPE_AUTH:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
+			if (!tsg_packet_auth_to_string(&buffer, &len, packet->tsgPacket.packetAuth))
35d644
 				goto fail;
35d644
 			break;
35d644
 		case TSG_PACKET_TYPE_REAUTH:
35d644
-			if (!tsg_print(&buffer, &len, "TODO"))
35d644
+			if (!tsg_packet_reauth_to_string(&buffer, &len, packet->tsgPacket.packetReauth))
35d644
 				goto fail;
35d644
 			break;
35d644
 		default: