20#include <freerdp/config.h> 
   22#include <winpr/assert.h> 
   23#include <winpr/cast.h> 
   25#include <winpr/crypto.h> 
   27#include <freerdp/log.h> 
   29#include "ncacn_http.h" 
   30#include "rpc_client.h" 
   31#include "rts_signature.h" 
   35#define TAG FREERDP_TAG("core.gateway.rts") 
   70static int rts_destination_command_read(rdpRpc* rpc, 
wStream* buffer, UINT32* Destination);
 
   72static const char* rts_command_to_string(UINT32 cmd, 
char* buffer, 
size_t len)
 
   74  const char* str = NULL;
 
   84    ENTRY(RTS_CMD_RECEIVE_WINDOW_SIZE);
 
   85    ENTRY(RTS_CMD_FLOW_CONTROL_ACK);
 
   86    ENTRY(RTS_CMD_CONNECTION_TIMEOUT);
 
   87    ENTRY(RTS_CMD_COOKIE);
 
   88    ENTRY(RTS_CMD_CHANNEL_LIFETIME);
 
   89    ENTRY(RTS_CMD_CLIENT_KEEPALIVE);
 
   90    ENTRY(RTS_CMD_VERSION);
 
   92    ENTRY(RTS_CMD_PADDING);
 
   93    ENTRY(RTS_CMD_NEGATIVE_ANCE);
 
   95    ENTRY(RTS_CMD_CLIENT_ADDRESS);
 
   96    ENTRY(RTS_CMD_ASSOCIATION_GROUP_ID);
 
   97    ENTRY(RTS_CMD_DESTINATION);
 
   98    ENTRY(RTS_CMD_PING_TRAFFIC_SENT_NOTIFY);
 
   99    ENTRY(RTS_CMD_LAST_ID);
 
  101      str = 
"RTS_CMD_UNKNOWN";
 
  107  (void)_snprintf(buffer, len, 
"%s [0x%08" PRIx32 
"]", str, cmd);
 
  111static const char* rts_pdu_ptype_to_string(UINT32 ptype)
 
  116      return "PTYPE_REQUEST";
 
  120      return "PTYPE_RESPONSE";
 
  122      return "PTYPE_FAULT";
 
  124      return "PTYPE_WORKING";
 
  126      return "PTYPE_NOCALL";
 
  128      return "PTYPE_REJECT";
 
  131    case PTYPE_CL_CANCEL:
 
  132      return "PTYPE_CL_CANCEL";
 
  135    case PTYPE_CANCEL_ACK:
 
  136      return "PTYPE_CANCEL_ACK";
 
  140      return "PTYPE_BIND_ACK";
 
  142      return "PTYPE_BIND_NAK";
 
  143    case PTYPE_ALTER_CONTEXT:
 
  144      return "PTYPE_ALTER_CONTEXT";
 
  145    case PTYPE_ALTER_CONTEXT_RESP:
 
  146      return "PTYPE_ALTER_CONTEXT_RESP";
 
  147    case PTYPE_RPC_AUTH_3:
 
  148      return "PTYPE_RPC_AUTH_3";
 
  150      return "PTYPE_SHUTDOWN";
 
  151    case PTYPE_CO_CANCEL:
 
  152      return "PTYPE_CO_CANCEL";
 
  154      return "PTYPE_ORPHANED";
 
  165  header.header.rpc_vers = 5;
 
  166  header.header.rpc_vers_minor = 0;
 
  167  header.header.ptype = PTYPE_RTS;
 
  168  header.header.packed_drep[0] = 0x10;
 
  169  header.header.packed_drep[1] = 0x00;
 
  170  header.header.packed_drep[2] = 0x00;
 
  171  header.header.packed_drep[3] = 0x00;
 
  172  header.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
 
  173  header.header.auth_length = 0;
 
  174  header.header.call_id = 0;
 
  179static BOOL rts_align_stream(
wStream* s, 
size_t alignment, BOOL silent)
 
  185  WINPR_ASSERT(alignment > 0);
 
  187  pos = Stream_GetPosition(s);
 
  188  pad = rpc_offset_align(&pos, alignment);
 
  189  return Stream_ConditionalSafeSeek(s, pad, silent);
 
  192static char* sdup(
const void* src, 
size_t length)
 
  195  WINPR_ASSERT(src || (length == 0));
 
  199  dst = calloc(length + 1, 
sizeof(
char));
 
  202  memcpy(dst, src, length);
 
  209  WINPR_ASSERT(header);
 
  213  Stream_Write_UINT8(s, header->rpc_vers);
 
  214  Stream_Write_UINT8(s, header->rpc_vers_minor);
 
  215  Stream_Write_UINT8(s, header->ptype);
 
  216  Stream_Write_UINT8(s, header->pfc_flags);
 
  217  Stream_Write(s, header->packed_drep, ARRAYSIZE(header->packed_drep));
 
  218  Stream_Write_UINT16(s, header->frag_length);
 
  219  Stream_Write_UINT16(s, header->auth_length);
 
  220  Stream_Write_UINT32(s, header->call_id);
 
  227  WINPR_ASSERT(header);
 
  236    const size_t sz = Stream_GetRemainingLength(s);
 
  241  Stream_Read_UINT8(s, header->rpc_vers);
 
  242  Stream_Read_UINT8(s, header->rpc_vers_minor);
 
  243  Stream_Read_UINT8(s, header->ptype);
 
  244  Stream_Read_UINT8(s, header->pfc_flags);
 
  245  Stream_Read(s, header->packed_drep, ARRAYSIZE(header->packed_drep));
 
  246  Stream_Read_UINT16(s, header->frag_length);
 
  247  Stream_Read_UINT16(s, header->auth_length);
 
  248  Stream_Read_UINT32(s, header->call_id);
 
  253      WLog_WARN(TAG, 
"Invalid header->frag_length of %" PRIu16 
", expected %" PRIuz,
 
  260    if (!Stream_CheckAndLogRequiredLength(TAG, s,
 
  266    const size_t sz2 = Stream_GetRemainingLength(s);
 
  273static BOOL rts_read_auth_verifier_no_checks(
wStream* s, auth_verifier_co_t* auth,
 
  279  WINPR_ASSERT(header);
 
  281  WINPR_ASSERT(header->frag_length > header->auth_length + 8);
 
  284    *startPos = Stream_GetPosition(s);
 
  288    const size_t expected = header->frag_length - header->auth_length - 8;
 
  290    Stream_SetPosition(s, expected);
 
  291    if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 8, silent))
 
  294    Stream_Read_UINT8(s, auth->auth_type);
 
  295    Stream_Read_UINT8(s, auth->auth_level);
 
  296    Stream_Read_UINT8(s, auth->auth_pad_length);
 
  297    Stream_Read_UINT8(s, auth->auth_reserved);
 
  298    Stream_Read_UINT32(s, auth->auth_context_id);
 
  301  if (header->auth_length != 0)
 
  303    const void* ptr = Stream_Pointer(s);
 
  304    if (!Stream_ConditionalSafeSeek(s, header->auth_length, silent))
 
  306    auth->auth_value = (BYTE*)sdup(ptr, header->auth_length);
 
  307    if (auth->auth_value == NULL)
 
  314static BOOL rts_read_auth_verifier(
wStream* s, auth_verifier_co_t* auth,
 
  320  WINPR_ASSERT(header);
 
  322  if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
 
  325  const size_t expected = header->frag_length - header->auth_length - 8;
 
  326  WINPR_ASSERT(pos + auth->auth_pad_length == expected);
 
  327  return pos + auth->auth_pad_length == expected;
 
  330static BOOL rts_read_auth_verifier_with_stub(
wStream* s, auth_verifier_co_t* auth,
 
  334  size_t alloc_hint = 0;
 
  337  if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
 
  340  switch (header->ptype)
 
  345      alloc_hint = hdr->alloc_hint;
 
  346      ptr = &hdr->stub_data;
 
  352      alloc_hint = hdr->alloc_hint;
 
  353      ptr = &hdr->stub_data;
 
  359      alloc_hint = hdr->alloc_hint;
 
  360      ptr = &hdr->stub_data;
 
  369    const size_t off = header->auth_length + 8 + auth->auth_pad_length + pos;
 
  370    const size_t size = header->frag_length - MIN(header->frag_length, off);
 
  371    const void* src = Stream_Buffer(s) + pos;
 
  373    if (off > header->frag_length)
 
  375                "Unexpected alloc_hint(%" PRIuz 
") for PDU %s: size %" PRIuz
 
  376                ", frag_length %" PRIu16 
", offset %" PRIuz,
 
  377                alloc_hint, rts_pdu_ptype_to_string(header->ptype), size, header->frag_length,
 
  383      *ptr = (BYTE*)sdup(src, size);
 
  392static void rts_free_auth_verifier(auth_verifier_co_t* auth)
 
  396  free(auth->auth_value);
 
  399static BOOL rts_write_auth_verifier(
wStream* s, 
const auth_verifier_co_t* auth,
 
  403  UINT8 auth_pad_length = 0;
 
  407  WINPR_ASSERT(header);
 
  410  pos = Stream_GetPosition(s);
 
  413    auth_pad_length = 4 - (pos % 4);
 
  414    if (!Stream_EnsureRemainingCapacity(s, auth_pad_length))
 
  416    Stream_Zero(s, auth_pad_length);
 
  419#if defined(WITH_VERBOSE_WINPR_ASSERT) && (WITH_VERBOSE_WINPR_ASSERT != 0) 
  420  WINPR_ASSERT(header->frag_length + 8ull > header->auth_length);
 
  422    size_t apos = Stream_GetPosition(s);
 
  423    size_t expected = header->frag_length - header->auth_length - 8;
 
  425    WINPR_ASSERT(apos == expected);
 
  429  if (!Stream_EnsureRemainingCapacity(s, 
sizeof(auth_verifier_co_t)))
 
  432  Stream_Write_UINT8(s, auth->auth_type);
 
  433  Stream_Write_UINT8(s, auth->auth_level);
 
  434  Stream_Write_UINT8(s, auth_pad_length);
 
  435  Stream_Write_UINT8(s, 0); 
 
  436  Stream_Write_UINT32(s, auth->auth_context_id);
 
  438  if (!Stream_EnsureRemainingCapacity(s, header->auth_length))
 
  440  Stream_Write(s, auth->auth_value, header->auth_length);
 
  447  WINPR_ASSERT(version);
 
  449  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2 * 
sizeof(UINT8), silent))
 
  451  Stream_Read_UINT8(s, version->major);
 
  452  Stream_Read_UINT8(s, version->minor);
 
  460  free(versions->p_protocols);
 
  461  versions->p_protocols = NULL;
 
  468  WINPR_ASSERT(versions);
 
  470  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 
sizeof(UINT8), silent))
 
  473  Stream_Read_UINT8(s, versions->n_protocols); 
 
  475  if (versions->n_protocols > 0)
 
  477    versions->p_protocols = calloc(versions->n_protocols, 
sizeof(
p_rt_version_t));
 
  478    if (!versions->p_protocols)
 
  481  for (BYTE x = 0; x < versions->n_protocols; x++)
 
  484    if (!rts_read_version(s, version, silent)) 
 
  486      rts_free_supported_versions(versions);
 
  499  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 
sizeof(UINT16), silent))
 
  502  Stream_Read_UINT16(s, port->length);
 
  503  if (port->length == 0)
 
  506  const void* ptr = Stream_ConstPointer(s);
 
  507  if (!Stream_ConditionalSafeSeek(s, port->length, silent))
 
  509  port->port_spec = sdup(ptr, port->length);
 
  510  return port->port_spec != NULL;
 
  513static void rts_free_port_any(
port_any_t* port)
 
  517  free(port->port_spec);
 
  525  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 
