23#include <freerdp/config.h> 
   25#include "../settings.h" 
   27#include <winpr/assert.h> 
   29#include <winpr/error.h> 
   30#include <winpr/print.h> 
   31#include <winpr/stream.h> 
   33#include <freerdp/log.h> 
   36#include "rpc_client.h" 
   39#include "../../crypto/opensslcompat.h" 
   41#define TAG FREERDP_TAG("core.gateway.tsg") 
   43#define TSG_CAPABILITY_TYPE_NAP 0x00000001 
   45#define TSG_PACKET_TYPE_HEADER 0x00004844 
   46#define TSG_PACKET_TYPE_VERSIONCAPS 0x00005643 
   47#define TSG_PACKET_TYPE_QUARCONFIGREQUEST 0x00005143 
   48#define TSG_PACKET_TYPE_QUARREQUEST 0x00005152 
   49#define TSG_PACKET_TYPE_RESPONSE 0x00005052 
   50#define TSG_PACKET_TYPE_QUARENC_RESPONSE 0x00004552 
   51#define TSG_PACKET_TYPE_CAPS_RESPONSE 0x00004350 
   52#define TSG_PACKET_TYPE_MSGREQUEST_PACKET 0x00004752 
   53#define TSG_PACKET_TYPE_MESSAGE_PACKET 0x00004750 
   54#define TSG_PACKET_TYPE_AUTH 0x00004054 
   55#define TSG_PACKET_TYPE_REAUTH 0x00005250 
   57typedef WCHAR* RESOURCENAME;
 
   61  RESOURCENAME* resourceName;
 
   62  UINT32 numResourceNames;
 
   63  RESOURCENAME* alternateResourceNames;
 
   64  UINT16 numAlternateResourceNames;
 
   81  TSG_CAPABILITY_NAP tsgCapNap;
 
   82} TSG_CAPABILITIES_UNION;
 
   86  UINT32 capabilityType;
 
   87  TSG_CAPABILITIES_UNION tsgPacket;
 
   88} TSG_PACKET_CAPABILITIES;
 
   92  TSG_PACKET_HEADER tsgHeader;
 
   93  TSG_PACKET_CAPABILITIES tsgCaps;
 
   94  UINT32 numCapabilities;
 
   97  UINT16 quarantineCapabilities;
 
   98} TSG_PACKET_VERSIONCAPS;
 
  103} TSG_PACKET_QUARCONFIGREQUEST;
 
  112} TSG_PACKET_QUARREQUEST;
 
  116  BOOL enableAllRedirections;
 
  117  BOOL disableAllRedirections;
 
  118  BOOL driveRedirectionDisabled;
 
  119  BOOL printerRedirectionDisabled;
 
  120  BOOL portRedirectionDisabled;
 
  122  BOOL clipboardRedirectionDisabled;
 
  123  BOOL pnpRedirectionDisabled;
 
  124} TSG_REDIRECTION_FLAGS;
 
  131  UINT32 responseDataLen;
 
  132  TSG_REDIRECTION_FLAGS redirectionFlags;
 
  133} TSG_PACKET_RESPONSE;
 
  139  WCHAR* certChainData;
 
  141  TSG_PACKET_VERSIONCAPS versionCaps;
 
  142} TSG_PACKET_QUARENC_RESPONSE;
 
  146  INT32 isDisplayMandatory;
 
  147  INT32 isConsentMandatory;
 
  150} TSG_PACKET_STRING_MESSAGE;
 
  154  UINT64 tunnelContext;
 
  155} TSG_PACKET_REAUTH_MESSAGE;
 
  162} TSG_PACKET_MSG_RESPONSE;
 
  166  TSG_PACKET_QUARENC_RESPONSE pktQuarEncResponse;
 
  167  TSG_PACKET_MSG_RESPONSE pktConsentMessage;
 
  168} TSG_PACKET_CAPS_RESPONSE;
 
  172  UINT32 maxMessagesPerBatch;
 
  173} TSG_PACKET_MSG_REQUEST;
 
  177  TSG_PACKET_VERSIONCAPS tsgVersionCaps;
 
  184  TSG_PACKET_VERSIONCAPS packetVersionCaps;
 
  185  TSG_PACKET_AUTH packetAuth;
 
  186} TSG_INITIAL_PACKET_TYPE_UNION;
 
  190  UINT64 tunnelContext;
 
  192  TSG_INITIAL_PACKET_TYPE_UNION tsgInitialPacket;
 
  197  TSG_PACKET_HEADER packetHeader;
 
  198  TSG_PACKET_VERSIONCAPS packetVersionCaps;
 
  199  TSG_PACKET_QUARCONFIGREQUEST packetQuarConfigRequest;
 
  200  TSG_PACKET_QUARREQUEST packetQuarRequest;
 
  201  TSG_PACKET_RESPONSE packetResponse;
 
  202  TSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse;
 
  203  TSG_PACKET_CAPS_RESPONSE packetCapsResponse;
 
  204  TSG_PACKET_MSG_REQUEST packetMsgRequest;
 
  205  TSG_PACKET_MSG_RESPONSE packetMsgResponse;
 
  206  TSG_PACKET_AUTH packetAuth;
 
  207  TSG_PACKET_REAUTH packetReauth;
 
  208} TSG_PACKET_TYPE_UNION;
 
  213  TSG_PACKET_TYPE_UNION tsgPacket;
 
  227  rdpTransport* transport;
 
  228  UINT64 ReauthTunnelContext;
 
  236static BOOL TsProxyReadPacketSTringMessage(wLog* log, 
wStream* s, uint32_t* index,
 
  237                                           TSG_PACKET_STRING_MESSAGE* msg);
 
  238static BOOL tsg_stream_align(wLog* log, 
wStream* s, 
size_t align);
 
  240static const char* tsg_packet_id_to_string(UINT32 packetId)
 
  244    case TSG_PACKET_TYPE_HEADER:
 
  245      return "TSG_PACKET_TYPE_HEADER";
 
  246    case TSG_PACKET_TYPE_VERSIONCAPS:
 
  247      return "TSG_PACKET_TYPE_VERSIONCAPS";
 
  248    case TSG_PACKET_TYPE_QUARCONFIGREQUEST:
 
  249      return "TSG_PACKET_TYPE_QUARCONFIGREQUEST";
 
  250    case TSG_PACKET_TYPE_QUARREQUEST:
 
  251      return "TSG_PACKET_TYPE_QUARREQUEST";
 
  252    case TSG_PACKET_TYPE_RESPONSE:
 
  253      return "TSG_PACKET_TYPE_RESPONSE";
 
  254    case TSG_PACKET_TYPE_QUARENC_RESPONSE:
 
  255      return "TSG_PACKET_TYPE_QUARENC_RESPONSE";
 
  256    case TSG_CAPABILITY_TYPE_NAP:
 
  257      return "TSG_CAPABILITY_TYPE_NAP";
 
  258    case TSG_PACKET_TYPE_CAPS_RESPONSE:
 
  259      return "TSG_PACKET_TYPE_CAPS_RESPONSE";
 
  260    case TSG_PACKET_TYPE_MSGREQUEST_PACKET:
 
  261      return "TSG_PACKET_TYPE_MSGREQUEST_PACKET";
 
  262    case TSG_PACKET_TYPE_MESSAGE_PACKET:
 
  263      return "TSG_PACKET_TYPE_MESSAGE_PACKET";
 
  264    case TSG_PACKET_TYPE_AUTH:
 
  265      return "TSG_PACKET_TYPE_AUTH";
 
  266    case TSG_PACKET_TYPE_REAUTH:
 
  267      return "TSG_PACKET_TYPE_REAUTH";
 
  273static const char* tsg_component_id_to_string(UINT16 ComponentId, 
char* buffer, 
size_t bytelen)
 
  275  const char* str = NULL;
 
  283    ENTRY(TS_GATEWAY_TRANSPORT);
 
  290  (void)_snprintf(buffer, bytelen, 
"%s [0x%04" PRIx16 
"]", str, ComponentId);
 
  294static const char* tsg_state_to_string(TSG_STATE state)
 
  298    case TSG_STATE_INITIAL:
 
  299      return "TSG_STATE_INITIAL";
 
  300    case TSG_STATE_CONNECTED:
 
  301      return "TSG_STATE_CONNECTED";
 
  302    case TSG_STATE_AUTHORIZED:
 
  303      return "TSG_STATE_AUTHORIZED";
 
  304    case TSG_STATE_CHANNEL_CREATED:
 
  305      return "TSG_STATE_CHANNEL_CREATED";
 
  306    case TSG_STATE_PIPE_CREATED:
 
  307      return "TSG_STATE_PIPE_CREATED";
 
  308    case TSG_STATE_TUNNEL_CLOSE_PENDING:
 
  309      return "TSG_STATE_TUNNEL_CLOSE_PENDING";
 
  310    case TSG_STATE_CHANNEL_CLOSE_PENDING:
 
  311      return "TSG_STATE_CHANNEL_CLOSE_PENDING";
 
  312    case TSG_STATE_FINAL:
 
  313      return "TSG_STATE_FINAL";
 
  315      return "TSG_STATE_UNKNOWN";
 
  321  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
 
  324  WINPR_ASSERT(tunnelContext);
 
  325  Stream_Read_UINT32(s, tunnelContext->ContextType); 
 
  326  Stream_Read(s, &tunnelContext->ContextUuid,
 
  327              sizeof(tunnelContext->ContextUuid)); 
 
  331static BOOL TsProxyWriteTunnelContext(WINPR_ATTR_UNUSED wLog* log, 
wStream* s,
 
  334  if (!Stream_EnsureRemainingCapacity(s, 20))
 
  337  Stream_Write_UINT32(s, tunnelContext->ContextType); 
 
  338  Stream_Write(s, &tunnelContext->ContextUuid,
 
  339               sizeof(tunnelContext->ContextUuid)); 
 
  343static BOOL tsg_ndr_pointer_write(WINPR_ATTR_UNUSED wLog* log, 
wStream* s, UINT32* index,
 
  347  const UINT32 ndrPtr = 0x20000 + (*index) * 4;
 
  351  if (!Stream_EnsureRemainingCapacity(s, 4))
 
  356    Stream_Write_UINT32(s, ndrPtr); 
 
  357    (*index) = (*index) + 1;
 
  360    Stream_Write_UINT32(s, 0);
 
  364static BOOL tsg_ndr_pointer_read(wLog* log, 
wStream* s, UINT32* index, UINT32* ptrval,
 
  368  const UINT32 ndrPtr = 0x20000 + (*index) * 4;
 
  372  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
 
  376  Stream_Read_UINT32(s, val);
 
  384      WLog_Print(log, WLOG_WARN, 
"Read NDR pointer 0x%04" PRIx32 
" but expected 0x%04" PRIx32,
 
  386      if ((val & 0xFFFF0000) != (ndrPtr & 0xFFFF0000))
 
  393    WLog_Print(log, WLOG_ERROR, 
"NDR pointer == 0, but the field is required");
 
  400static BOOL tsg_ndr_write_string(WINPR_ATTR_UNUSED wLog* log, 
wStream* s, 
const WCHAR* str,
 
  403  if (!Stream_EnsureRemainingCapacity(s, 12 + length) || (length > UINT32_MAX))
 
  406  Stream_Write_UINT32(s, (UINT32)length);    
 
  407  Stream_Write_UINT32(s, 0);                 
 
  408  Stream_Write_UINT32(s, (UINT32)length);    
 
  409  Stream_Write_UTF16_String(s, str, length); 
 
  413static BOOL tsg_ndr_read_string(wLog* log, 
wStream* s, WCHAR** str, UINT32 lengthInBytes)
 
  417  UINT32 ActualCount = 0;
 
  419  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
 
  422  Stream_Read_UINT32(s, MaxCount);    
 
  423  Stream_Read_UINT32(s, Offset);      
 
  424  Stream_Read_UINT32(s, ActualCount); 
 
  425  if (ActualCount > MaxCount)
 
  427    WLog_Print(log, WLOG_ERROR,
 
  428               "failed to read string, ActualCount (%" PRIu32 
") > MaxCount (%" PRIu32 
")",
 
  429               ActualCount, MaxCount);
 
  434    WLog_Print(log, WLOG_ERROR, 
"Unsupported Offset (%" PRIu32 
"), expected 0", Offset);
 
  437  if (ActualCount > lengthInBytes / 
sizeof(WCHAR))
 
  439    WLog_Print(log, WLOG_ERROR,
 
  440               "failed to read string, ActualCount (%" PRIu32
 
  441               ") * sizeof(WCHAR) > lengthInBytes (%" PRIu32 
")",
 
  442               ActualCount, lengthInBytes);
 
  446    *str = Stream_PointerAs(s, WCHAR);
 
  448  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ActualCount * 
sizeof(WCHAR)))
 
  450  Stream_Seek(s, ActualCount * 
sizeof(WCHAR));
 
  454static BOOL tsg_ndr_read_packet_header(wLog* log, 
wStream* s, TSG_PACKET_HEADER* header)
 
  456  const UINT32 ComponentId = TS_GATEWAY_TRANSPORT;
 
  458  WINPR_ASSERT(header);
 
  459  if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, 2, 
sizeof(UINT16)))
 
  461  Stream_Read_UINT16(s, header->ComponentId);
 
  462  Stream_Read_UINT16(s, header->PacketId);
 
  464  if (ComponentId != header->ComponentId)
 
  466    char buffer[64] = { 0 };
 
  467    char buffer2[64] = { 0 };
 
  468    WLog_Print(log, WLOG_ERROR, 
"Unexpected ComponentId: %s, Expected %s",
 
  469               tsg_component_id_to_string(header->ComponentId, buffer, 
sizeof(buffer)),
 
  470               tsg_component_id_to_string(ComponentId, buffer2, 
sizeof(buffer2)));
 
  477static BOOL tsg_ndr_write_packet_header(WINPR_ATTR_UNUSED wLog* log, 
wStream* s,
 
  478                                        const TSG_PACKET_HEADER* header)
 
  480  WINPR_ASSERT(header);
 
  481  if (!Stream_EnsureRemainingCapacity(s, 2 * 
sizeof(UINT16)))
 
  483  Stream_Write_UINT16(s, header->ComponentId);
 
  484  Stream_Write_UINT16(s, header->PacketId);
 
  488static BOOL tsg_ndr_read_nap(wLog* log, 
wStream* s, TSG_CAPABILITY_NAP* nap)
 
  492  if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, 1, 
sizeof(UINT32)))
 
  494  Stream_Read_UINT32(s, nap->capabilities);
 
  498static BOOL tsg_ndr_write_nap(WINPR_ATTR_UNUSED wLog* log, 
wStream* s,
 
  499                              const TSG_CAPABILITY_NAP* nap)
 
  503  if (!Stream_EnsureRemainingCapacity(s, 1 * 
sizeof(UINT32)))
 
  505  Stream_Write_UINT32(s, nap->capabilities);
 
  509static BOOL tsg_ndr_read_tsg_caps(wLog* log, 
wStream* s, TSG_PACKET_CAPABILITIES* caps)
 
  511  UINT32 capabilityType = 0;
 
  515  if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, 3, 
