From 683e05a51b05f5eb9e4044e6c7f32c74c837c68c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 8 Nov 2012 23:45:29 -0500 Subject: [PATCH] libfreerdp-core: implemented parsing of TsProxyCreateTunnel response --- libfreerdp/core/tsg.c | 176 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 157 insertions(+), 19 deletions(-) diff --git a/libfreerdp/core/tsg.c b/libfreerdp/core/tsg.c index c57d35528..372deccc3 100644 --- a/libfreerdp/core/tsg.c +++ b/libfreerdp/core/tsg.c @@ -170,7 +170,7 @@ DWORD TsProxySendToServer(handle_t IDL_handle, byte pRpcMessage[], UINT32 count, return length; } -BOOL tsg_proxy_create_tunnel(rdpTsg* tsg) +BOOL tsg_proxy_create_tunnel_write_request(rdpTsg* tsg) { int status; BYTE* buffer; @@ -178,19 +178,6 @@ BOOL tsg_proxy_create_tunnel(rdpTsg* tsg) UINT32 NapCapabilities; rdpRpc* rpc = tsg->rpc; - /** - * OpNum = 1 - * - * HRESULT TsProxyCreateTunnel( - * [in, ref] PTSG_PACKET tsgPacket, - * [out, ref] PTSG_PACKET* tsgPacketResponse, - * [out] PTUNNEL_CONTEXT_HANDLE_SERIALIZE* tunnelContext, - * [out] unsigned long* tunnelId - * ); - */ - - DEBUG_TSG("TsProxyCreateTunnel"); - length = 108; buffer = (BYTE*) malloc(length); @@ -230,22 +217,138 @@ BOOL tsg_proxy_create_tunnel(rdpTsg* tsg) status = rpc_tsg_write(rpc, buffer, length, TsProxyCreateTunnelOpnum); if (status <= 0) - { - printf("TsProxyCreateTunnel write failure\n"); return FALSE; - } free(buffer); + return TRUE; +} + +BOOL tsg_proxy_create_tunnel_read_response(rdpTsg* tsg) +{ + int status; + BYTE* buffer; + UINT32 count; + UINT32 length; + UINT32 offset; + UINT32 Pointer; + PTSG_PACKET packet; + UINT32 SwitchValue; + rdpRpc* rpc = tsg->rpc; + PTSG_PACKET_CAPABILITIES tsgCaps; + PTSG_PACKET_VERSIONCAPS versionCaps; + PTSG_PACKET_CAPS_RESPONSE packetCapsResponse; + status = rpc_recv_pdu(rpc); if (status <= 0) + return FALSE; + + length = status; + buffer = rpc->buffer; + + packet = (PTSG_PACKET) malloc(sizeof(TSG_PACKET)); + ZeroMemory(packet, sizeof(TSG_PACKET)); + + packet->packetId = *((UINT32*) &buffer[28]); /* PacketId */ + SwitchValue = *((UINT32*) &buffer[32]); /* SwitchValue */ + + if ((packet->packetId != TSG_PACKET_TYPE_CAPS_RESPONSE) || + (SwitchValue != TSG_PACKET_TYPE_CAPS_RESPONSE)) { - printf("TsProxyCreateTunnel read failure\n"); + printf("Unexpected PacketId: 0x%08X\n", packet->packetId); return FALSE; } - CopyMemory(tsg->TunnelContext, rpc->buffer + (status - 48), 16); + packetCapsResponse = (PTSG_PACKET_CAPS_RESPONSE) malloc(sizeof(TSG_PACKET_CAPS_RESPONSE)); + ZeroMemory(packetCapsResponse, sizeof(TSG_PACKET_CAPS_RESPONSE)); + packet->tsgPacket.packetCapsResponse = packetCapsResponse; + + /* PacketQuarResponsePtr (4 bytes) */ + packetCapsResponse->pktQuarEncResponse.flags = *((UINT32*) &buffer[40]); /* Flags */ + packetCapsResponse->pktQuarEncResponse.certChainLen = *((UINT32*) &buffer[44]); /* CertChainLength */ + /* CertChainDataPtr (4 bytes) */ + CopyMemory(&packetCapsResponse->pktQuarEncResponse.nonce, &buffer[52], 16); /* Nonce */ + offset = 68; + + Pointer = *((UINT32*) &buffer[offset]); /* Ptr */ + offset += 4; + + if (Pointer == 0x0002000C) + { + /* Not sure exactly what this is */ + offset += 4; /* 0x00000001 (4 bytes) */ + offset += 4; /* 0x00000001 (4 bytes) */ + offset += 4; /* 0x00000000 (4 bytes) */ + offset += 4; /* 0x00000001 (4 bytes) */ + } + + Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x00020014 */ + offset += 4; + + offset += 4; /* MaxCount (4 bytes) */ + offset += 4; /* Offset (4 bytes) */ + count = *((UINT32*) &buffer[offset]); /* ActualCount (4 bytes) */ + offset += 4; + + /* + * CertChainData is a wide character string, and the count is + * given in characters excluding the null terminator, therefore: + * size = ((count + 1) * 2) + */ + offset += ((count + 1) * 2); /* CertChainData */ + + versionCaps = (PTSG_PACKET_VERSIONCAPS) malloc(sizeof(TSG_PACKET_VERSIONCAPS)); + ZeroMemory(versionCaps, sizeof(TSG_PACKET_VERSIONCAPS)); + packetCapsResponse->pktQuarEncResponse.versionCaps = versionCaps; + + versionCaps->tsgHeader.ComponentId = *((UINT16*) &buffer[offset]); /* ComponentId */ + versionCaps->tsgHeader.PacketId = *((UINT16*) &buffer[offset + 2]); /* PacketId */ + offset += 4; + + if (versionCaps->tsgHeader.ComponentId != TS_GATEWAY_TRANSPORT) + { + printf("Unexpected ComponentId: 0x%04X\n", versionCaps->tsgHeader.ComponentId); + return FALSE; + } + + Pointer = *((UINT32*) &buffer[offset]); /* TsgCapsPtr */ + versionCaps->numCapabilities = *((UINT32*) &buffer[offset + 4]); /* NumCapabilities */ + versionCaps->majorVersion = *((UINT16*) &buffer[offset + 8]); /* MajorVersion */ + versionCaps->majorVersion = *((UINT16*) &buffer[offset + 10]); /* MinorVersion */ + versionCaps->quarantineCapabilities = *((UINT16*) &buffer[offset + 12]); /* QuarantineCapabilities */ + offset += 14; + + /* 4-byte alignment */ + rpc_offset_align(&offset, 4); + + tsgCaps = (PTSG_PACKET_CAPABILITIES) malloc(sizeof(TSG_PACKET_CAPABILITIES)); + ZeroMemory(tsgCaps, sizeof(TSG_PACKET_CAPABILITIES)); + versionCaps->tsgCaps = tsgCaps; + + offset += 4; /* MaxCount (4 bytes) */ + tsgCaps->capabilityType = *((UINT32*) &buffer[offset]); /* CapabilityType */ + SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */ + offset += 8; + + if ((SwitchValue != TSG_CAPABILITY_TYPE_NAP) || + (tsgCaps->capabilityType != TSG_CAPABILITY_TYPE_NAP)) + { + printf("Unexpected CapabilityType: 0x%08X, Expected TSG_CAPABILITY_TYPE_NAP\n", + tsgCaps->capabilityType); + return FALSE; + } + + tsgCaps->tsgPacket.tsgCapNap.capabilities = *((UINT32*) &buffer[offset]); /* Capabilities */ + offset += 4; + + /* ??? (16 bytes): all zeros */ + offset += 16; + + offset += 4; /* ContextType (4 bytes) */ + CopyMemory(tsg->TunnelContext, &buffer[offset], 16); /* ContextUuid */ + + /* TODO: trailing bytes */ #ifdef WITH_DEBUG_TSG printf("TSG TunnelContext:\n"); @@ -253,6 +356,41 @@ BOOL tsg_proxy_create_tunnel(rdpTsg* tsg) printf("\n"); #endif + free(tsgCaps); + free(versionCaps); + free(packetCapsResponse); + free(packet); + + return TRUE; +} + +BOOL tsg_proxy_create_tunnel(rdpTsg* tsg) +{ + /** + * OpNum = 1 + * + * HRESULT TsProxyCreateTunnel( + * [in, ref] PTSG_PACKET tsgPacket, + * [out, ref] PTSG_PACKET* tsgPacketResponse, + * [out] PTUNNEL_CONTEXT_HANDLE_SERIALIZE* tunnelContext, + * [out] unsigned long* tunnelId + * ); + */ + + DEBUG_TSG("TsProxyCreateTunnel"); + + if (!tsg_proxy_create_tunnel_write_request(tsg)) + { + printf("TsProxyCreateTunnel: error writing request\n"); + return FALSE; + } + + if (!tsg_proxy_create_tunnel_read_response(tsg)) + { + printf("TsProxyCreateTunnel: error reading response\n"); + return FALSE; + } + return TRUE; }