sizeof(
p_uuid_t), silent))
 
  528  Stream_Read_UINT32(s, uuid->time_low);
 
  529  Stream_Read_UINT16(s, uuid->time_mid);
 
  530  Stream_Read_UINT16(s, uuid->time_hi_and_version);
 
  531  Stream_Read_UINT8(s, uuid->clock_seq_hi_and_reserved);
 
  532  Stream_Read_UINT8(s, uuid->clock_seq_low);
 
  533  Stream_Read(s, uuid->node, ARRAYSIZE(uuid->node));
 
  542  if (!Stream_EnsureRemainingCapacity(s, 
sizeof(
p_uuid_t)))
 
  545  Stream_Write_UINT32(s, uuid->time_low);
 
  546  Stream_Write_UINT16(s, uuid->time_mid);
 
  547  Stream_Write_UINT16(s, uuid->time_hi_and_version);
 
  548  Stream_Write_UINT8(s, uuid->clock_seq_hi_and_reserved);
 
  549  Stream_Write_UINT8(s, uuid->clock_seq_low);
 
  550  Stream_Write(s, uuid->node, ARRAYSIZE(uuid->node));
 
  567  WINPR_ASSERT(syntax_id);
 
  569  if (!rts_read_uuid(s, &syntax_id->if_uuid, silent))
 
  572  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
 
  575  Stream_Read_UINT32(s, syntax_id->if_version);
 
  582  WINPR_ASSERT(syntax_id);
 
  584  if (!rts_write_uuid(s, &syntax_id->if_uuid))
 
  587  if (!Stream_EnsureRemainingCapacity(s, 4))
 
  590  Stream_Write_UINT32(s, syntax_id->if_version);
 
  598  rts_syntax_id_free(ptr->transfer_syntaxes);
 
  602WINPR_ATTR_MALLOC(rts_context_elem_free, 1)
 
  612  WINPR_ASSERT(element);
 
  614  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
 
  617  Stream_Read_UINT16(s, element->p_cont_id);
 
  618  Stream_Read_UINT8(s, element->n_transfer_syn); 
 
  619  Stream_Read_UINT8(s, element->reserved);       
 
  621  if (!rts_read_syntax_id(s, &element->abstract_syntax, silent)) 
 
  624  if (element->n_transfer_syn > 0)
 
  626    element->transfer_syntaxes = rts_syntax_id_new(element->n_transfer_syn);
 
  627    if (!element->transfer_syntaxes)
 
  629    for (BYTE x = 0; x < element->n_transfer_syn; x++)
 
  632      if (!rts_read_syntax_id(s, syn, silent)) 
 
  643  WINPR_ASSERT(element);
 
  645  if (!Stream_EnsureRemainingCapacity(s, 4))
 
  647  Stream_Write_UINT16(s, element->p_cont_id);
 
  648  Stream_Write_UINT8(s, element->n_transfer_syn);         
 
  649  Stream_Write_UINT8(s, element->reserved);               
 
  650  if (!rts_write_syntax_id(s, &element->abstract_syntax)) 
 
  653  for (BYTE x = 0; x < element->n_transfer_syn; x++)
 
  656    if (!rts_write_syntax_id(s, syn)) 
 
  668  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
 
  670  Stream_Read_UINT8(s, list->n_context_elem); 
 
  671  Stream_Read_UINT8(s, list->reserved);       
 
  672  Stream_Read_UINT16(s, list->reserved2);     
 
  674  if (list->n_context_elem > 0)
 
  676    list->p_cont_elem = rts_context_elem_new(list->n_context_elem);
 
  677    if (!list->p_cont_elem)
 
  679    for (BYTE x = 0; x < list->n_context_elem; x++)
 
  682      if (!rts_read_context_elem(s, element, silent))
 
  693  rts_context_elem_free(list->p_cont_elem);
 
  701  if (!Stream_EnsureRemainingCapacity(s, 4))
 
  703  Stream_Write_UINT8(s, list->n_context_elem); 
 
  704  Stream_Write_UINT8(s, 0);                    
 
  705  Stream_Write_UINT16(s, 0);                   
 
  707  for (BYTE x = 0; x < list->n_context_elem; x++)
 
  710    if (!rts_write_context_elem(s, element))
 
  716static p_result_t* rts_result_new(
size_t count)
 
  721static void rts_result_free(
p_result_t* results)
 
  731  WINPR_ASSERT(result);
 
  733  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2, silent))
 
  735  Stream_Read_UINT16(s, result->result);
 
  736  Stream_Read_UINT16(s, result->reason);
 
  738  return rts_read_syntax_id(s, &result->transfer_syntax, silent);
 
  741static void rts_free_result(
p_result_t* result)
 
  752  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
 
  754  Stream_Read_UINT8(s, list->n_results);  
 
  755  Stream_Read_UINT8(s, list->reserved);   
 
  756  Stream_Read_UINT16(s, list->reserved2); 
 
  758  if (list->n_results > 0)
 
  760    list->p_results = rts_result_new(list->n_results);
 
  761    if (!list->p_results)
 
  764    for (BYTE x = 0; x < list->n_results; x++)
 
  767      if (!rts_read_result(s, result, silent))
 
  779  for (BYTE x = 0; x < list->n_results; x++)
 
  782    rts_free_result(result);
 
  784  rts_result_free(list->p_results);
 
  792  rts_free_context_list(&ctx->p_context_elem);
 
  793  rts_free_auth_verifier(&ctx->auth_verifier);
 
  801  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
  805  Stream_Read_UINT16(s, ctx->max_xmit_frag);
 
  806  Stream_Read_UINT16(s, ctx->max_recv_frag);
 
  807  Stream_Read_UINT32(s, ctx->assoc_group_id);
 
  809  if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
 
  812  if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
 
  818static BOOL rts_read_pdu_alter_context_response(
wStream* s,
 
  825  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
  829  Stream_Read_UINT16(s, ctx->max_xmit_frag);
 
  830  Stream_Read_UINT16(s, ctx->max_recv_frag);
 
  831  Stream_Read_UINT32(s, ctx->assoc_group_id);
 
  833  if (!rts_read_port_any(s, &ctx->sec_addr, silent))
 
  836  if (!rts_align_stream(s, 4, silent))
 
  839  if (!rts_read_result_list(s, &ctx->p_result_list, silent))
 
  842  if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
 
  853  rts_free_port_any(&ctx->sec_addr);
 
  854  rts_free_result_list(&ctx->p_result_list);
 
  855  rts_free_auth_verifier(&ctx->auth_verifier);
 
  863  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
  866  Stream_Read_UINT16(s, ctx->max_xmit_frag);
 
  867  Stream_Read_UINT16(s, ctx->max_recv_frag);
 
  868  Stream_Read_UINT32(s, ctx->assoc_group_id);
 
  870  if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
 
  873  if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
 
  883  rts_free_context_list(&ctx->p_context_elem);
 
  884  rts_free_auth_verifier(&ctx->auth_verifier);
 
  892  if (!Stream_CheckAndLogRequiredLength(
 
  895  Stream_Read_UINT16(s, ctx->max_xmit_frag);
 
  896  Stream_Read_UINT16(s, ctx->max_recv_frag);
 
  897  Stream_Read_UINT32(s, ctx->assoc_group_id);
 
  899  if (!rts_read_port_any(s, &ctx->sec_addr, silent))
 
  902  if (!rts_align_stream(s, 4, silent))
 
  905  if (!rts_read_result_list(s, &ctx->p_result_list, silent))
 
  908  return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
 
  915  rts_free_port_any(&ctx->sec_addr);
 
  916  rts_free_result_list(&ctx->p_result_list);
 
  917  rts_free_auth_verifier(&ctx->auth_verifier);
 
  925  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
  928  Stream_Read_UINT16(s, ctx->provider_reject_reason);
 
  929  return rts_read_supported_versions(s, &ctx->versions, silent);
 
  937  rts_free_supported_versions(&ctx->versions);
 
  945  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
  948  Stream_Read_UINT16(s, ctx->max_xmit_frag);
 
  949  Stream_Read_UINT16(s, ctx->max_recv_frag);
 
  951  return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
 
  958  rts_free_auth_verifier(&ctx->auth_verifier);
 
  966  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 12, silent))
 
  968  Stream_Read_UINT32(s, ctx->alloc_hint);
 
  969  Stream_Read_UINT16(s, ctx->p_cont_id);
 
  970  Stream_Read_UINT8(s, ctx->cancel_count);
 
  971  Stream_Read_UINT8(s, ctx->reserved);
 
  972  Stream_Read_UINT32(s, ctx->status);
 
  974  WLog_WARN(TAG, 
"status=%s", Win32ErrorCode2Tag(ctx->status & 0xFFFF));
 
  975  return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
 
  982  rts_free_auth_verifier(&ctx->auth_verifier);
 
  990  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
  993  return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
 
 1000  rts_free_auth_verifier(&ctx->auth_verifier);
 
 1008  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
 1011  return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
 
 1018  rts_free_auth_verifier(&ctx->auth_verifier);
 
 1026  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
 1029  Stream_Read_UINT32(s, ctx->alloc_hint);
 
 1030  Stream_Read_UINT16(s, ctx->p_cont_id);
 
 1031  Stream_Read_UINT16(s, ctx->opnum);
 
 1032  if (!rts_read_uuid(s, &ctx->object, silent))
 
 1035  return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
 
 1042  rts_free_auth_verifier(&ctx->auth_verifier);
 
 1050  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
 1053  Stream_Read_UINT32(s, ctx->alloc_hint);
 
 1054  Stream_Read_UINT16(s, ctx->p_cont_id);
 
 1055  Stream_Read_UINT8(s, ctx->cancel_count);
 
 1056  Stream_Read_UINT8(s, ctx->reserved);
 
 1058  if (!rts_align_stream(s, 8, silent))
 
 1061  return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
 
 1068  free(ctx->stub_data);
 
 1069  rts_free_auth_verifier(&ctx->auth_verifier);
 
 1077  if (!Stream_ConditionalCheckAndLogRequiredLength(
 
 1081  Stream_Read_UINT16(s, ctx->Flags);
 
 1082  Stream_Read_UINT16(s, ctx->NumberOfCommands);
 
 1091void rts_free_pdu_header(
rpcconn_hdr_t* header, BOOL allocated)
 
 1096  switch (header->common.ptype)
 
 1098    case PTYPE_ALTER_CONTEXT:
 
 1099      rts_free_pdu_alter_context(&header->alter_context);
 
 1101    case PTYPE_ALTER_CONTEXT_RESP:
 
 1102      rts_free_pdu_alter_context_response(&header->alter_context_response);
 
 1105      rts_free_pdu_bind(&header->bind);
 
 1107    case PTYPE_BIND_ACK:
 
 1108      rts_free_pdu_bind_ack(&header->bind_ack);
 
 1110    case PTYPE_BIND_NAK:
 
 1111      rts_free_pdu_bind_nak(&header->bind_nak);
 
 1113    case PTYPE_RPC_AUTH_3:
 
 1114      rts_free_pdu_auth3(&header->rpc_auth_3);
 
 1116    case PTYPE_CANCEL_ACK:
 
 1117      rts_free_pdu_cancel_ack(&header->cancel);
 
 1120      rts_free_pdu_fault(&header->fault);
 
 1122    case PTYPE_ORPHANED:
 
 1123      rts_free_pdu_orphaned(&header->orphaned);
 
 1126      rts_free_pdu_request(&header->request);
 
 1128    case PTYPE_RESPONSE:
 
 1129      rts_free_pdu_response(&header->response);
 
 1132      rts_free_pdu_rts(&header->rts);
 
 1135    case PTYPE_SHUTDOWN:
 
 1144    case PTYPE_CL_CANCEL:
 
 1146    case PTYPE_CO_CANCEL:
 
 1157  return rts_read_pdu_header_ex(s, header, FALSE);
 
 1164  WINPR_ASSERT(header);
 
 1166  if (!rts_read_common_pdu_header(s, &header->common, silent))
 
 1169  WLog_DBG(TAG, 
"Reading PDU type %s", rts_pdu_ptype_to_string(header->common.ptype));
 
 1171  switch (header->common.ptype)
 
 1173    case PTYPE_ALTER_CONTEXT:
 
 1174      rc = rts_read_pdu_alter_context(s, &header->alter_context, silent);
 
 1176    case PTYPE_ALTER_CONTEXT_RESP:
 
 1177      rc = rts_read_pdu_alter_context_response(s, &header->alter_context_response, silent);
 
 1180      rc = rts_read_pdu_bind(s, &header->bind, silent);
 
 1182    case PTYPE_BIND_ACK:
 
 1183      rc = rts_read_pdu_bind_ack(s, &header->bind_ack, silent);
 
 1185    case PTYPE_BIND_NAK:
 
 1186      rc = rts_read_pdu_bind_nak(s, &header->bind_nak, silent);
 
 1188    case PTYPE_RPC_AUTH_3:
 
 1189      rc = rts_read_pdu_auth3(s, &header->rpc_auth_3, silent);
 
 1191    case PTYPE_CANCEL_ACK:
 
 1192      rc = rts_read_pdu_cancel_ack(s, &header->cancel, silent);
 
 1195      rc = rts_read_pdu_fault(s, &header->fault, silent);
 
 1197    case PTYPE_ORPHANED:
 
 1198      rc = rts_read_pdu_orphaned(s, &header->orphaned, silent);
 
 1201      rc = rts_read_pdu_request(s, &header->request, silent);
 
 1203    case PTYPE_RESPONSE:
 
 1204      rc = rts_read_pdu_response(s, &header->response, silent);
 
 1207      rc = rts_read_pdu_rts(s, &header->rts, silent);
 
 1209    case PTYPE_SHUTDOWN:
 
 1219    case PTYPE_CL_CANCEL:
 
 1221    case PTYPE_CO_CANCEL:
 
 1232  WINPR_ASSERT(header);
 
 1236  if (!rts_write_common_pdu_header(s, &header->header))
 
 1239  Stream_Write_UINT16(s, header->Flags);
 
 1240  Stream_Write_UINT16(s, header->NumberOfCommands);
 
 1245static BOOL rts_receive_window_size_command_read(rdpRpc* rpc, 
wStream* buffer,
 
 1246                                                 UINT32* ReceiveWindowSize)
 
 1249  WINPR_ASSERT(buffer);
 
 1251  if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
 
 1253  const uint32_t CommandType = Stream_Get_UINT32(buffer);
 
 1254  if (CommandType != RTS_CMD_RECEIVE_WINDOW_SIZE)
 
 1256    WLog_Print(rpc->log, WLOG_ERROR,
 
 1257               "[MS-RPCH] 2.2.3.5.1 ReceiveWindowSize::CommandType must be 0x%08" PRIx32
 
 1260               WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_RECEIVE_WINDOW_SIZE), CommandType);
 
 1263  const UINT32 val = Stream_Get_UINT32(buffer);
 
 1264  if (ReceiveWindowSize)
 
 1265    *ReceiveWindowSize = val; 
 
 1271static BOOL rts_receive_window_size_command_write(
wStream* s, UINT32 ReceiveWindowSize)
 
 1275  if (!Stream_EnsureRemainingCapacity(s, 2 * 
sizeof(UINT32)))
 
 1278  Stream_Write_UINT32(s, RTS_CMD_RECEIVE_WINDOW_SIZE); 
 
 1279  Stream_Write_UINT32(s, ReceiveWindowSize);           
 
 1285static int rts_flow_control_ack_command_read(rdpRpc* rpc, 
wStream* buffer, UINT32* BytesReceived,
 
 1286                                             UINT32* AvailableWindow, BYTE* ChannelCookie)
 
 1292  WINPR_ASSERT(buffer);
 
 1294  int rc = rts_destination_command_read(rpc, buffer, &Command);
 
 1298  if (Command != RTS_CMD_FLOW_CONTROL_ACK)
 
 1300    char buffer1[64] = { 0 };
 
 1301    char buffer2[64] = { 0 };
 
 1302    WLog_Print(rpc->log, WLOG_ERROR, 
"got command %s, expected %s",
 
 1303               rts_command_to_string(Command, buffer1, 
sizeof(buffer1)),
 
 1304               rts_command_to_string(RTS_CMD_FLOW_CONTROL_ACK, buffer2, 
sizeof(buffer2)));
 
 1309  if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 24))
 
 1312  Stream_Read_UINT32(buffer, val);
 
 1314    *BytesReceived = val; 
 
 1316  Stream_Read_UINT32(buffer, val);
 
 1317  if (AvailableWindow)
 
 1318    *AvailableWindow = val; 
 
 1321    Stream_Read(buffer, ChannelCookie, 16); 
 
 1323    Stream_Seek(buffer, 16);
 
 1328static BOOL rts_flow_control_ack_command_write(
wStream* s, UINT32 BytesReceived,
 
 1329                                               UINT32 AvailableWindow, BYTE* ChannelCookie)
 
 1333  if (!Stream_EnsureRemainingCapacity(s, 28))
 
 1336  Stream_Write_UINT32(s, RTS_CMD_FLOW_CONTROL_ACK); 
 
 1337  Stream_Write_UINT32(s, BytesReceived);            
 
 1338  Stream_Write_UINT32(s, AvailableWindow);          
 
 1339  Stream_Write(s, ChannelCookie, 16);               
 
 1345static BOOL rts_connection_timeout_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc, 