sizeof(UINT32)))
 
  517  Stream_Read_UINT32(s, count);
 
  518  Stream_Read_UINT32(s, capabilityType);
 
  519  Stream_Read_UINT32(s, caps->capabilityType);
 
  520  if (capabilityType != caps->capabilityType)
 
  522    WLog_Print(log, WLOG_ERROR, 
"Inconsistent data, capabilityType %s != %s",
 
  523               tsg_packet_id_to_string(capabilityType),
 
  524               tsg_packet_id_to_string(caps->capabilityType));
 
  527  switch (caps->capabilityType)
 
  529    case TSG_CAPABILITY_TYPE_NAP:
 
  532        WLog_Print(log, WLOG_ERROR, 
"Inconsistent data, capabilityType %s count=%" PRIu32,
 
  533                   tsg_packet_id_to_string(capabilityType), count);
 
  536      return tsg_ndr_read_nap(log, s, &caps->tsgPacket.tsgCapNap);
 
  538      WLog_Print(log, WLOG_ERROR,
 
  539                 "unknown TSG_PACKET_CAPABILITIES::capabilityType 0x%04" PRIx32
 
  540                 " [count=%" PRIu32 
"]",
 
  541                 caps->capabilityType, count);
 
  546static BOOL tsg_ndr_write_tsg_caps(wLog* log, 
wStream* s, 
const TSG_PACKET_CAPABILITIES* caps)
 
  550  if (!Stream_EnsureRemainingCapacity(s, 2 * 
sizeof(UINT32)))
 
  552  Stream_Write_UINT32(s, caps->capabilityType);
 
  553  Stream_Write_UINT32(s, caps->capabilityType);
 
  555  switch (caps->capabilityType)
 
  557    case TSG_CAPABILITY_TYPE_NAP:
 
  558      return tsg_ndr_write_nap(log, s, &caps->tsgPacket.tsgCapNap);
 
  560      WLog_Print(log, WLOG_ERROR,
 
  561                 "unknown TSG_PACKET_CAPABILITIES::capabilityType 0x%04" PRIx32,
 
  562                 caps->capabilityType);
 
  567static BOOL tsg_ndr_read_version_caps(wLog* log, 
wStream* s, UINT32* index,
 
  568                                      TSG_PACKET_VERSIONCAPS* caps)
 
  571  if (!tsg_ndr_read_packet_header(log, s, &caps->tsgHeader))
 
  574  UINT32 TSGCapsPtr = 0;
 
  575  if (!tsg_ndr_pointer_read(log, s, index, &TSGCapsPtr, TRUE))
 
  578  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 10))
 
  580  Stream_Read_UINT32(s, caps->numCapabilities);
 
  581  Stream_Read_UINT16(s, caps->majorVersion);
 
  582  Stream_Read_UINT16(s, caps->minorVersion);
 
  583  Stream_Read_UINT16(s, caps->quarantineCapabilities);
 
  585  if (!tsg_stream_align(log, s, 4))
 
  588  if (caps->numCapabilities > 1)
 
  590    WLog_ERR(TAG, 
"TSG_PACKET_VERSIONCAPS::numCapabilities > 1 (%" PRIu32 
"), not supported!",
 
  591             caps->numCapabilities);
 
  595  return tsg_ndr_read_tsg_caps(log, s, &caps->tsgCaps);
 
  598static BOOL tsg_ndr_write_version_caps(wLog* log, 
wStream* s, UINT32* index,
 
  599                                       const TSG_PACKET_VERSIONCAPS* caps)
 
  602  if (!tsg_ndr_write_packet_header(log, s, &caps->tsgHeader))
 
  605  if (!tsg_ndr_pointer_write(log, s, index, 1)) 
 
  608  if (!Stream_EnsureRemainingCapacity(s, 10))
 
  611  if (caps->numCapabilities > 1)
 
  613    WLog_ERR(TAG, 
"TSG_PACKET_VERSIONCAPS::numCapabilities > 1 (%" PRIu32 
"), not supported!",
 
  614             caps->numCapabilities);
 
  617  Stream_Write_UINT32(s, caps->numCapabilities);
 
  618  Stream_Write_UINT16(s, caps->majorVersion);
 
  619  Stream_Write_UINT16(s, caps->minorVersion);
 
  620  Stream_Write_UINT16(s, caps->quarantineCapabilities);
 
  623  Stream_Write_UINT16(s, 0x0000);                
 
  624  Stream_Write_UINT32(s, caps->numCapabilities); 
 
  625  return tsg_ndr_write_tsg_caps(log, s, &caps->tsgCaps);
 
  628static BOOL tsg_ndr_read_quarenc_response(wLog* log, 
wStream* s, UINT32* index,
 
  629                                          TSG_PACKET_QUARENC_RESPONSE* quarenc)
 
  631  WINPR_ASSERT(quarenc);
 
  632  UINT32 CertChainDataPtr = 0;
 
  633  UINT32 VersionCapsPtr = 0;
 
  635  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
 
  637  Stream_Read_UINT32(s, quarenc->flags);
 
  638  Stream_Read_UINT32(s, quarenc->certChainLen);
 
  640  if (!tsg_ndr_pointer_read(log, s, index, &CertChainDataPtr, quarenc->certChainLen != 0))
 
  643  if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, 1, 
sizeof(quarenc->nonce)))
 
  645  Stream_Read(s, &quarenc->nonce, 
sizeof(quarenc->nonce));
 
  647  if (!tsg_ndr_pointer_read(log, s, index, &VersionCapsPtr, TRUE))
 
  653static BOOL tsg_ndr_read_quarenc_data(wLog* log, 
wStream* s, UINT32* index,
 
  654                                      TSG_PACKET_QUARENC_RESPONSE* quarenc)
 
  656  WINPR_ASSERT(quarenc);
 
  658  if (quarenc->certChainLen > 0)
 
  661    if (!tsg_ndr_read_string(log, s, &quarenc->certChainData,
 
  662                             quarenc->certChainLen * 
sizeof(WCHAR)))
 
  665    if (!tsg_stream_align(log, s, 4))
 
  669  return tsg_ndr_read_version_caps(log, s, index, &quarenc->versionCaps);
 
  672static BOOL tsg_ndr_write_auth(wLog* log, 
wStream* s, UINT32* index, 
const TSG_PACKET_AUTH* auth)
 
  676  if (!tsg_ndr_write_version_caps(log, s, index, &auth->tsgVersionCaps))
 
  679  if (!Stream_EnsureRemainingCapacity(s, 4))
 
  682  Stream_Write_UINT32(s, auth->cookieLen);
 
  683  if (!tsg_ndr_pointer_write(log, s, index, auth->cookieLen))
 
  686  if (!Stream_EnsureRemainingCapacity(s, auth->cookieLen))
 
  688  Stream_Write(s, auth->cookie, auth->cookieLen);
 
  692static BOOL tsg_ndr_write_reauth(wLog* log, 
wStream* s, UINT32* index,
 
  693                                 const TSG_PACKET_REAUTH* auth)
 
  697  if (!Stream_EnsureRemainingCapacity(s, 12))
 
  700  Stream_Write_UINT64(s, auth->tunnelContext); 
 
  701  Stream_Write_UINT32(s, auth->packetId);      
 
  703  switch (auth->packetId)
 
  705    case TSG_PACKET_TYPE_VERSIONCAPS:
 
  706      return tsg_ndr_write_version_caps(log, s, index,
 
  707                                        &auth->tsgInitialPacket.packetVersionCaps);
 
  708    case TSG_PACKET_TYPE_AUTH:
 
  709      return tsg_ndr_write_auth(log, s, index, &auth->tsgInitialPacket.packetAuth);
 
  711      WLog_Print(log, WLOG_ERROR, 
"unexpected packetId %s",
 
  712                 tsg_packet_id_to_string(auth->packetId));
 
  717static BOOL tsg_ndr_read_packet_response(wLog* log, 
wStream* s, UINT32* index,
 
  718                                         TSG_PACKET_RESPONSE* response)
 
  720  UINT32 ResponseDataPtr = 0;
 
  722  WINPR_ASSERT(response);
 
  724  if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, 2, 