wStream* buffer,
 
 1346                                                UINT32* ConnectionTimeout)
 
 1349  WINPR_ASSERT(buffer);
 
 1351  if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
 
 1354  const uint32_t CommandType = Stream_Get_UINT32(buffer);
 
 1355  if (CommandType != RTS_CMD_CONNECTION_TIMEOUT)
 
 1357    WLog_Print(rpc->log, WLOG_ERROR,
 
 1358               "[MS-RPCH] 2.2.3.5.3 ConnectionTimeout::CommandType must be 0x%08" PRIx32
 
 1361               WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_CONNECTION_TIMEOUT), CommandType);
 
 1364  const UINT32 val = Stream_Get_UINT32(buffer);
 
 1365  if (ConnectionTimeout)
 
 1366    *ConnectionTimeout = val; 
 
 1371static BOOL rts_cookie_command_write(
wStream* s, 
const BYTE* Cookie)
 
 1375  if (!Stream_EnsureRemainingCapacity(s, 20))
 
 1378  Stream_Write_UINT32(s, RTS_CMD_COOKIE); 
 
 1379  Stream_Write(s, Cookie, 16);            
 
 1384static BOOL rts_channel_lifetime_command_write(
wStream* s, UINT32 ChannelLifetime)
 
 1388  if (!Stream_EnsureRemainingCapacity(s, 8))
 
 1390  Stream_Write_UINT32(s, RTS_CMD_CHANNEL_LIFETIME); 
 
 1391  Stream_Write_UINT32(s, ChannelLifetime);          
 
 1396static BOOL rts_client_keepalive_command_write(
wStream* s, UINT32 ClientKeepalive)
 
 1400  if (!Stream_EnsureRemainingCapacity(s, 8))
 
 1408  Stream_Write_UINT32(s, RTS_CMD_CLIENT_KEEPALIVE); 
 
 1409  Stream_Write_UINT32(s, ClientKeepalive);          
 
 1415static BOOL rts_version_command_read(rdpRpc* rpc, 
wStream* buffer, uint32_t* pversion)
 
 1418  WINPR_ASSERT(buffer);
 
 1420  if (!Stream_EnsureRemainingCapacity(buffer, 8))
 
 1423  const uint32_t CommandType = Stream_Get_UINT32(buffer); 
 
 1424  if (CommandType != RTS_CMD_VERSION)
 
 1426    WLog_Print(rpc->log, WLOG_ERROR,
 
 1427               "[MS-RPCH] 2.2.3.5.7 Version::CommandType must be 0x%08" PRIx32 
", got " 
 1429               WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_VERSION), CommandType);
 
 1432  const uint32_t version = Stream_Get_UINT32(buffer); 
 
 1435    WLog_Print(rpc->log, WLOG_WARN,
 
 1436               "[MS-RPCH] 2.2.3.5.7 Version::Version should be 0x00000001, got 0x%08" PRIx32,
 
 1440    *pversion = version;
 
 1446static BOOL rts_version_command_write(
wStream* buffer)
 
 1448  WINPR_ASSERT(buffer);
 
 1450  if (!Stream_EnsureRemainingCapacity((buffer), 8))
 
 1453  Stream_Write_UINT32(buffer, RTS_CMD_VERSION); 
 
 1454  Stream_Write_UINT32(buffer, 1);               
 
 1459static BOOL rts_empty_command_write(
wStream* s)
 
 1463  if (!Stream_EnsureRemainingCapacity(s, 8))
 
 1466  Stream_Write_UINT32(s, RTS_CMD_EMPTY); 
 
 1471static BOOL rts_padding_command_read(
wStream* s, 
size_t* length, BOOL silent)
 
 1473  UINT32 ConformanceCount = 0;
 
 1475  WINPR_ASSERT(length);
 
 1476  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
 
 1478  Stream_Read_UINT32(s, ConformanceCount); 
 
 1479  *length = ConformanceCount + 4;
 
 1483static BOOL rts_client_address_command_read(
wStream* s, 
size_t* length, BOOL silent)
 
 1485  UINT32 AddressType = 0;
 
 1488  WINPR_ASSERT(length);
 
 1490  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
 
 1492  Stream_Read_UINT32(s, AddressType); 
 
 1494  if (AddressType == 0)
 
 1498    *length = 4 + 4 + 12;
 
 1504    *length = 4 + 16 + 12;
 
 1509static BOOL rts_association_group_id_command_write(
wStream* s, 
const BYTE* AssociationGroupId)
 
 1513  if (!Stream_EnsureRemainingCapacity(s, 20))
 
 1516  Stream_Write_UINT32(s, RTS_CMD_ASSOCIATION_GROUP_ID); 
 
 1517  Stream_Write(s, AssociationGroupId, 16);              
 
 1522static int rts_destination_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc, 
wStream* buffer,
 
 1523                                        UINT32* Destination)
 
 1527  WINPR_ASSERT(buffer);
 
 1529  if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 4))
 
 1531  Stream_Read_UINT32(buffer, val);
 
 1538static BOOL rts_destination_command_write(
wStream* s, UINT32 Destination)
 
 1542  if (!Stream_EnsureRemainingCapacity(s, 8))
 
 1545  Stream_Write_UINT32(s, RTS_CMD_DESTINATION); 
 
 1546  Stream_Write_UINT32(s, Destination);         
 
 1551void rts_generate_cookie(BYTE* cookie)
 
 1553  WINPR_ASSERT(cookie);
 
 1554  winpr_RAND(cookie, 16);
 
 1557#define rts_send_buffer(channel, s, frag_length) \ 
 1558  rts_send_buffer_int((channel), (s), (frag_length), __FILE__, __LINE__, __func__) 
 1559static BOOL rts_send_buffer_int(
RpcChannel* channel, 
wStream* s, 
size_t frag_length,
 
 1560                                const char* file, 
size_t line, 
const char* fkt)
 
 1562  BOOL status = FALSE;
 
 1565  WINPR_ASSERT(channel);
 
 1566  WINPR_ASSERT(channel->rpc);
 
 1569  Stream_SealLength(s);
 
 1571  const DWORD level = WLOG_TRACE;
 
 1572  if (WLog_IsLevelActive(channel->rpc->log, level))
 
 1574    WLog_PrintTextMessage(channel->rpc->log, level, line, file, fkt,
 
 1575                          "Sending [%s] %" PRIuz 
" bytes", fkt, Stream_Length(s));
 
 1579  if (Stream_Length(s) != frag_length)
 
 1582  rc = rpc_channel_write(channel, Stream_Buffer(s), Stream_Length(s));
 
 1585  if ((
size_t)rc != Stream_Length(s))
 
 1594BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc)
 
 1596  BOOL status = FALSE;
 
 1599  UINT32 ReceiveWindowSize = 0;
 
 1600  BYTE* OUTChannelCookie = NULL;
 
 1601  BYTE* VirtualConnectionCookie = NULL;
 
 1607  connection = rpc->VirtualConnection;
 
 1608  WINPR_ASSERT(connection);
 
 1610  outChannel = connection->DefaultOutChannel;
 
 1611  WINPR_ASSERT(outChannel);
 
 1613  header.header.frag_length = 76;
 
 1614  header.Flags = RTS_FLAG_NONE;
 
 1615  header.NumberOfCommands = 4;
 
 1617  WLog_DBG(TAG, 
"Sending CONN/A1 RTS PDU");
 
 1618  VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
 
 1619  OUTChannelCookie = (BYTE*)&(outChannel->common.Cookie);
 
 1620  ReceiveWindowSize = outChannel->ReceiveWindow;
 
 1622  buffer = Stream_New(NULL, header.header.frag_length);
 
 1627  if (!rts_write_pdu_header(buffer, &header)) 
 
 1629  status = rts_version_command_write(buffer); 
 
 1632  status = rts_cookie_command_write(
 
 1633      buffer, VirtualConnectionCookie); 
 
 1636  status = rts_cookie_command_write(buffer, OUTChannelCookie); 
 
 1639  status = rts_receive_window_size_command_write(
 
 1640      buffer, ReceiveWindowSize); 
 
 1643  status = rts_send_buffer(&outChannel->common, buffer, header.header.frag_length);
 
 1645  Stream_Free(buffer, TRUE);
 
 1649BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc, 