sizeof(UINT32)))
 
  726  Stream_Read_UINT32(s, response->flags); 
 
  727  Stream_Seek_UINT32(s);                  
 
  729  if (response->flags != TSG_PACKET_TYPE_QUARREQUEST)
 
  731    WLog_Print(log, WLOG_ERROR,
 
  732               "Unexpected Packet Response Flags: 0x%08" PRIX32
 
  733               ", Expected TSG_PACKET_TYPE_QUARREQUEST",
 
  738  if (!tsg_ndr_pointer_read(log, s, index, &ResponseDataPtr, TRUE))
 
  741  if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, 10, 
sizeof(UINT32)))
 
  744  Stream_Read_UINT32(s, response->responseDataLen); 
 
  746      s, response->redirectionFlags.enableAllRedirections); 
 
  749      response->redirectionFlags.disableAllRedirections); 
 
  750  Stream_Read_INT32(s, response->redirectionFlags
 
  751                           .driveRedirectionDisabled); 
 
  753                    response->redirectionFlags
 
  754                        .printerRedirectionDisabled); 
 
  757      response->redirectionFlags.portRedirectionDisabled); 
 
  758  Stream_Read_INT32(s, response->redirectionFlags.reserved); 
 
  760      s, response->redirectionFlags
 
  761             .clipboardRedirectionDisabled); 
 
  764      response->redirectionFlags.pnpRedirectionDisabled); 
 
  766  const UINT32 MaxSizeValue = Stream_Get_UINT32(s);   
 
  767  const UINT32 MaxOffsetValue = Stream_Get_UINT32(s); 
 
  769  if (MaxSizeValue != response->responseDataLen)
 
  771    WLog_Print(log, WLOG_ERROR, 
"Unexpected size value: %" PRIu32 
", expected: %" PRIu32 
"",
 
  772               MaxSizeValue, response->responseDataLen);
 
  776  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, MaxSizeValue))
 
  779  if (MaxSizeValue >= 4)
 
  781    const UINT32 idleTimeout = Stream_Get_UINT32(s);
 
  782    WLog_Print(log, WLOG_DEBUG, 
"[IDLE_TIMEOUT] idleTimeout=%" PRIu32 
": TODO: unused",
 
  784    Stream_Seek(s, MaxSizeValue - 4);
 
  787    Stream_Seek(s, MaxSizeValue); 
 
  791WINPR_ATTR_FORMAT_ARG(3, 4)
 
  792static BOOL tsg_print(
char** buffer, 
size_t* len, WINPR_FORMAT_ARG const 
char* fmt, ...)
 
  796  if (!buffer || !len || !fmt)
 
  799  rc = vsnprintf(*buffer, *len, fmt, ap);
 
  801  if ((rc < 0) || ((
size_t)rc > *len))
 
  804  *buffer += (size_t)rc;
 
  808static BOOL tsg_packet_header_to_string(
char** buffer, 
size_t* length,
 
  809                                        const TSG_PACKET_HEADER* header)
 
  811  WINPR_ASSERT(buffer);
 
  812  WINPR_ASSERT(length);
 
  813  WINPR_ASSERT(header);
 
  815  return tsg_print(buffer, length,
 
  816                   "header { ComponentId=0x%04" PRIx16 
", PacketId=0x%04" PRIx16 
" }",
 
  817                   header->ComponentId, header->PacketId);
 
  820static BOOL tsg_type_capability_nap_to_string(
char** buffer, 
size_t* length,
 
  821                                              const TSG_CAPABILITY_NAP* cur)
 
  823  WINPR_ASSERT(buffer);
 
  824  WINPR_ASSERT(length);
 
  827  return tsg_print(buffer, length, 
"%s { capabilities=0x%08" PRIx32 
" }",
 
  828                   tsg_packet_id_to_string(TSG_CAPABILITY_TYPE_NAP), cur->capabilities);
 
  831static BOOL tsg_packet_capabilities_to_string(
char** buffer, 
size_t* length,
 
  832                                              const TSG_PACKET_CAPABILITIES* caps, UINT32 numCaps)
 
  834  WINPR_ASSERT(buffer);
 
  835  WINPR_ASSERT(length);
 
  838  if (!tsg_print(buffer, length, 
"capabilities { "))
 
  841  for (UINT32 x = 0; x < numCaps; x++)
 
  843    const TSG_PACKET_CAPABILITIES* cur = &caps[x];
 
  844    switch (cur->capabilityType)
 
  846      case TSG_CAPABILITY_TYPE_NAP:
 
  847        if (!tsg_type_capability_nap_to_string(buffer, length, &cur->tsgPacket.tsgCapNap))
 
  851        if (!tsg_print(buffer, length, 
"TSG_UNKNOWN_CAPABILITY"))
 
  856  return tsg_print(buffer, length, 
" }");
 
  859static BOOL tsg_packet_versioncaps_to_string(
char** buffer, 
size_t* length,
 
  860                                             const TSG_PACKET_VERSIONCAPS* caps)
 
  862  WINPR_ASSERT(buffer);
 
  863  WINPR_ASSERT(length);
 
  866  if (!tsg_print(buffer, length, 
"versioncaps { "))
 
  868  if (!tsg_packet_header_to_string(buffer, length, &caps->tsgHeader))
 
  871  if (!tsg_print(buffer, length, 
" "))
 
  874  if (caps->numCapabilities > 1)
 
  876    WLog_ERR(TAG, 
"TSG_PACKET_VERSIONCAPS::numCapabilities > 1 (%" PRIu32 
"), not supported!",
 
  877             caps->numCapabilities);
 
  881  if (!tsg_packet_capabilities_to_string(buffer, length, &caps->tsgCaps, caps->numCapabilities))
 
  884  if (!tsg_print(buffer, length,
 
  885                 " numCapabilities=0x%08" PRIx32 
", majorVersion=0x%04" PRIx16
 
  886                 ", minorVersion=0x%04" PRIx16 
", quarantineCapabilities=0x%04" PRIx16,
 
  887                 caps->numCapabilities, caps->majorVersion, caps->minorVersion,
 
  888                 caps->quarantineCapabilities))
 
  891  return tsg_print(buffer, length, 
" }");
 
  894static BOOL tsg_packet_quarconfigrequest_to_string(
char** buffer, 
size_t* length,
 
  895                                                   const TSG_PACKET_QUARCONFIGREQUEST* caps)
 
  897  WINPR_ASSERT(buffer);
 
  898  WINPR_ASSERT(length);
 
  901  if (!tsg_print(buffer, length, 
"quarconfigrequest { "))
 
  904  if (!tsg_print(buffer, length, 
" "))
 
  907  if (!tsg_print(buffer, length, 
" flags=0x%08" PRIx32, caps->flags))
 
  910  return tsg_print(buffer, length, 
" }");
 
  913static BOOL tsg_packet_quarrequest_to_string(
char** buffer, 
size_t* length,
 
  914                                             const TSG_PACKET_QUARREQUEST* caps)
 
  918  char* strdata = NULL;
 
  920  WINPR_ASSERT(buffer);
 
  921  WINPR_ASSERT(length);
 
  924  if (!tsg_print(buffer, length, 
"quarrequest { "))
 
  927  if (!tsg_print(buffer, length, 
" "))
 
  930  if (caps->nameLength > 0)
 
  932    if (caps->nameLength > INT_MAX)
 
  934    name = ConvertWCharNToUtf8Alloc(caps->machineName, caps->nameLength, NULL);
 
  939  strdata = winpr_BinToHexString(caps->data, caps->dataLen, TRUE);
 
  940  if (strdata || (caps->dataLen == 0))
 
  941    rc = tsg_print(buffer, length,
 
  942                   " flags=0x%08" PRIx32 
", machineName=%s [%" PRIu32 
"], data[%" PRIu32 
"]=%s",
 
  943                   caps->flags, name, caps->nameLength, caps->dataLen, strdata);
 
  949  return tsg_print(buffer, length, 
" }");
 
  952static const char* tsg_bool_to_string(BOOL val)
 
  959static const char* tsg_redirection_flags_to_string(
char* buffer, 
size_t size,
 
  960                                                   const TSG_REDIRECTION_FLAGS* flags)
 
  962  WINPR_ASSERT(buffer || (size == 0));
 
  967      "enableAllRedirections=%s,  disableAllRedirections=%s, driveRedirectionDisabled=%s, " 
  968      "printerRedirectionDisabled=%s, portRedirectionDisabled=%s, reserved=%s, " 
  969      "clipboardRedirectionDisabled=%s, pnpRedirectionDisabled=%s",
 
  970      tsg_bool_to_string(flags->enableAllRedirections),
 
  971      tsg_bool_to_string(flags->disableAllRedirections),
 
  972      tsg_bool_to_string(flags->driveRedirectionDisabled),
 
  973      tsg_bool_to_string(flags->printerRedirectionDisabled),
 
  974      tsg_bool_to_string(flags->portRedirectionDisabled), tsg_bool_to_string(flags->reserved),
 
  975      tsg_bool_to_string(flags->clipboardRedirectionDisabled),
 
  976      tsg_bool_to_string(flags->pnpRedirectionDisabled));
 
  980static BOOL tsg_packet_response_to_string(
char** buffer, 
size_t* length,
 
  981                                          const TSG_PACKET_RESPONSE* caps)
 
  984  char* strdata = NULL;
 
  985  char tbuffer[8192] = { 0 };
 
  987  WINPR_ASSERT(buffer);
 
  988  WINPR_ASSERT(length);
 
  991  if (!tsg_print(buffer, length, 
"response { "))
 
  994  if (!tsg_print(buffer, length, 
" "))
 
  997  strdata = winpr_BinToHexString(caps->responseData, caps->responseDataLen, TRUE);
 
  998  if (strdata || (caps->responseDataLen == 0))
 
 1001        " flags=0x%08" PRIx32 