wStream* buffer)
 
 1652  UINT32 ConnectionTimeout = 0;
 
 1655  if (!rts_read_pdu_header(buffer, &header))
 
 1658  if (header.rts.Flags != RTS_FLAG_NONE)
 
 1660    WLog_Print(rpc->log, WLOG_ERROR,
 
 1661               "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected Flags=0x%08" PRIx32
 
 1662               ", expected 0x%08" PRIx32,
 
 1663               header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
 
 1666  if (header.rts.NumberOfCommands != 1)
 
 1668    WLog_Print(rpc->log, WLOG_ERROR,
 
 1669               "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected NumberOfCommands=%" PRIu32
 
 1671               header.rts.NumberOfCommands);
 
 1675  if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
 
 1678  WLog_Print(rpc->log, WLOG_DEBUG, 
"Receiving CONN/A3 RTS PDU: ConnectionTimeout: %" PRIu32 
"",
 
 1682  WINPR_ASSERT(rpc->VirtualConnection);
 
 1683  WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
 
 1685  rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
 
 1690  rts_free_pdu_header(&header, FALSE);
 
 1696BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc)
 
 1698  BOOL status = FALSE;
 
 1701  BYTE* INChannelCookie = NULL;
 
 1702  BYTE* AssociationGroupId = NULL;
 
 1703  BYTE* VirtualConnectionCookie = NULL;
 
 1709  connection = rpc->VirtualConnection;
 
 1710  WINPR_ASSERT(connection);
 
 1712  inChannel = connection->DefaultInChannel;
 
 1713  WINPR_ASSERT(inChannel);
 
 1715  header.header.frag_length = 104;
 
 1716  header.Flags = RTS_FLAG_NONE;
 
 1717  header.NumberOfCommands = 6;
 
 1719  WLog_DBG(TAG, 
"Sending CONN/B1 RTS PDU");
 
 1721  VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
 
 1722  INChannelCookie = (BYTE*)&(inChannel->common.Cookie);
 
 1723  AssociationGroupId = (BYTE*)&(connection->AssociationGroupId);
 
 1724  buffer = Stream_New(NULL, header.header.frag_length);
 
 1728  if (!rts_write_pdu_header(buffer, &header)) 
 
 1730  if (!rts_version_command_write(buffer)) 
 
 1732  if (!rts_cookie_command_write(buffer,
 
 1733                                VirtualConnectionCookie)) 
 
 1735  if (!rts_cookie_command_write(buffer, INChannelCookie)) 
 
 1737  if (!rts_channel_lifetime_command_write(buffer,
 
 1738                                          rpc->ChannelLifetime)) 
 
 1740  if (!rts_client_keepalive_command_write(buffer,
 
 1741                                          rpc->KeepAliveInterval)) 
 
 1743  if (!rts_association_group_id_command_write(
 
 1744          buffer, AssociationGroupId)) 
 
 1746  status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
 
 1748  Stream_Free(buffer, TRUE);
 
 1754BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc, 
wStream* buffer)
 
 1757  UINT32 ReceiveWindowSize = 0;
 
 1758  UINT32 ConnectionTimeout = 0;
 
 1761  WINPR_ASSERT(buffer);
 
 1764  if (!rts_read_pdu_header(buffer, &header))
 
 1767  if (header.rts.Flags != RTS_FLAG_NONE)
 
 1769    WLog_Print(rpc->log, WLOG_ERROR,
 
 1770               "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected Flags=0x%08" PRIx32
 
 1771               ", expected 0x%08" PRIx32,
 
 1772               header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
 
 1775  if (header.rts.NumberOfCommands != 3)
 
 1777    WLog_Print(rpc->log, WLOG_ERROR,
 
 1778               "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected NumberOfCommands=%" PRIu32
 
 1780               header.rts.NumberOfCommands);
 
 1783  if (!rts_version_command_read(rpc, buffer, NULL))
 
 1786  if (!rts_receive_window_size_command_read(rpc, buffer, &ReceiveWindowSize))
 
 1789  if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
 
 1792  WLog_Print(rpc->log, WLOG_DEBUG,
 
 1793             "Receiving CONN/C2 RTS PDU: ConnectionTimeout: %" PRIu32
 
 1794             " ReceiveWindowSize: %" PRIu32 
"",
 
 1795             ConnectionTimeout, ReceiveWindowSize);
 
 1798  WINPR_ASSERT(rpc->VirtualConnection);
 
 1799  WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
 
 1801  rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
 
 1802  rpc->VirtualConnection->DefaultInChannel->PeerReceiveWindow = ReceiveWindowSize;
 
 1807  rts_free_pdu_header(&header, FALSE);
 
 1813BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc)
 
 1815  BOOL status = FALSE;
 
 1818  UINT32 BytesReceived = 0;
 
 1819  UINT32 AvailableWindow = 0;
 
 1820  BYTE* ChannelCookie = NULL;
 
 1827  connection = rpc->VirtualConnection;
 
 1828  WINPR_ASSERT(connection);
 
 1830  inChannel = connection->DefaultInChannel;
 
 1831  WINPR_ASSERT(inChannel);
 
 1833  outChannel = connection->DefaultOutChannel;
 
 1834  WINPR_ASSERT(outChannel);
 
 1836  header.header.frag_length = 56;
 
 1837  header.Flags = RTS_FLAG_OTHER_CMD;
 
 1838  header.NumberOfCommands = 2;
 
 1840  WLog_DBG(TAG, 
"Sending FlowControlAck RTS PDU");
 
 1842  BytesReceived = outChannel->BytesReceived;
 
 1843  AvailableWindow = outChannel->AvailableWindowAdvertised;
 
 1844  ChannelCookie = (BYTE*)&(outChannel->common.Cookie);
 
 1845  outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
 
 1846  buffer = Stream_New(NULL, header.header.frag_length);
 
 1851  if (!rts_write_pdu_header(buffer, &header)) 
 
 1853  if (!rts_destination_command_write(buffer, FDOutProxy)) 
 
 1857  if (!rts_flow_control_ack_command_write(buffer, BytesReceived, AvailableWindow, ChannelCookie))
 
 1860  status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
 
 1862  Stream_Free(buffer, TRUE);
 
 1866static int rts_recv_flow_control_ack_pdu(rdpRpc* rpc, 
wStream* buffer)
 
 1869  UINT32 BytesReceived = 0;
 
 1870  UINT32 AvailableWindow = 0;
 
 1871  BYTE ChannelCookie[16] = { 0 };
 
 1873  rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
 
 1874                                         (BYTE*)&ChannelCookie);
 
 1878           "Receiving FlowControlAck RTS PDU: BytesReceived: %" PRIu32
 
 1879           " AvailableWindow: %" PRIu32 