", reserved=0x%08" PRIx32 
", responseData[%" PRIu32
 
 1002        "]=%s, redirectionFlags={ %s }",
 
 1003        caps->flags, caps->reserved, caps->responseDataLen, strdata,
 
 1004        tsg_redirection_flags_to_string(tbuffer, ARRAYSIZE(tbuffer), &caps->redirectionFlags));
 
 1009  return tsg_print(buffer, length, 
" }");
 
 1012static BOOL tsg_packet_quarenc_response_to_string(
char** buffer, 
size_t* length,
 
 1013                                                  const TSG_PACKET_QUARENC_RESPONSE* caps)
 
 1016  char* strdata = NULL;
 
 1017  RPC_CSTR uuid = NULL;
 
 1018  char tbuffer[8192] = { 0 };
 
 1019  size_t size = ARRAYSIZE(tbuffer);
 
 1020  char* ptbuffer = tbuffer;
 
 1022  WINPR_ASSERT(buffer);
 
 1023  WINPR_ASSERT(length);
 
 1026  if (!tsg_print(buffer, length, 
"quarenc_response { "))
 
 1029  if (!tsg_print(buffer, length, 
" "))
 
 1032  if (caps->certChainLen > 0)
 
 1034    if (caps->certChainLen > INT_MAX)
 
 1036    strdata = ConvertWCharNToUtf8Alloc(caps->certChainData, caps->certChainLen, NULL);
 
 1041  tsg_packet_versioncaps_to_string(&ptbuffer, &size, &caps->versionCaps);
 
 1042  UuidToStringA(&caps->nonce, &uuid);
 
 1043  if (strdata || (caps->certChainLen == 0))
 
 1045        tsg_print(buffer, length,
 
 1046                  " flags=0x%08" PRIx32 
", certChain[%" PRIu32 
"]=%s, nonce=%s, versionCaps=%s",
 
 1047                  caps->flags, caps->certChainLen, strdata, uuid, tbuffer);
 
 1049  RpcStringFreeA(&uuid);
 
 1053  return tsg_print(buffer, length, 
" }");
 
 1056static BOOL tsg_packet_message_response_to_string(
char** buffer, 
size_t* length,
 
 1057                                                  const TSG_PACKET_MSG_RESPONSE* caps)
 
 1059  WINPR_ASSERT(buffer);
 
 1060  WINPR_ASSERT(length);
 
 1063  if (!tsg_print(buffer, length, 
"msg_response { "))
 
 1066  if (!tsg_print(buffer, length,
 
 1067                 " msgID=0x%08" PRIx32 
", msgType=0x%08" PRIx32 
", isMsgPresent=%" PRId32,
 
 1068                 caps->msgID, caps->msgType, caps->isMsgPresent))
 
 1071  return tsg_print(buffer, length, 
" }");
 
 1074static BOOL tsg_packet_caps_response_to_string(
char** buffer, 
size_t* length,
 
 1075                                               const TSG_PACKET_CAPS_RESPONSE* caps)
 
 1077  WINPR_ASSERT(buffer);
 
 1078  WINPR_ASSERT(length);
 
 1081  if (!tsg_print(buffer, length, 
"caps_response { "))
 
 1084  if (!tsg_packet_quarenc_response_to_string(buffer, length, &caps->pktQuarEncResponse))
 
 1087  if (!tsg_packet_message_response_to_string(buffer, length, &caps->pktConsentMessage))
 
 1090  return tsg_print(buffer, length, 
" }");
 
 1093static BOOL tsg_packet_message_request_to_string(
char** buffer, 
size_t* length,
 
 1094                                                 const TSG_PACKET_MSG_REQUEST* caps)
 
 1096  WINPR_ASSERT(buffer);
 
 1097  WINPR_ASSERT(length);
 
 1100  if (!tsg_print(buffer, length, 
"caps_message_request { "))
 
 1103  if (!tsg_print(buffer, length, 
" maxMessagesPerBatch=%" PRIu32, caps->maxMessagesPerBatch))
 
 1106  return tsg_print(buffer, length, 
" }");
 
 1109static BOOL tsg_packet_auth_to_string(
char** buffer, 
size_t* length, 
const TSG_PACKET_AUTH* caps)
 
 1112  char* strdata = NULL;
 
 1113  WINPR_ASSERT(buffer);
 
 1114  WINPR_ASSERT(length);
 
 1117  if (!tsg_print(buffer, length, 
"caps_message_request { "))
 
 1120  if (!tsg_packet_versioncaps_to_string(buffer, length, &caps->tsgVersionCaps))
 
 1123  strdata = winpr_BinToHexString(caps->cookie, caps->cookieLen, TRUE);
 
 1124  if (strdata || (caps->cookieLen == 0))
 
 1125    rc = tsg_print(buffer, length, 
" cookie[%" PRIu32 
"]=%s", caps->cookieLen, strdata);
 
 1130  return tsg_print(buffer, length, 
" }");
 
 1133static BOOL tsg_packet_reauth_to_string(
char** buffer, 
size_t* length,
 
 1134                                        const TSG_PACKET_REAUTH* caps)
 
 1137  WINPR_ASSERT(buffer);
 
 1138  WINPR_ASSERT(length);
 
 1141  if (!tsg_print(buffer, length, 
"caps_message_request { "))
 
 1144  if (!tsg_print(buffer, length, 
" tunnelContext=0x%016" PRIx64 
", packetId=%s [0x%08" PRIx32 
"]",
 
 1145                 caps->tunnelContext, tsg_packet_id_to_string(caps->packetId), caps->packetId))
 
 1148  switch (caps->packetId)
 
 1150    case TSG_PACKET_TYPE_VERSIONCAPS:
 
 1151      rc = tsg_packet_versioncaps_to_string(buffer, length,
 
 1152                                            &caps->tsgInitialPacket.packetVersionCaps);
 
 1154    case TSG_PACKET_TYPE_AUTH:
 
 1155      rc = tsg_packet_auth_to_string(buffer, length, &caps->tsgInitialPacket.packetAuth);
 
 1158      rc = tsg_print(buffer, length, 
"TODO: Unhandled packet type %s [0x%08" PRIx32 
"]",
 
 1159                     tsg_packet_id_to_string(caps->packetId), caps->packetId);
 
 1166  return tsg_print(buffer, length, 
" }");
 
 1169static const char* tsg_packet_to_string(
const TSG_PACKET* packet)
 
 1172  static char sbuffer[8193] = { 0 };
 
 1173  char* buffer = sbuffer;
 
 1175  if (!tsg_print(&buffer, &len, 
"TSG_PACKET { packetId=%s [0x%08" PRIx32 
"], ",
 
 1176                 tsg_packet_id_to_string(packet->packetId), packet->packetId))
 
 1179  switch (packet->packetId)
 
 1181    case TSG_PACKET_TYPE_HEADER:
 
 1182      if (!tsg_packet_header_to_string(&buffer, &len, &packet->tsgPacket.packetHeader))
 
 1185    case TSG_PACKET_TYPE_VERSIONCAPS:
 
 1186      if (!tsg_packet_versioncaps_to_string(&buffer, &len,
 
 1187                                            &packet->tsgPacket.packetVersionCaps))
 
 1190    case TSG_PACKET_TYPE_QUARCONFIGREQUEST:
 
 1191      if (!tsg_packet_quarconfigrequest_to_string(&buffer, &len,
 
 1192                                                  &packet->tsgPacket.packetQuarConfigRequest))
 
 1195    case TSG_PACKET_TYPE_QUARREQUEST:
 
 1196      if (!tsg_packet_quarrequest_to_string(&buffer, &len,
 
 1197                                            &packet->tsgPacket.packetQuarRequest))
 
 1200    case TSG_PACKET_TYPE_RESPONSE:
 
 1201      if (!tsg_packet_response_to_string(&buffer, &len, &packet->tsgPacket.packetResponse))
 
 1204    case TSG_PACKET_TYPE_QUARENC_RESPONSE:
 
 1205      if (!tsg_packet_quarenc_response_to_string(&buffer, &len,
 
 1206                                                 &packet->tsgPacket.packetQuarEncResponse))
 
 1209    case TSG_PACKET_TYPE_CAPS_RESPONSE:
 
 1210      if (!tsg_packet_caps_response_to_string(&buffer, &len,
 
 1211                                              &packet->tsgPacket.packetCapsResponse))
 
 1214    case TSG_PACKET_TYPE_MSGREQUEST_PACKET:
 
 1215      if (!tsg_packet_message_request_to_string(&buffer, &len,
 
 1216                                                &packet->tsgPacket.packetMsgRequest))
 
 1219    case TSG_PACKET_TYPE_MESSAGE_PACKET:
 
 1220      if (!tsg_packet_message_response_to_string(&buffer, &len,
 
 1221                                                 &packet->tsgPacket.packetMsgResponse))
 
 1224    case TSG_PACKET_TYPE_AUTH:
 
 1225      if (!tsg_packet_auth_to_string(&buffer, &len, &packet->tsgPacket.packetAuth))
 
 1228    case TSG_PACKET_TYPE_REAUTH:
 
 1229      if (!tsg_packet_reauth_to_string(&buffer, &len, &packet->tsgPacket.packetReauth))
 
 1233      if (!tsg_print(&buffer, &len, 
"INVALID"))
 
 1238  if (!tsg_print(&buffer, &len, 
" }"))
 
 1245static BOOL tsg_stream_align(wLog* log, 
wStream* s, 
size_t align)
 
 1253  pos = Stream_GetPosition(s);
 
 1255  if ((pos % align) != 0)
 
 1256    offset = align - pos % align;
 
 1258  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, offset))
 
 1260  Stream_Seek(s, offset);
 
 1264static BIO_METHOD* BIO_s_tsg(
void);
 
 1301static int TsProxySendToServer(handle_t IDL_handle, 
const byte pRpcMessage[], UINT32 count,
 
 1302                               const UINT32* lengths)
 
 1307  const byte* buffer1 = NULL;
 
 1308  const byte* buffer2 = NULL;
 
 1309  const byte* buffer3 = NULL;
 
 1310  UINT32 buffer1Length = 0;
 
 1311  UINT32 buffer2Length = 0;
 
 1312  UINT32 buffer3Length = 0;
 
 1313  UINT32 numBuffers = 0;
 
 1314  UINT32 totalDataBytes = 0;
 
 1315  tsg = (rdpTsg*)IDL_handle;
 
 1316  buffer1Length = buffer2Length = buffer3Length = 0;
 
 1321    buffer1 = &pRpcMessage[0];
 
 1322    buffer1Length = lengths[0];
 
 1323    totalDataBytes += lengths[0] + 4;
 
 1329    buffer2 = &pRpcMessage[1];
 
 1330    buffer2Length = lengths[1];
 
 1331    totalDataBytes += lengths[1] + 4;
 
 1337    buffer3 = &pRpcMessage[2];
 
 1338    buffer3Length = lengths[2];
 
 1339    totalDataBytes += lengths[2] + 4;
 
 1342  length = 28ull + totalDataBytes;
 
 1343  if (length > INT_MAX)
 
 1345  s = Stream_New(NULL, length);
 
 1349    WLog_Print(tsg->log, WLOG_ERROR, 
"Stream_New failed!");
 
 1354  if (!TsProxyWriteTunnelContext(tsg->log, s, &tsg->ChannelContext))
 
 1356  Stream_Write_UINT32_BE(s, totalDataBytes);            
 
 1357  Stream_Write_UINT32_BE(s, numBuffers);                
 
 1359  if (buffer1Length > 0)
 
 1360    Stream_Write_UINT32_BE(s, buffer1Length); 
 
 1362  if (buffer2Length > 0)
 
 1363    Stream_Write_UINT32_BE(s, buffer2Length); 
 
 1365  if (buffer3Length > 0)
 
 1366    Stream_Write_UINT32_BE(s, buffer3Length); 
 
 1368  if (buffer1Length > 0)
 
 1369    Stream_Write(s, buffer1, buffer1Length); 
 
 1371  if (buffer2Length > 0)
 
 1372    Stream_Write(s, buffer2, buffer2Length); 
 
 1374  if (buffer3Length > 0)
 
 1375    Stream_Write(s, buffer3, buffer3Length); 
 
 1377  if (!rpc_client_write_call(tsg->rpc, s, TsProxySendToServerOpnum))
 
 1382  Stream_Free(s, TRUE);
 
 1397static BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg, 
const TSG_PACKET* tsgPacket)
 
 1405  if (!tsg || !tsg->rpc)
 
 1409  WLog_Print(tsg->log, WLOG_DEBUG, 
"%s", tsg_packet_to_string(tsgPacket));
 
 1410  s = Stream_New(NULL, 108);
 
 1415  switch (tsgPacket->packetId)
 
 1417    case TSG_PACKET_TYPE_VERSIONCAPS:
 
 1420      const TSG_PACKET_VERSIONCAPS* packetVersionCaps =
 
 1421          &tsgPacket->tsgPacket.packetVersionCaps;
 
 1423      Stream_Write_UINT32(s, tsgPacket->packetId); 
 
 1424      Stream_Write_UINT32(s, tsgPacket->packetId); 
 
 1425      if (!tsg_ndr_pointer_write(tsg->log, s, &index, 1)) 
 
 1428      if (!tsg_ndr_write_version_caps(tsg->log, s, &index, packetVersionCaps))
 
 1438      Stream_Write_UINT8(s, 0x8A);
 
 1439      Stream_Write_UINT8(s, 0xE3);
 
 1440      Stream_Write_UINT8(s, 0x13);
 
 1441      Stream_Write_UINT8(s, 0x71);
 
 1442      Stream_Write_UINT8(s, 0x02);
 
 1443      Stream_Write_UINT8(s, 0xF4);
 
 1444      Stream_Write_UINT8(s, 0x36);
 
 1445      Stream_Write_UINT8(s, 0x71);
 
 1446      Stream_Write_UINT32(s, 0x00040001); 
 
 1447      Stream_Write_UINT32(s, 0x00000001); 
 
 1449      Stream_Write_UINT8(s, 2);       
 
 1450      Stream_Write_UINT8(s, 0x40);    
 
 1451      Stream_Write_UINT16(s, 0x0028); 
 
 1453      Stream_Write(s, &TSGU_UUID, 
sizeof(
p_uuid_t));
 
 1454      Stream_Write_UINT32(s, TSGU_SYNTAX_IF_VERSION);
 
 1456      Stream_Write(s, &NDR_UUID, 
sizeof(
p_uuid_t));
 
 1457      Stream_Write_UINT32(s, NDR_SYNTAX_IF_VERSION);
 
 1458      opnum = TsProxyCreateTunnelOpnum;
 
 1462    case TSG_PACKET_TYPE_REAUTH:
 
 1464      const TSG_PACKET_REAUTH* packetReauth = &tsgPacket->tsgPacket.packetReauth;
 
 1466      Stream_Write_UINT32(s, tsgPacket->packetId);        
 
 1467      Stream_Write_UINT32(s, tsgPacket->packetId);        
 
 1468      if (!tsg_ndr_pointer_write(tsg->log, s, &index, 1)) 
 
 1470      if (!tsg_ndr_write_reauth(tsg->log, s, &index, packetReauth))
 
 1472      opnum = TsProxyCreateTunnelOpnum;
 
 1477      WLog_Print(tsg->log, WLOG_WARN, 
"unexpected packetId %s",
 
 1478                 tsg_packet_id_to_string(tsgPacket->packetId));
 
 1486    return rpc_client_write_call(rpc, s, opnum);
 
 1488  Stream_Free(s, TRUE);
 
 1492static BOOL tsg_ndr_read_consent_message(wLog* log, rdpContext* context, 
wStream* s, UINT32* index,
 
 1493                                         BOOL isMessagePresent)
 
 1495  TSG_PACKET_STRING_MESSAGE packetStringMessage = { 0 };
 
 1497  WINPR_ASSERT(context);
 
 1498  WINPR_ASSERT(index);
 
 1500  if (!TsProxyReadPacketSTringMessage(log, s, index, &packetStringMessage))
 
 1503  if (context->instance && isMessagePresent)
 
 1505    return IFCALLRESULT(TRUE, context->instance->PresentGatewayMessage, context->instance,
 
 1506                        TSG_ASYNC_MESSAGE_CONSENT_MESSAGE ? GATEWAY_MESSAGE_CONSENT
 
 1507                                                          : TSG_ASYNC_MESSAGE_SERVICE_MESSAGE,
 
 1508                        packetStringMessage.isDisplayMandatory != 0,
 
 1509                        packetStringMessage.isConsentMandatory != 0,
 
 1510                        packetStringMessage.msgBytes, packetStringMessage.msgBuffer);
 
 1519  if (!tsg_stream_align(log, s, 4))
 
 1523  if (!TsProxyReadTunnelContext(log, s, tunnelContext))
 
 1526  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
 
 1529  WINPR_ASSERT(tunnelId);
 
 1530  Stream_Read_UINT32(s, *tunnelId); 
 
 1532  INT32 ReturnValue = 0;
 
 1533  Stream_Read_INT32(s, ReturnValue); 
 
 1534  if (ReturnValue != NO_ERROR)
 
 1535    WLog_WARN(TAG, 
"ReturnValue=%s", NtStatus2Tag(ReturnValue));
 
 1539static BOOL tsg_ndr_read_TSG_PACKET_MSG_RESPONSE_header(wLog* log, 
wStream* s,
 
 1540                                                        TSG_PACKET_MSG_RESPONSE* pkt)
 
 1543  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
 
 1546  Stream_Read_UINT32(s, pkt->msgID);                 
 
 1547  Stream_Read_UINT32(s, pkt->msgType);               
 
 1548  Stream_Read_INT32(s, pkt->isMsgPresent);           
 
 1549  const uint32_t SwitchValue = Stream_Get_UINT32(s); 
 
 1551  if (pkt->msgType != SwitchValue)
 
 1554             "[MS-TSGU] 2.2.9.2.1.9 TSG_PACKET_MSG_RESPONSE MsgType[0x%08" PRIx32
 
 1555             "] != MessageSwitchValue [0x%08" PRIx32 