"",
 
 1880           BytesReceived, AvailableWindow);
 
 1882  WINPR_ASSERT(rpc->VirtualConnection);
 
 1883  WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
 
 1885  rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
 
 1886      AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
 
 1890static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, 
wStream* buffer)
 
 1893  UINT32 Destination = 0;
 
 1894  UINT32 BytesReceived = 0;
 
 1895  UINT32 AvailableWindow = 0;
 
 1896  BYTE ChannelCookie[16] = { 0 };
 
 1914  int rc = rts_destination_command_read(rpc, buffer, &Command);
 
 1918  if (Command != RTS_CMD_DESTINATION)
 
 1920    char buffer1[64] = { 0 };
 
 1921    char buffer2[64] = { 0 };
 
 1922    WLog_Print(rpc->log, WLOG_ERROR, 
"got command %s, expected %s",
 
 1923               rts_command_to_string(Command, buffer1, 
sizeof(buffer1)),
 
 1924               rts_command_to_string(RTS_CMD_DESTINATION, buffer2, 
sizeof(buffer2)));
 
 1928  rc = rts_destination_command_read(rpc, buffer, &Destination);
 
 1932  switch (Destination)
 
 1943      WLog_Print(rpc->log, WLOG_ERROR,
 
 1944                 "got destination %" PRIu32
 
 1945                 ", expected one of [FDClient[0]|FDInProxy[1]|FDServer[2]|FDOutProxy[3]",
 
 1950  rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
 
 1956           "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %" PRIu32
 
 1957           " AvailableWindow: %" PRIu32 
"",
 
 1958           BytesReceived, AvailableWindow);
 
 1960  WINPR_ASSERT(rpc->VirtualConnection);
 
 1961  WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
 
 1962  rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
 
 1963      AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
 
 1967BOOL rts_recv_ping_pdu(rdpRpc* rpc, 
wStream* s)
 
 1973  WINPR_ASSERT(rpc->auth);
 
 1976  if (!rts_read_pdu_header(s, &header))
 
 1980  if (header.common.ptype != PTYPE_RTS)
 
 1982    WLog_Print(rpc->log, WLOG_ERROR, 
"received invalid ping PDU, type is 0x%" PRIx32,
 
 1983               header.common.ptype);
 
 1986  if (header.rts.Flags != RTS_FLAG_PING)
 
 1988    WLog_Print(rpc->log, WLOG_ERROR, 
"received unexpected ping PDU::Flags 0x%" PRIx32,
 
 1993  rts_free_pdu_header(&header, FALSE);
 
 1997static int rts_send_ping_pdu(rdpRpc* rpc)
 
 1999  BOOL status = FALSE;
 
 2005  WINPR_ASSERT(rpc->VirtualConnection);
 
 2007  inChannel = rpc->VirtualConnection->DefaultInChannel;
 
 2008  WINPR_ASSERT(inChannel);
 
 2010  header.header.frag_length = 20;
 
 2011  header.Flags = RTS_FLAG_PING;
 
 2012  header.NumberOfCommands = 0;
 
 2014  WLog_DBG(TAG, 
"Sending Ping RTS PDU");
 
 2015  buffer = Stream_New(NULL, header.header.frag_length);
 
 2020  if (!rts_write_pdu_header(buffer, &header)) 
 
 2022  status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
 
 2024  Stream_Free(buffer, TRUE);
 
 2025  return (status) ? 1 : -1;
 
 2028BOOL rts_command_length(UINT32 CommandType, 
wStream* s, 
size_t* length, BOOL silent)
 
 2031  size_t CommandLength = 0;
 
 2035  switch (CommandType)
 
 2037    case RTS_CMD_RECEIVE_WINDOW_SIZE:
 
 2038      CommandLength = RTS_CMD_RECEIVE_WINDOW_SIZE_LENGTH;
 
 2041    case RTS_CMD_FLOW_CONTROL_ACK:
 
 2042      CommandLength = RTS_CMD_FLOW_CONTROL_ACK_LENGTH;
 
 2045    case RTS_CMD_CONNECTION_TIMEOUT:
 
 2046      CommandLength = RTS_CMD_CONNECTION_TIMEOUT_LENGTH;
 
 2049    case RTS_CMD_COOKIE:
 
 2050      CommandLength = RTS_CMD_COOKIE_LENGTH;
 
 2053    case RTS_CMD_CHANNEL_LIFETIME:
 
 2054      CommandLength = RTS_CMD_CHANNEL_LIFETIME_LENGTH;
 
 2057    case RTS_CMD_CLIENT_KEEPALIVE:
 
 2058      CommandLength = RTS_CMD_CLIENT_KEEPALIVE_LENGTH;
 
 2061    case RTS_CMD_VERSION:
 
 2062      CommandLength = RTS_CMD_VERSION_LENGTH;
 
 2066      CommandLength = RTS_CMD_EMPTY_LENGTH;
 
 2069    case RTS_CMD_PADDING: 
 
 2070      if (!rts_padding_command_read(s, &padding, silent))
 
 2074    case RTS_CMD_NEGATIVE_ANCE:
 
 2075      CommandLength = RTS_CMD_NEGATIVE_ANCE_LENGTH;
 
 2079      CommandLength = RTS_CMD_ANCE_LENGTH;
 
 2082    case RTS_CMD_CLIENT_ADDRESS: 
 
 2083      if (!rts_client_address_command_read(s, &CommandLength, silent))
 
 2087    case RTS_CMD_ASSOCIATION_GROUP_ID:
 
 2088      CommandLength = RTS_CMD_ASSOCIATION_GROUP_ID_LENGTH;
 
 2091    case RTS_CMD_DESTINATION:
 
 2092      CommandLength = RTS_CMD_DESTINATION_LENGTH;
 
 2095    case RTS_CMD_PING_TRAFFIC_SENT_NOTIFY:
 
 2096      CommandLength = RTS_CMD_PING_TRAFFIC_SENT_NOTIFY_LENGTH;
 
 2100      WLog_ERR(TAG, 
"Error: Unknown RTS Command Type: 0x%" PRIx32 
"", CommandType);
 
 2104  CommandLength += padding;
 
 2105  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, CommandLength, silent))
 
 2109    *length = CommandLength;
 
 2113static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
 
 2115  BOOL status = FALSE;
 
 2118  BYTE* SuccessorChannelCookie = NULL;
 
 2123  WINPR_ASSERT(rpc->VirtualConnection);
 
 2125  inChannel = rpc->VirtualConnection->DefaultInChannel;
 
 2126  WINPR_ASSERT(inChannel);
 
 2128  nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
 
 2129  WINPR_ASSERT(nextOutChannel);
 
 2131  header.header.frag_length = 56;
 
 2132  header.Flags = RTS_FLAG_OUT_CHANNEL;
 
 2133  header.NumberOfCommands = 3;
 
 2135  WLog_DBG(TAG, 
"Sending OUT_R2/A7 RTS PDU");
 
 2137  SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
 
 2138  buffer = Stream_New(NULL, header.header.frag_length);
 
 2143  if (!rts_write_pdu_header(buffer, &header)) 
 
 2145  if (!rts_destination_command_write(buffer, FDServer)) 
 
 2147  if (!rts_cookie_command_write(buffer,
 
 2148                                SuccessorChannelCookie)) 
 
 2150  if (!rts_version_command_write(buffer)) 
 
 2152  status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
 
 2154  Stream_Free(buffer, TRUE);
 
 2155  return (status) ? 1 : -1;
 
 2158static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc)
 
 2160  BOOL status = FALSE;
 
 2166  WINPR_ASSERT(rpc->VirtualConnection);
 
 2168  nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
 
 2169  WINPR_ASSERT(nextOutChannel);
 
 2171  header.header.frag_length = 24;
 
 2172  header.Flags = RTS_FLAG_PING;
 
 2173  header.NumberOfCommands = 1;
 
 2175  WLog_DBG(TAG, 
"Sending OUT_R2/C1 RTS PDU");
 
 2176  buffer = Stream_New(NULL, header.header.frag_length);
 
 2181  if (!rts_write_pdu_header(buffer, &header)) 
 
 2184  if (!rts_empty_command_write(buffer)) 
 
 2186  status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
 
 2188  Stream_Free(buffer, TRUE);
 
 2189  return (status) ? 1 : -1;
 
 2192BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
 
 2194  BOOL status = FALSE;
 
 2197  UINT32 ReceiveWindowSize = 0;
 
 2198  BYTE* VirtualConnectionCookie = NULL;
 
 2199  BYTE* PredecessorChannelCookie = NULL;
 
 2200  BYTE* SuccessorChannelCookie = NULL;
 
 2207  connection = rpc->VirtualConnection;
 
 2208  WINPR_ASSERT(connection);
 
 2210  outChannel = connection->DefaultOutChannel;
 
 2211  WINPR_ASSERT(outChannel);
 
 2213  nextOutChannel = connection->NonDefaultOutChannel;
 
 2214  WINPR_ASSERT(nextOutChannel);
 
 2216  header.header.frag_length = 96;
 
 2217  header.Flags = RTS_FLAG_RECYCLE_CHANNEL;
 
 2218  header.NumberOfCommands = 5;
 
 2220  WLog_DBG(TAG, 
"Sending OUT_R1/A3 RTS PDU");
 
 2222  VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
 
 2223  PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie);
 
 2224  SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
 
 2225  ReceiveWindowSize = outChannel->ReceiveWindow;
 
 2226  buffer = Stream_New(NULL, header.header.frag_length);
 
 2231  if (!rts_write_pdu_header(buffer, &header)) 
 
 2233  if (!rts_version_command_write(buffer)) 
 
 2235  if (!rts_cookie_command_write(buffer,
 
 2236                                VirtualConnectionCookie)) 
 
 2238  if (!rts_cookie_command_write(
 
 2239          buffer, PredecessorChannelCookie)) 
 
 2241  if (!rts_cookie_command_write(buffer,
 
 2242                                SuccessorChannelCookie)) 
 
 2244  if (!rts_receive_window_size_command_write(buffer,
 
 2248  status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
 
 2250  Stream_Free(buffer, TRUE);
 
 2254static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, 
wStream* buffer)
 
 2257  UINT32 Destination = 0;
 
 2260  WINPR_ASSERT(buffer);
 
 2262  connection = rpc->VirtualConnection;
 
 2263  WINPR_ASSERT(connection);
 
 2265  WLog_DBG(TAG, 
"Receiving OUT R1/A2 RTS PDU");
 
 2267  status = rts_destination_command_read(rpc, buffer, &Destination);
 
 2271  connection->NonDefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
 
 2273  if (!connection->NonDefaultOutChannel)
 
 2276  status = rpc_out_channel_replacement_connect(connection->NonDefaultOutChannel, 5000);
 
 2280    WLog_ERR(TAG, 
"rpc_out_channel_replacement_connect failure");
 
 2284  rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
 
 2285                                      CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
 
 2289static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED 
wStream* buffer)
 
 2295  WINPR_ASSERT(buffer);
 
 2297  connection = rpc->VirtualConnection;
 
 2298  WINPR_ASSERT(connection);
 
 2300  WLog_DBG(TAG, 
"Receiving OUT R2/A6 RTS PDU");
 
 2301  status = rts_send_OUT_R2_C1_pdu(rpc);
 
 2305    WLog_ERR(TAG, 
"rts_send_OUT_R2_C1_pdu failure");
 
 2309  status = rts_send_OUT_R2_A7_pdu(rpc);
 
 2313    WLog_ERR(TAG, 
"rts_send_OUT_R2_A7_pdu failure");
 
 2317  rpc_out_channel_transition_to_state(connection->NonDefaultOutChannel,
 
 2318                                      CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
 
 2319  rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
 
 2320                                      CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
 
 2324static int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED 
wStream* buffer)
 
 2329  WINPR_ASSERT(buffer);
 
 2331  connection = rpc->VirtualConnection;
 
 2332  WINPR_ASSERT(connection);
 
 2334  WLog_DBG(TAG, 
"Receiving OUT R2/B3 RTS PDU");
 
 2335  rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
 
 2336                                      CLIENT_OUT_CHANNEL_STATE_RECYCLED);
 
 2342  BOOL status = FALSE;
 
 2348  WINPR_ASSERT(buffer);
 
 2349  WINPR_ASSERT(header);
 
 2351  wLog* log = WLog_Get(TAG);
 
 2353  const size_t total = Stream_Length(buffer);
 
 2354  length = header->common.frag_length;
 
 2357    WLog_Print(log, WLOG_ERROR, 
"PDU length %" PRIuz 
" does not match available data %" PRIuz,
 
 2362  connection = rpc->VirtualConnection;
 
 2366    WLog_Print(log, WLOG_ERROR, 
"not connected, aborting");
 
 2370  if (!rts_extract_pdu_signature(&signature, buffer, header))
 
 2373  rts_print_pdu_signature(log, WLOG_TRACE, &signature);
 
 2375  if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, 
sizeof(signature)) == 0)
 
 2377    status = rts_recv_flow_control_ack_pdu(rpc, buffer);
 
 2379  else if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE,
 
 2380                  sizeof(signature)) == 0)
 
 2382    status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer);
 
 2384  else if (memcmp(&signature, &RTS_PDU_PING_SIGNATURE, 
sizeof(signature)) == 0)
 
 2386    status = rts_send_ping_pdu(rpc);
 
 2390    if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
 
 2392      if (memcmp(&signature, &RTS_PDU_OUT_R1_A2_SIGNATURE, 
sizeof(signature)) == 0)
 
 2394        status = rts_recv_OUT_R1_A2_pdu(rpc, buffer);
 
 2397    else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_A6W)
 
 2399      if (memcmp(&signature, &RTS_PDU_OUT_R2_A6_SIGNATURE, 
sizeof(signature)) == 0)
 
 2401        status = rts_recv_OUT_R2_A6_pdu(rpc, buffer);
 
 2404    else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_B3W)
 
 2406      if (memcmp(&signature, &RTS_PDU_OUT_R2_B3_SIGNATURE, 
sizeof(signature)) == 0)
 
 2408        status = rts_recv_OUT_R2_B3_pdu(rpc, buffer);
 
 2415    const UINT32 SignatureId = rts_identify_pdu_signature(&signature, NULL);
 
 2416    WLog_Print(log, WLOG_ERROR, 
"error parsing RTS PDU with signature id: 0x%08" PRIX32 
"",
 
 2418    rts_print_pdu_signature(log, WLOG_ERROR, &signature);
 
 2421  const size_t rem = Stream_GetRemainingLength(buffer);
 
 2424    WLog_Print(log, WLOG_ERROR, 
"%" PRIuz 
" bytes or %" PRIuz 
" total not parsed, aborting",
 
 2426    rts_print_pdu_signature(log, WLOG_ERROR, &signature);
 
 2438  if (!rts_write_common_pdu_header(s, &auth->header))
 
 2441  if (!Stream_EnsureRemainingCapacity(s, 2 * 
sizeof(UINT16)))
 
 2444  Stream_Write_UINT16(s, auth->max_xmit_frag);
 
 2445  Stream_Write_UINT16(s, auth->max_recv_frag);
 
 2447  return rts_write_auth_verifier(s, &auth->auth_verifier, &auth->header);
 
 2456  if (!rts_write_common_pdu_header(s, &bind->header))
 
 2459  if (!Stream_EnsureRemainingCapacity(s, 8))
 
 2462  Stream_Write_UINT16(s, bind->max_xmit_frag);
 
 2463  Stream_Write_UINT16(s, bind->max_recv_frag);
 
 2464  Stream_Write_UINT32(s, bind->assoc_group_id);
 
 2466  if (!rts_write_context_list(s, &bind->p_context_elem))
 
 2469  return rts_write_auth_verifier(s, &bind->auth_verifier, &bind->header);
 
 2472BOOL rts_conditional_check_and_log(
const char* tag, 
wStream* s, 
size_t size, BOOL silent,
 
 2473                                   const char* fkt, 
const char* file, 
size_t line)
 
 2477    const size_t rem = Stream_GetRemainingLength(s);
 
 2483  return Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, size, 1, 
"%s(%s:%" PRIuz 
")", fkt,
 
 2487BOOL rts_conditional_safe_seek(
wStream* s, 
size_t size, BOOL silent, 
const char* fkt,
 
 2488                               const char* file, 
size_t line)
 
 2492    const size_t rem = Stream_GetRemainingLength(s);
 
 2496  return Stream_SafeSeekEx(s, size, file, line, fkt);