"]",
 
 1556             pkt->msgType, SwitchValue);
 
 1563static BOOL tsg_ndr_read_TSG_PACKET_MSG_RESPONSE(wLog* log, rdpContext* context, 
wStream* s,
 
 1564                                                 uint32_t* index, uint32_t MsgPtr,
 
 1565                                                 const TSG_PACKET_MSG_RESPONSE* pkg,
 
 1566                                                 uint64_t* reauthContext)
 
 1572    WLog_Print(log, WLOG_DEBUG,
 
 1573               "Message {0x%08" PRIx32 
"} [%s]::isMsgPresent=%" PRId32 
", MsgPtr=0x%08" PRIx32,
 
 1574               pkg->msgType, tsg_packet_id_to_string(pkg->msgType), pkg->isMsgPresent, MsgPtr);
 
 1578  switch (pkg->msgType)
 
 1580    case TSG_ASYNC_MESSAGE_CONSENT_MESSAGE:
 
 1581    case TSG_ASYNC_MESSAGE_SERVICE_MESSAGE:
 
 1582      return tsg_ndr_read_consent_message(log, context, s, index, pkg->isMsgPresent);
 
 1584    case TSG_ASYNC_MESSAGE_REAUTH:
 
 1586      if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
 
 1589      WINPR_ASSERT(reauthContext);
 
 1590      const uint64_t val = Stream_Get_UINT64(s); 
 
 1591      if (pkg->isMsgPresent != 0)
 
 1592        *reauthContext = val;
 
 1597      WLog_Print(log, WLOG_ERROR, 
"Unexpected Message Type: 0x%" PRIx32 
"", pkg->msgType);
 
 1602static BOOL tsg_ndr_read_caps_response(wLog* log, rdpContext* context, 
wStream* s, UINT32* index,
 
 1603                                       UINT32 PacketPtr, TSG_PACKET_CAPS_RESPONSE* caps,
 
 1605                                       uint64_t* reauthContext)
 
 1607  UINT32 PacketQuarResponsePtr = 0;
 
 1609  WINPR_ASSERT(context);
 
 1610  WINPR_ASSERT(index);
 
 1612  WINPR_ASSERT(reauthContext);
 
 1614  if (!tsg_ndr_pointer_read(log, s, index, &PacketQuarResponsePtr, TRUE))
 
 1617  if (!tsg_ndr_read_quarenc_response(log, s, index, &caps->pktQuarEncResponse))
 
 1622    TSG_PACKET_MSG_RESPONSE pkg = { 0 };
 
 1625    if (!tsg_ndr_read_TSG_PACKET_MSG_RESPONSE_header(log, s, &pkg))
 
 1628    if (!tsg_ndr_pointer_read(log, s, index, &MsgPtr, TRUE))
 
 1631    if (!tsg_ndr_read_quarenc_data(log, s, index, &caps->pktQuarEncResponse))
 
 1634    if (!tsg_ndr_read_TSG_PACKET_MSG_RESPONSE(log, context, s, index, MsgPtr, &pkg,
 
 1639  return tsg_ndr_read_tunnel_context(log, s, tunnelContext, tunnelId);
 
 1644static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, 
const RPC_PDU* pdu,
 
 1649  TSG_PACKET packet = { 0 };
 
 1650  UINT32 SwitchValue = 0;
 
 1651  rdpContext* context = NULL;
 
 1652  UINT32 PacketPtr = 0;
 
 1655  WINPR_ASSERT(tsg->rpc);
 
 1656  WINPR_ASSERT(tsg->rpc->transport);
 
 1658  context = transport_get_context(tsg->rpc->transport);
 
 1659  WINPR_ASSERT(context);
 
 1664  if (!tsg_ndr_pointer_read(tsg->log, pdu->s, &index, &PacketPtr, TRUE))
 
 1667  if (!Stream_CheckAndLogRequiredLengthWLog(tsg->log, pdu->s, 8))
 
 1669  Stream_Read_UINT32(pdu->s, packet.packetId); 
 
 1670  Stream_Read_UINT32(pdu->s, SwitchValue);     
 
 1672  WLog_Print(tsg->log, WLOG_DEBUG, 
"%s", tsg_packet_id_to_string(packet.packetId));
 
 1674  if ((packet.packetId == TSG_PACKET_TYPE_CAPS_RESPONSE) &&
 
 1675      (SwitchValue == TSG_PACKET_TYPE_CAPS_RESPONSE))
 
 1677    if (!tsg_ndr_read_caps_response(tsg->log, context, pdu->s, &index, PacketPtr,
 
 1678                                    &packet.tsgPacket.packetCapsResponse, tunnelContext,
 
 1679                                    tunnelId, &tsg->ReauthTunnelContext))
 
 1682  else if ((packet.packetId == TSG_PACKET_TYPE_QUARENC_RESPONSE) &&
 
 1683           (SwitchValue == TSG_PACKET_TYPE_QUARENC_RESPONSE))
 
 1685    UINT32 PacketQuarResponsePtr = 0;
 
 1687    if (!tsg_ndr_pointer_read(tsg->log, pdu->s, &index, &PacketQuarResponsePtr, TRUE))
 
 1690    if (!tsg_ndr_read_quarenc_response(tsg->log, pdu->s, &index,
 
 1691                                       &packet.tsgPacket.packetQuarEncResponse))
 
 1694    if (!tsg_ndr_read_quarenc_data(tsg->log, pdu->s, &index,
 
 1695                                   &packet.tsgPacket.packetQuarEncResponse))
 
 1698    if (!tsg_ndr_read_tunnel_context(tsg->log, pdu->s, tunnelContext, tunnelId))
 
 1703    WLog_Print(tsg->log, WLOG_ERROR,
 
 1704               "Unexpected PacketId: 0x%08" PRIX32 
", Expected TSG_PACKET_TYPE_CAPS_RESPONSE " 
 1705               "or TSG_PACKET_TYPE_QUARENC_RESPONSE",
 
 1710  const size_t rem = Stream_GetRemainingLength(pdu->s);
 
 1713    WLog_Print(tsg->log, WLOG_WARN, 
"Partially parsed %s, %" PRIuz 
" bytes remain",
 
 1714               tsg_packet_id_to_string(packet.packetId), rem);
 
 1732static BOOL TsProxyAuthorizeTunnelWriteRequest(rdpTsg* tsg, 
CONTEXT_HANDLE* tunnelContext)
 
 1740  if (!tsg || !tsg->rpc || !tunnelContext || !tsg->MachineName)
 
 1743  count = _wcslen(tsg->MachineName) + 1;
 
 1744  if (count > UINT32_MAX)
 
 1748  WLog_Print(tsg->log, WLOG_DEBUG, 
"TsProxyAuthorizeTunnelWriteRequest");
 
 1749  s = Stream_New(NULL, 1024 + count * 2);
 
 1754  if (!TsProxyWriteTunnelContext(tsg->log, s, tunnelContext))
 
 1756    Stream_Free(s, TRUE);
 
 1762  Stream_Write_UINT32(s, TSG_PACKET_TYPE_QUARREQUEST); 
 
 1763  Stream_Write_UINT32(s, TSG_PACKET_TYPE_QUARREQUEST); 
 
 1764  if (!tsg_ndr_pointer_write(tsg->log, s, &index, 1))  
 
 1766  Stream_Write_UINT32(s, 0x00000000);                  
 
 1767  if (!tsg_ndr_pointer_write(tsg->log, s, &index, 1))  
 
 1769  Stream_Write_UINT32(s, (UINT32)count);               
 
 1770  if (!tsg_ndr_pointer_write(tsg->log, s, &index, 1))  
 
 1772  Stream_Write_UINT32(s, 0);                           
 
 1774  if (!tsg_ndr_write_string(tsg->log, s, tsg->MachineName, count))
 
 1777  offset = Stream_GetPosition(s);
 
 1778  pad = rpc_offset_align(&offset, 4);
 
 1779  Stream_Zero(s, pad);
 
 1780  Stream_Write_UINT32(s, 0x00000000); 
 
 1781  Stream_SealLength(s);
 
 1782  return rpc_client_write_call(rpc, s, TsProxyAuthorizeTunnelOpnum);
 
 1784  Stream_Free(s, TRUE);
 
 1788static UINT32 tsg_redir_to_flags(
const TSG_REDIRECTION_FLAGS* redirect)
 
 1791  if (redirect->enableAllRedirections)
 
 1792    flags |= HTTP_TUNNEL_REDIR_ENABLE_ALL;
 
 1793  if (redirect->disableAllRedirections)
 
 1794    flags |= HTTP_TUNNEL_REDIR_DISABLE_ALL;
 
 1796  if (redirect->driveRedirectionDisabled)
 
 1797    flags |= HTTP_TUNNEL_REDIR_DISABLE_DRIVE;
 
 1798  if (redirect->printerRedirectionDisabled)
 
 1799    flags |= HTTP_TUNNEL_REDIR_DISABLE_PRINTER;
 
 1800  if (redirect->portRedirectionDisabled)
 
 1801    flags |= HTTP_TUNNEL_REDIR_DISABLE_PORT;
 
 1802  if (redirect->clipboardRedirectionDisabled)
 
 1803    flags |= HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD;
 
 1804  if (redirect->pnpRedirectionDisabled)
 
 1805    flags |= HTTP_TUNNEL_REDIR_DISABLE_PNP;
 
 1809static BOOL tsg_redirect_apply(rdpTsg* tsg, 
const TSG_REDIRECTION_FLAGS* redirect)
 
 1812  WINPR_ASSERT(redirect);
 
 1814  rdpTransport* transport = tsg->transport;
 
 1815  WINPR_ASSERT(transport);
 
 1817  rdpContext* context = transport_get_context(transport);
 
 1818  UINT32 redirFlags = tsg_redir_to_flags(redirect);
 
 1819  return utils_apply_gateway_policy(tsg->log, context, redirFlags, 
"TSG");
 
 1822static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, 
const RPC_PDU* pdu)
 
 1825  UINT32 SwitchValue = 0;
 
 1827  TSG_PACKET packet = { 0 };
 
 1828  UINT32 PacketPtr = 0;
 
 1829  UINT32 PacketResponsePtr = 0;
 
 1834  wLog* log = tsg->log;
 
 1837  if (!tsg_ndr_pointer_read(log, pdu->s, &index, &PacketPtr, TRUE))
 
 1840  if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, 8))
 
 1842  Stream_Read_UINT32(pdu->s, packet.packetId);  
 
 1843  Stream_Read_UINT32(pdu->s, SwitchValue);      
 
 1845  WLog_Print(log, WLOG_DEBUG, 
"%s", tsg_packet_id_to_string(packet.packetId));
 
 1847  if (packet.packetId == E_PROXY_NAP_ACCESSDENIED)
 
 1849    WLog_Print(log, WLOG_ERROR, 
"status: E_PROXY_NAP_ACCESSDENIED (0x%08X)",
 
 1850               E_PROXY_NAP_ACCESSDENIED);
 
 1851    WLog_Print(log, WLOG_ERROR,
 
 1852               "Ensure that the Gateway Connection Authorization Policy is correct");
 
 1856  if ((packet.packetId != TSG_PACKET_TYPE_RESPONSE) || (SwitchValue != TSG_PACKET_TYPE_RESPONSE))
 
 1858    WLog_Print(log, WLOG_ERROR,
 
 1859               "Unexpected PacketId: 0x%08" PRIX32 
", Expected TSG_PACKET_TYPE_RESPONSE",
 
 1864  if (!tsg_ndr_pointer_read(log, pdu->s, &index, &PacketResponsePtr, TRUE))
 
 1867  if (!tsg_ndr_read_packet_response(log, pdu->s, &index, &packet.tsgPacket.packetResponse))
 
 1872  if (packet.tsgPacket.packetResponse.flags & TSG_PACKET_TYPE_QUARREQUEST)
 
 1873    rc = tsg_redirect_apply(tsg, &packet.tsgPacket.packetResponse.redirectionFlags);
 
 1889static BOOL TsProxyMakeTunnelCallWriteRequest(rdpTsg* tsg, 
CONTEXT_HANDLE* tunnelContext,
 
 1895  if (!tsg || !tsg->rpc || !tunnelContext)
 
 1899  WLog_Print(tsg->log, WLOG_DEBUG, 
"TsProxyMakeTunnelCallWriteRequest");
 
 1900  s = Stream_New(NULL, 40);
 
 1907  if (!TsProxyWriteTunnelContext(tsg->log, s, tunnelContext))
 
 1909  Stream_Write_UINT32(s, procId);                     
 
 1911  Stream_Write_UINT32(s, TSG_PACKET_TYPE_MSGREQUEST_PACKET); 
 
 1912  Stream_Write_UINT32(s, TSG_PACKET_TYPE_MSGREQUEST_PACKET); 
 
 1913  if (!tsg_ndr_pointer_write(tsg->log, s, &index, 1))        
 
 1915  Stream_Write_UINT32(s, 0x00000001);                        
 
 1916  return rpc_client_write_call(rpc, s, TsProxyMakeTunnelCallOpnum);
 
 1918  Stream_Free(s, TRUE);
 
 1922static BOOL TsProxyReadPacketSTringMessage(wLog* log, 
wStream* s, uint32_t* index,
 
 1923                                           TSG_PACKET_STRING_MESSAGE* msg)
 
 1929  const TSG_PACKET_STRING_MESSAGE empty = { 0 };
 
 1932  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
 
 1935  Stream_Read_INT32(s, msg->isDisplayMandatory); 
 
 1936  Stream_Read_INT32(s, msg->isConsentMandatory); 
 
 1937  Stream_Read_UINT32(s, msg->msgBytes);          
 
 1939  if (!tsg_ndr_pointer_read(log, s, index, &MsgPtr, msg->msgBytes != 0))
 
 1942  if (msg->msgBytes > TSG_MESSAGING_MAX_MESSAGE_LENGTH)
 
 1944    WLog_Print(log, WLOG_ERROR, 
"Out of Spec Message Length %" PRIu32 
"", msg->msgBytes);
 
 1948  if (msg->msgBytes == 0)
 
 1950    WLog_Print(log, WLOG_DEBUG, 
"Empty message, skipping string read");
 
 1954  return tsg_ndr_read_string(log, s, &msg->msgBuffer, msg->msgBytes);
 
 1957static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, 
const RPC_PDU* pdu)
 
 1961  TSG_PACKET packet = { 0 };
 
 1962  rdpContext* context = NULL;
 
 1963  TSG_PACKET_MSG_RESPONSE packetMsgResponse = { 0 };
 
 1964  UINT32 PacketPtr = 0;
 
 1965  UINT32 PacketMsgResponsePtr = 0;
 
 1968  WINPR_ASSERT(tsg->rpc);
 
 1970  context = transport_get_context(tsg->rpc->transport);
 
 1971  WINPR_ASSERT(context);
 
 1978  if (!Stream_CheckAndLogRequiredLengthWLog(tsg->log, pdu->s, 28))
 
 1981  if (!tsg_ndr_pointer_read(tsg->log, pdu->s, &index, &PacketPtr, TRUE))
 
 1984  Stream_Read_UINT32(pdu->s, packet.packetId); 
 
 1985  const uint32_t SwitchValue = Stream_Get_UINT32(pdu->s); 
 
 1987  WLog_Print(tsg->log, WLOG_DEBUG, 
"%s", tsg_packet_id_to_string(packet.packetId));
 
 1989  if ((packet.packetId != TSG_PACKET_TYPE_MESSAGE_PACKET) || (packet.packetId != SwitchValue))
 
 1991    WLog_Print(tsg->log, WLOG_ERROR,
 
 1992               "Unexpected PacketId: 0x%08" PRIX32 
", Expected TSG_PACKET_TYPE_MESSAGE_PACKET",
 
 1997  if (!tsg_ndr_pointer_read(tsg->log, pdu->s, &index, &PacketMsgResponsePtr, TRUE))
 
 2000  if (!tsg_ndr_read_TSG_PACKET_MSG_RESPONSE_header(tsg->log, pdu->s, &packetMsgResponse))
 
 2003  UINT32 MessagePtr = 0;
 
 2004  if (!tsg_ndr_pointer_read(tsg->log, pdu->s, &index, &MessagePtr, TRUE))
 
 2007  if (!tsg_ndr_read_TSG_PACKET_MSG_RESPONSE(tsg->log, context, pdu->s, &index, MessagePtr,
 
 2008                                            &packetMsgResponse, &tsg->ReauthTunnelContext))
 
 2027static BOOL TsProxyCreateChannelWriteRequest(rdpTsg* tsg, 
CONTEXT_HANDLE* tunnelContext)
 
 2030  WINPR_ASSERT(tunnelContext);
 
 2032  WLog_Print(tsg->log, WLOG_DEBUG, 
"TsProxyCreateChannelWriteRequest");
 
 2034  if (!tsg->rpc || !tsg->Hostname)
 
 2037  rdpRpc* rpc = tsg->rpc;
 
 2038  const size_t count = _wcslen(tsg->Hostname) + 1;
 
 2039  if (count > UINT32_MAX)
 
 2042  wStream* s = Stream_New(NULL, 60 + count * 2);
 
 2047  if (!TsProxyWriteTunnelContext(tsg->log, s, tunnelContext))
 
 2052  if (!tsg_ndr_pointer_write(tsg->log, s, &index, 1))
 
 2054  Stream_Write_UINT32(s, 0x00000001); 
 
 2055  if (!tsg_ndr_pointer_write(tsg->log, s, &index, 0))
 
 2057  Stream_Write_UINT16(s, 0x0000);     
 
 2058  Stream_Write_UINT16(s, 0x0000);     
 
 2060  Stream_Write_UINT16(s, 0x0003);                     
 
 2061  Stream_Write_UINT16(s, tsg->Port);                  
 
 2062  Stream_Write_UINT32(s, 0x00000001);                 
 
 2063  if (!tsg_ndr_pointer_write(tsg->log, s, &index, 1))
 
 2065  if (!tsg_ndr_write_string(tsg->log, s, tsg->Hostname, (UINT32)count))
 
 2067  return rpc_client_write_call(rpc, s, TsProxyCreateChannelOpnum);
 
 2070  Stream_Free(s, TRUE);
 
 2074static BOOL TsProxyCreateChannelReadResponse(wLog* log, 
const RPC_PDU* pdu,
 
 2081  WINPR_ASSERT(channelId);
 
 2083  WLog_Print(log, WLOG_DEBUG, 
"TsProxyCreateChannelReadResponse");
 
 2085  if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, 28))
 
 2089  if (!TsProxyReadTunnelContext(log, pdu->s, channelContext))
 
 2091  if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, pdu->s, 2, 
sizeof(UINT32)))
 
 2093  Stream_Read_UINT32(pdu->s, *channelId);                  
 
 2094  Stream_Seek_UINT32(pdu->s);                              
 
 2106static BOOL TsProxyCloseChannelWriteRequest(rdpTsg* tsg, 
CONTEXT_HANDLE* context)
 
 2109  WINPR_ASSERT(context);
 
 2111  WLog_Print(tsg->log, WLOG_DEBUG, 
"TsProxyCloseChannelWriteRequest");
 
 2113  rdpRpc* rpc = tsg->rpc;
 
 2116  wStream* s = Stream_New(NULL, 20);
 
 2122  if (!TsProxyWriteTunnelContext(tsg->log, s, context))
 
 2124  return rpc_client_write_call(rpc, s, TsProxyCloseChannelOpnum);
 
 2126  Stream_Free(s, TRUE);
 
 2133  WLog_Print(log, WLOG_DEBUG, 
"TsProxyCloseChannelReadResponse");
 
 2138  if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, 24))
 
 2142  if (!TsProxyReadTunnelContext(log, pdu->s, context))
 
 2146    const size_t len = 
sizeof(UINT32);
 
 2147    if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, len))
 
 2149    Stream_Seek(pdu->s, len); 
 
 2162static BOOL TsProxyCloseTunnelWriteRequest(rdpTsg* tsg, 
const CONTEXT_HANDLE* context)
 
 2165  WINPR_ASSERT(context);
 
 2167  WLog_Print(tsg->log, WLOG_DEBUG, 
"TsProxyCloseTunnelWriteRequest");
 
 2169  rdpRpc* rpc = tsg->rpc;
 
 2172  wStream* s = Stream_New(NULL, 20);
 
 2178  if (!TsProxyWriteTunnelContext(tsg->log, s, context))
 
 2180  return rpc_client_write_call(rpc, s, TsProxyCloseTunnelOpnum);
 
 2182  Stream_Free(s, TRUE);
 
 2192  WINPR_ASSERT(context);
 
 2194  WLog_Print(log, WLOG_DEBUG, 
"TsProxyCloseTunnelReadResponse");
 
 2196  if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, 24))
 
 2200  if (!TsProxyReadTunnelContext(log, pdu->s, context))
 
 2203    const size_t len = 
sizeof(UINT32);
 
 2204    if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, len))
 
 2206    Stream_Seek(pdu->s, len); 
 
 2221static BOOL TsProxySetupReceivePipeWriteRequest(rdpTsg* tsg, 
const CONTEXT_HANDLE* channelContext)
 
 2225  WLog_Print(tsg->log, WLOG_DEBUG, 
"TsProxySetupReceivePipeWriteRequest");
 
 2228  WINPR_ASSERT(tsg->rpc);
 
 2230  if (!channelContext)
 
 2234  s = Stream_New(NULL, 20);
 
 2240  if (!TsProxyWriteTunnelContext(tsg->log, s, channelContext))
 
 2242  return rpc_client_write_call(rpc, s, TsProxySetupReceivePipeOpnum);
 
 2244  Stream_Free(s, TRUE);
 
 2248static BOOL tsg_transition_to_state(rdpTsg* tsg, TSG_STATE state)
 
 2251  const char* oldState = tsg_state_to_string(tsg->state);
 
 2252  const char* newState = tsg_state_to_string(state);
 
 2254  WLog_Print(tsg->log, WLOG_DEBUG, 
"%s -> %s", oldState, newState);
 
 2255  return tsg_set_state(tsg, state);
 
 2258static BOOL tsg_initialize_version_caps(TSG_PACKET_VERSIONCAPS* packetVersionCaps)
 
 2260  WINPR_ASSERT(packetVersionCaps);
 
 2262  packetVersionCaps->tsgHeader.ComponentId = TS_GATEWAY_TRANSPORT;
 
 2263  packetVersionCaps->tsgHeader.PacketId = TSG_PACKET_TYPE_VERSIONCAPS;
 
 2264  packetVersionCaps->numCapabilities = 1;
 
 2265  packetVersionCaps->majorVersion = 1;
 
 2266  packetVersionCaps->minorVersion = 1;
 
 2267  packetVersionCaps->quarantineCapabilities = 0;
 
 2268  packetVersionCaps->tsgCaps.capabilityType = TSG_CAPABILITY_TYPE_NAP;
 
 2278  packetVersionCaps->tsgCaps.tsgPacket.tsgCapNap.capabilities =
 
 2279      TSG_NAP_CAPABILITY_QUAR_SOH | TSG_NAP_CAPABILITY_IDLE_TIMEOUT |
 
 2280      TSG_MESSAGING_CAP_CONSENT_SIGN | TSG_MESSAGING_CAP_SERVICE_MSG | TSG_MESSAGING_CAP_REAUTH;
 
 2284BOOL tsg_proxy_begin(rdpTsg* tsg)
 
 2286  TSG_PACKET tsgPacket = { 0 };
 
 2290  tsgPacket.packetId = TSG_PACKET_TYPE_VERSIONCAPS;
 
 2291  if (!tsg_initialize_version_caps(&tsgPacket.tsgPacket.packetVersionCaps) ||
 
 2292      !TsProxyCreateTunnelWriteRequest(tsg, &tsgPacket))
 
 2294    WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCreateTunnel failure");
 
 2295    tsg_transition_to_state(tsg, TSG_STATE_FINAL);
 
 2299  return tsg_transition_to_state(tsg, TSG_STATE_INITIAL);
 
 2302static BOOL tsg_proxy_reauth(rdpTsg* tsg)
 
 2304  TSG_PACKET tsgPacket = { 0 };
 
 2308  tsg->reauthSequence = TRUE;
 
 2309  TSG_PACKET_REAUTH* packetReauth = &tsgPacket.tsgPacket.packetReauth;
 
 2311  tsgPacket.packetId = TSG_PACKET_TYPE_REAUTH;
 
 2312  packetReauth->tunnelContext = tsg->ReauthTunnelContext;
 
 2313  packetReauth->packetId = TSG_PACKET_TYPE_VERSIONCAPS;
 
 2315  if (!tsg_initialize_version_caps(&packetReauth->tsgInitialPacket.packetVersionCaps))
 
 2318  if (!TsProxyCreateTunnelWriteRequest(tsg, &tsgPacket))
 
 2320    WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCreateTunnel failure");
 
 2321    tsg_transition_to_state(tsg, TSG_STATE_FINAL);
 
 2325  if (!TsProxyMakeTunnelCallWriteRequest(tsg, &tsg->TunnelContext,
 
 2326                                         TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST))
 
 2328    WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyMakeTunnelCall failure");
 
 2329    tsg_transition_to_state(tsg, TSG_STATE_FINAL);
 
 2333  return tsg_transition_to_state(tsg, TSG_STATE_INITIAL);
 
 2336BOOL tsg_recv_pdu(rdpTsg* tsg, 
const RPC_PDU* pdu)
 
 2344  WINPR_ASSERT(tsg->rpc);
 
 2348  if (!(pdu->Flags & RPC_PDU_FLAG_STUB))
 
 2350    const size_t len = 24;
 
 2351    if (!Stream_CheckAndLogRequiredLengthWLog(tsg->log, pdu->s, len))
 
 2353    Stream_Seek(pdu->s, len);
 
 2358    case TSG_STATE_INITIAL:
 
 2361      TunnelContext = (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext;
 
 2363      if (!TsProxyCreateTunnelReadResponse(tsg, pdu, TunnelContext, &tsg->TunnelId))
 
 2365        WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCreateTunnelReadResponse failure");
 
 2369      if (!tsg_transition_to_state(tsg, TSG_STATE_CONNECTED))
 
 2372      if (!TsProxyAuthorizeTunnelWriteRequest(tsg, TunnelContext))
 
 2374        WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyAuthorizeTunnel failure");
 
 2382    case TSG_STATE_CONNECTED:
 
 2385          (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext;
 
 2387      if (!TsProxyAuthorizeTunnelReadResponse(tsg, pdu))
 
 2389        WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyAuthorizeTunnelReadResponse failure");
 
 2393      if (!tsg_transition_to_state(tsg, TSG_STATE_AUTHORIZED))
 
 2396      if (!tsg->reauthSequence)
 
 2398        if (!TsProxyMakeTunnelCallWriteRequest(tsg, TunnelContext,
 
 2399                                               TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST))
 
 2401          WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyMakeTunnelCall failure");
 
 2406      if (!TsProxyCreateChannelWriteRequest(tsg, TunnelContext))
 
 2408        WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCreateChannel failure");
 
 2416    case TSG_STATE_AUTHORIZED:
 
 2417      call = rpc_client_call_find_by_id(rpc->client, pdu->CallId);
 
 2422      if (call->OpNum == TsProxyMakeTunnelCallOpnum)
 
 2424        if (!TsProxyMakeTunnelCallReadResponse(tsg, pdu))
 
 2426          WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyMakeTunnelCallReadResponse failure");
 
 2432      else if (call->OpNum == TsProxyCreateChannelOpnum)
 
 2436        if (!TsProxyCreateChannelReadResponse(tsg->log, pdu, &ChannelContext,
 
 2439          WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCreateChannelReadResponse failure");
 
 2443        if (!tsg->reauthSequence)
 
 2444          CopyMemory(&tsg->ChannelContext, &ChannelContext, 
sizeof(
CONTEXT_HANDLE));
 
 2446          CopyMemory(&tsg->NewChannelContext, &ChannelContext, 
sizeof(
CONTEXT_HANDLE));
 
 2448        if (!tsg_transition_to_state(tsg, TSG_STATE_CHANNEL_CREATED))
 
 2451        if (!tsg->reauthSequence)
 
 2453          if (!TsProxySetupReceivePipeWriteRequest(tsg, &tsg->ChannelContext))
 
 2455            WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxySetupReceivePipe failure");
 
 2461          if (!TsProxyCloseChannelWriteRequest(tsg, &tsg->NewChannelContext))
 
 2463            WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCloseChannelWriteRequest failure");
 
 2467          if (!TsProxyCloseTunnelWriteRequest(tsg, &tsg->NewTunnelContext))
 
 2469            WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCloseTunnelWriteRequest failure");
 
 2474        rc = tsg_transition_to_state(tsg, TSG_STATE_PIPE_CREATED);
 
 2475        tsg->reauthSequence = FALSE;
 
 2479        WLog_Print(tsg->log, WLOG_ERROR,
 
 2480                   "TSG_STATE_AUTHORIZED unexpected OpNum: %" PRIu32 
"\n", call->OpNum);
 
 2485    case TSG_STATE_CHANNEL_CREATED:
 
 2488    case TSG_STATE_PIPE_CREATED:
 
 2489      call = rpc_client_call_find_by_id(rpc->client, pdu->CallId);
 
 2494      if (call->OpNum == TsProxyMakeTunnelCallOpnum)
 
 2496        if (!TsProxyMakeTunnelCallReadResponse(tsg, pdu))
 
 2498          WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyMakeTunnelCallReadResponse failure");
 
 2504        if (tsg->ReauthTunnelContext)
 
 2505          rc = tsg_proxy_reauth(tsg);
 
 2507      else if (call->OpNum == TsProxyCloseChannelOpnum)
 
 2511        if (!TsProxyCloseChannelReadResponse(tsg->log, pdu, &ChannelContext))
 
 2513          WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCloseChannelReadResponse failure");
 
 2519      else if (call->OpNum == TsProxyCloseTunnelOpnum)
 
 2523        if (!TsProxyCloseTunnelReadResponse(tsg->log, pdu, &TunnelContext))
 
 2525          WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCloseTunnelReadResponse failure");
 
 2534    case TSG_STATE_TUNNEL_CLOSE_PENDING:
 
 2538      if (!TsProxyCloseChannelReadResponse(tsg->log, pdu, &ChannelContext))
 
 2540        WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCloseChannelReadResponse failure");
 
 2544      if (!tsg_transition_to_state(tsg, TSG_STATE_CHANNEL_CLOSE_PENDING))
 
 2547      if (!TsProxyCloseChannelWriteRequest(tsg, NULL))
 
 2549        WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCloseChannelWriteRequest failure");
 
 2553      if (!TsProxyMakeTunnelCallWriteRequest(tsg, &tsg->TunnelContext,
 
 2554                                             TSG_TUNNEL_CANCEL_ASYNC_MSG_REQUEST))
 
 2556        WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyMakeTunnelCall failure");
 
 2564    case TSG_STATE_CHANNEL_CLOSE_PENDING:
 
 2568      if (!TsProxyCloseTunnelReadResponse(tsg->log, pdu, &TunnelContext))
 
 2570        WLog_Print(tsg->log, WLOG_ERROR, 
"TsProxyCloseTunnelReadResponse failure");
 
 2574      rc = tsg_transition_to_state(tsg, TSG_STATE_FINAL);
 
 2578    case TSG_STATE_FINAL:
 
 2587BOOL tsg_check_event_handles(rdpTsg* tsg)
 
 2590  if (rpc_client_in_channel_recv(tsg->rpc) < 0)
 
 2593  if (rpc_client_out_channel_recv(tsg->rpc) < 0)
 
 2599DWORD tsg_get_event_handles(rdpTsg* tsg, HANDLE* events, DWORD count)
 
 2602  rdpRpc* rpc = tsg->rpc;
 
 2605  if (events && (nCount < count))
 
 2607    events[nCount] = rpc->client->PipeEvent;
 
 2613  if (connection->DefaultInChannel && connection->DefaultInChannel->common.tls)
 
 2615    if (events && (nCount < count))
 
 2617      BIO_get_event(connection->DefaultInChannel->common.tls->bio, &events[nCount]);
 
 2624  if (connection->NonDefaultInChannel && connection->NonDefaultInChannel->common.tls)
 
 2626    if (events && (nCount < count))
 
 2628      BIO_get_event(connection->NonDefaultInChannel->common.tls->bio, &events[nCount]);
 
 2635  if (connection->DefaultOutChannel && connection->DefaultOutChannel->common.tls)
 
 2637    if (events && (nCount < count))
 
 2639      BIO_get_event(connection->DefaultOutChannel->common.tls->bio, &events[nCount]);
 
 2646  if (connection->NonDefaultOutChannel && connection->NonDefaultOutChannel->common.tls)
 
 2648    if (events && (nCount < count))
 
 2650      BIO_get_event(connection->NonDefaultOutChannel->common.tls->bio, &events[nCount]);
 
 2660static BOOL tsg_set_hostname(rdpTsg* tsg, 
const char* hostname)
 
 2663  free(tsg->Hostname);
 
 2664  tsg->Hostname = ConvertUtf8ToWCharAlloc(hostname, NULL);
 
 2665  return tsg->Hostname != NULL;
 
 2668static BOOL tsg_set_machine_name(rdpTsg* tsg, 
const char* machineName)
 
 2671  free(tsg->MachineName);
 
 2672  tsg->MachineName = ConvertUtf8ToWCharAlloc(machineName, NULL);
 
 2673  return tsg->MachineName != NULL;
 
 2676BOOL tsg_connect(rdpTsg* tsg, 
const char* hostname, UINT16 port, DWORD timeout)
 
 2678  UINT64 looptimeout = timeout * 1000ULL;
 
 2680  HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
 
 2684  rdpRpc* rpc = tsg->rpc;
 
 2687  rdpTransport* transport = rpc->transport;
 
 2688  rdpContext* context = transport_get_context(transport);
 
 2689  WINPR_ASSERT(context);
 
 2691  rdpSettings* settings = context->settings;
 
 2693  freerdp_set_last_error(context, ERROR_SUCCESS);
 
 2696  tsg->transport = transport;
 
 2698  if (!settings->GatewayPort)
 
 2699    settings->GatewayPort = 443;
 
 2701  if (!tsg_set_hostname(tsg, hostname))
 
 2704  if (!tsg_set_machine_name(tsg, settings->ComputerName))
 
 2707  if (!rpc_connect(rpc, timeout))
 
 2709    WLog_Print(tsg->log, WLOG_ERROR, 
"rpc_connect error!");
 
 2713  nCount = tsg_get_event_handles(tsg, events, ARRAYSIZE(events));
 
 2718  while (tsg->state != TSG_STATE_PIPE_CREATED)
 
 2720    const DWORD polltimeout = 250;
 
 2721    DWORD status = WaitForMultipleObjects(nCount, events, FALSE, polltimeout);
 
 2722    if (status == WAIT_TIMEOUT)
 
 2726        if (looptimeout < polltimeout)
 
 2728        looptimeout -= polltimeout;
 
 2732      looptimeout = timeout * 1000ULL;
 
 2734    if (!tsg_check_event_handles(tsg))
 
 2736      WLog_Print(tsg->log, WLOG_ERROR, 
"tsg_check failure");
 
 2737      transport_set_layer(transport, TRANSPORT_LAYER_CLOSED);
 
 2742  WLog_Print(tsg->log, WLOG_INFO, 
"TS Gateway Connection Success");
 
 2743  tsg->bio = BIO_new(BIO_s_tsg());
 
 2748  BIO_set_data(tsg->bio, (
void*)tsg);
 
 2752BOOL tsg_disconnect(rdpTsg* tsg)
 
 2776  if (tsg->state != TSG_STATE_TUNNEL_CLOSE_PENDING)
 
 2778    if (!TsProxyCloseChannelWriteRequest(tsg, &tsg->ChannelContext))
 
 2781    return tsg_transition_to_state(tsg, TSG_STATE_CHANNEL_CLOSE_PENDING);
 
 2797static int tsg_read(rdpTsg* tsg, BYTE* data, 
size_t length)
 
 2807  if (transport_get_layer(rpc->transport) == TRANSPORT_LAYER_CLOSED)
 
 2809    WLog_Print(tsg->log, WLOG_ERROR, 
"tsg_read error: connection lost");
 
 2815    status = rpc_client_receive_pipe_read(rpc->client, data, length);
 
 2820    if (!status && !transport_get_blocking(rpc->transport))
 
 2823    if (transport_get_layer(rpc->transport) == TRANSPORT_LAYER_CLOSED)
 
 2825      WLog_Print(tsg->log, WLOG_ERROR, 
"tsg_read error: connection lost");
 
 2832    if (transport_get_blocking(rpc->transport))
 
 2834      while (WaitForSingleObject(rpc->client->PipeEvent, 0) != WAIT_OBJECT_0)
 
 2836        if (!tsg_check_event_handles(tsg))
 
 2839        (void)WaitForSingleObject(rpc->client->PipeEvent, 100);
 
 2842  } 
while (transport_get_blocking(rpc->transport));
 
 2847static int tsg_write(rdpTsg* tsg, 
const BYTE* data, UINT32 length)
 
 2851  if (!tsg || !data || !tsg->rpc || !tsg->rpc->transport)
 
 2854  if (transport_get_layer(tsg->rpc->transport) == TRANSPORT_LAYER_CLOSED)
 
 2856    WLog_Print(tsg->log, WLOG_ERROR, 
"error, connection lost");
 
 2860  status = TsProxySendToServer((handle_t)tsg, data, 1, &length);
 
 2868rdpTsg* tsg_new(rdpTransport* transport)
 
 2870  rdpTsg* tsg = (rdpTsg*)calloc(1, 
sizeof(rdpTsg));
 
 2874  tsg->log = WLog_Get(TAG);
 
 2875  tsg->transport = transport;
 
 2876  tsg->rpc = rpc_new(tsg->transport);
 
 2887void tsg_free(rdpTsg* tsg)
 
 2892    free(tsg->Hostname);
 
 2893    free(tsg->MachineName);
 
 2898static int transport_bio_tsg_write(BIO* bio, 
const char* buf, 
int num)
 
 2901  rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio);
 
 2902  BIO_clear_flags(bio, BIO_FLAGS_WRITE);
 
 2906  status = tsg_write(tsg, (
const BYTE*)buf, (UINT32)num);
 
 2910    BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
 2913  else if (status == 0)
 
 2915    BIO_set_flags(bio, BIO_FLAGS_WRITE);
 
 2916    WSASetLastError(WSAEWOULDBLOCK);
 
 2920    BIO_set_flags(bio, BIO_FLAGS_WRITE);
 
 2923  return status >= 0 ? status : -1;
 
 2926static int transport_bio_tsg_read(BIO* bio, 
char* buf, 
int size)
 
 2929  rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio);
 
 2931  if (!tsg || (size < 0))
 
 2933    BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
 2937  BIO_clear_flags(bio, BIO_FLAGS_READ);
 
 2938  status = tsg_read(tsg, (BYTE*)buf, (
size_t)size);
 
 2942    BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
 2945  else if (status == 0)
 
 2947    BIO_set_flags(bio, BIO_FLAGS_READ);
 
 2948    WSASetLastError(WSAEWOULDBLOCK);
 
 2952    BIO_set_flags(bio, BIO_FLAGS_READ);
 
 2955  return status > 0 ? status : -1;
 
 2958static int transport_bio_tsg_puts(BIO* bio, 
const char* str)
 
 2966static int transport_bio_tsg_gets(BIO* bio, 
char* str, 
int size)
 
 2974static long transport_bio_tsg_ctrl(BIO* bio, 
int cmd, 
long arg1, 
void* arg2)
 
 2977  rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio);
 
 2979  RpcInChannel* inChannel = connection->DefaultInChannel;
 
 2984    case BIO_CTRL_FLUSH:
 
 2985      (void)BIO_flush(inChannel->common.tls->bio);
 
 2986      (void)BIO_flush(outChannel->common.tls->bio);
 
 2990    case BIO_C_GET_EVENT:
 
 2993        *((HANDLE*)arg2) = tsg->rpc->client->PipeEvent;
 
 2999    case BIO_C_SET_NONBLOCK:
 
 3003    case BIO_C_READ_BLOCKED:
 
 3005      BIO* cbio = outChannel->common.bio;
 
 3006      status = BIO_read_blocked(cbio);
 
 3010    case BIO_C_WRITE_BLOCKED:
 
 3012      BIO* cbio = inChannel->common.bio;
 
 3013      status = BIO_write_blocked(cbio);
 
 3017    case BIO_C_WAIT_READ:
 
 3019      int timeout = (int)arg1;
 
 3020      BIO* cbio = outChannel->common.bio;
 
 3022      if (BIO_read_blocked(cbio))
 
 3023        return BIO_wait_read(cbio, timeout);
 
 3024      else if (BIO_write_blocked(cbio))
 
 3025        return BIO_wait_write(cbio, timeout);
 
 3031    case BIO_C_WAIT_WRITE:
 
 3033      int timeout = (int)arg1;
 
 3034      BIO* cbio = inChannel->common.bio;
 
 3036      if (BIO_write_blocked(cbio))
 
 3037        status = BIO_wait_write(cbio, timeout);
 
 3038      else if (BIO_read_blocked(cbio))
 
 3039        status = BIO_wait_read(cbio, timeout);
 
 3044#if OPENSSL_VERSION_NUMBER >= 0x30000000L 
 3045    case BIO_CTRL_GET_KTLS_SEND:
 
 3048    case BIO_CTRL_GET_KTLS_RECV:
 
 3059static int transport_bio_tsg_new(BIO* bio)
 
 3062  BIO_set_init(bio, 1);
 
 3063  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
 3067static int transport_bio_tsg_free(BIO* bio)
 
 3074BIO_METHOD* BIO_s_tsg(
void)
 
 3076  static BIO_METHOD* bio_methods = NULL;
 
 3078  if (bio_methods == NULL)
 
 3080    if (!(bio_methods = BIO_meth_new(BIO_TYPE_TSG, 
"TSGateway")))
 
 3083    BIO_meth_set_write(bio_methods, transport_bio_tsg_write);
 
 3084    BIO_meth_set_read(bio_methods, transport_bio_tsg_read);
 
 3085    BIO_meth_set_puts(bio_methods, transport_bio_tsg_puts);
 
 3086    BIO_meth_set_gets(bio_methods, transport_bio_tsg_gets);
 
 3087    BIO_meth_set_ctrl(bio_methods, transport_bio_tsg_ctrl);
 
 3088    BIO_meth_set_create(bio_methods, transport_bio_tsg_new);
 
 3089    BIO_meth_set_destroy(bio_methods, transport_bio_tsg_free);
 
 3095TSG_STATE tsg_get_state(rdpTsg* tsg)
 
 3098    return TSG_STATE_INITIAL;
 
 3103BIO* tsg_get_bio(rdpTsg* tsg)
 
 3111BOOL tsg_set_state(rdpTsg* tsg, TSG_STATE state)