20#include <winpr/assert.h> 
   21#include <winpr/stream.h> 
   23#include <freerdp/log.h> 
   25#include "rts_signature.h" 
   27#define TAG FREERDP_TAG("core.gateway.rts") 
   32  { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0 }
 
   34const RtsPduSignature RTS_PDU_CONN_A2_SIGNATURE = { RTS_FLAG_OUT_CHANNEL,
 
   36                                                  { RTS_CMD_VERSION, RTS_CMD_COOKIE,
 
   37                                                    RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME,
 
   38                                                    RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 } };
 
   40  RTS_FLAG_NONE, 1, { RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0, 0, 0 }
 
   46  { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME,
 
   47    RTS_CMD_CLIENT_KEEPALIVE, RTS_CMD_ASSOCIATION_GROUP_ID, 0, 0 }
 
   52  { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE,
 
   53    RTS_CMD_CONNECTION_TIMEOUT, RTS_CMD_ASSOCIATION_GROUP_ID, RTS_CMD_CLIENT_ADDRESS, 0 }
 
   56  RTS_FLAG_NONE, 2, { RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_VERSION, 0, 0, 0, 0, 0, 0 }
 
   61                                                  { RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE,
 
   62                                                    RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } };
 
   65                                                  { RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE,
 
   66                                                    RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } };
 
   69  RTS_FLAG_RECYCLE_CHANNEL,
 
   71  { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 }
 
   76  { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE,
 
   77    RTS_CMD_CONNECTION_TIMEOUT, 0, 0 }
 
   81                                                   { RTS_CMD_DESTINATION, RTS_CMD_VERSION,
 
   82                                                     RTS_CMD_RECEIVE_WINDOW_SIZE,
 
   83                                                     RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0 } };
 
   86                                                   { RTS_CMD_DESTINATION, RTS_CMD_VERSION,
 
   87                                                     RTS_CMD_RECEIVE_WINDOW_SIZE,
 
   88                                                     RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0 } };
 
   91                                                   { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
 
   94                                                   { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
 
   98                                                   { RTS_CMD_EMPTY, 0, 0, 0, 0, 0, 0, 0 } };
 
  100  RTS_FLAG_NONE, 1, { RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0, 0, 0, 0 }
 
  104  RTS_FLAG_RECYCLE_CHANNEL,
 
  106  { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 }
 
  110                                                   { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
 
  113                                                   { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } };
 
  116                                                   { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } };
 
  119                                                   { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
 
  122  RTS_FLAG_RECYCLE_CHANNEL, 1, { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
 
  125  RTS_FLAG_RECYCLE_CHANNEL, 1, { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
 
  127const RtsPduSignature RTS_PDU_OUT_R1_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL,
 
  129                                                    { RTS_CMD_VERSION, RTS_CMD_COOKIE,
 
  130                                                      RTS_CMD_COOKIE, RTS_CMD_COOKIE,
 
  131                                                      RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 } };
 
  133  RTS_FLAG_RECYCLE_CHANNEL | RTS_FLAG_OUT_CHANNEL,
 
  135  { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME,
 
  136    RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0 }
 
  139  RTS_FLAG_OUT_CHANNEL,
 
  141  { RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 }
 
  144  RTS_FLAG_OUT_CHANNEL,
 
  146  { RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 }
 
  149  RTS_FLAG_OUT_CHANNEL, 2, { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 }
 
  152  RTS_FLAG_OUT_CHANNEL, 2, { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 }
 
  156                                                    { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
 
  159                                                     { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
 
  162                                                     { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
 
  165  RTS_FLAG_RECYCLE_CHANNEL, 1, { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
 
  168  RTS_FLAG_RECYCLE_CHANNEL, 1, { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
 
  170const RtsPduSignature RTS_PDU_OUT_R2_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL,
 
  172                                                    { RTS_CMD_VERSION, RTS_CMD_COOKIE,
 
  173                                                      RTS_CMD_COOKIE, RTS_CMD_COOKIE,
 
  174                                                      RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 } };
 
  177                                                    { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
 
  179  RTS_FLAG_NONE, 2, { RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 }
 
  182  RTS_FLAG_NONE, 2, { RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 }
 
  185  RTS_FLAG_NONE, 3, { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, RTS_CMD_VERSION, 0, 0, 0, 0, 0 }
 
  188  RTS_FLAG_OUT_CHANNEL, 2, { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 }
 
  193                                                    { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
 
  195  RTS_FLAG_NONE, 1, { RTS_CMD_NEGATIVE_ANCE, 0, 0, 0, 0, 0, 0, 0 }
 
  199                                                    { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
 
  203                                                    { 0, 0, 0, 0, 0, 0, 0, 0 } };
 
  206  RTS_FLAG_OTHER_CMD, 1, { RTS_CMD_CLIENT_KEEPALIVE, 0, 0, 0, 0, 0, 0, 0 }
 
  209  RTS_FLAG_OTHER_CMD, 1, { RTS_CMD_PING_TRAFFIC_SENT_NOTIFY, 0, 0, 0, 0, 0, 0, 0 }
 
  211const RtsPduSignature RTS_PDU_ECHO_SIGNATURE = { RTS_FLAG_ECHO, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
 
  212const RtsPduSignature RTS_PDU_PING_SIGNATURE = { RTS_FLAG_PING, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
 
  214  RTS_FLAG_OTHER_CMD, 1, { RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0, 0 }
 
  216const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE = {
 
  217  RTS_FLAG_OTHER_CMD, 2, { RTS_CMD_DESTINATION, RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0 }
 
  221  { RTS_PDU_CONN_A1, FALSE, &RTS_PDU_CONN_A1_SIGNATURE, 
"CONN/A1" },
 
  222  { RTS_PDU_CONN_A2, FALSE, &RTS_PDU_CONN_A2_SIGNATURE, 
"CONN/A2" },
 
  223  { RTS_PDU_CONN_A3, TRUE, &RTS_PDU_CONN_A3_SIGNATURE, 
"CONN/A3" },
 
  225  { RTS_PDU_CONN_B1, FALSE, &RTS_PDU_CONN_B1_SIGNATURE, 
"CONN/B1" },
 
  226  { RTS_PDU_CONN_B2, FALSE, &RTS_PDU_CONN_B2_SIGNATURE, 
"CONN/B2" },
 
  227  { RTS_PDU_CONN_B3, FALSE, &RTS_PDU_CONN_B3_SIGNATURE, 
"CONN/B3" },
 
  229  { RTS_PDU_CONN_C1, FALSE, &RTS_PDU_CONN_C1_SIGNATURE, 
"CONN/C1" },
 
  230  { RTS_PDU_CONN_C2, TRUE, &RTS_PDU_CONN_C2_SIGNATURE, 
"CONN/C2" },
 
  232  { RTS_PDU_IN_R1_A1, FALSE, &RTS_PDU_IN_R1_A1_SIGNATURE, 
"IN_R1/A1" },
 
  233  { RTS_PDU_IN_R1_A2, FALSE, &RTS_PDU_IN_R1_A2_SIGNATURE, 
"IN_R1/A2" },
 
  234  { RTS_PDU_IN_R1_A3, FALSE, &RTS_PDU_IN_R1_A3_SIGNATURE, 
"IN_R1/A3" },
 
  235  { RTS_PDU_IN_R1_A4, TRUE, &RTS_PDU_IN_R1_A4_SIGNATURE, 
"IN_R1/A4" },
 
  236  { RTS_PDU_IN_R1_A5, TRUE, &RTS_PDU_IN_R1_A5_SIGNATURE, 
"IN_R1/A5" },
 
  237  { RTS_PDU_IN_R1_A6, FALSE, &RTS_PDU_IN_R1_A6_SIGNATURE, 
"IN_R1/A6" },
 
  239  { RTS_PDU_IN_R1_B1, FALSE, &RTS_PDU_IN_R1_B1_SIGNATURE, 
"IN_R1/B1" },
 
  240  { RTS_PDU_IN_R1_B2, FALSE, &RTS_PDU_IN_R1_B2_SIGNATURE, 
"IN_R1/B2" },
 
  242  { RTS_PDU_IN_R2_A1, FALSE, &RTS_PDU_IN_R2_A1_SIGNATURE, 
"IN_R2/A1" },
 
  243  { RTS_PDU_IN_R2_A2, FALSE, &RTS_PDU_IN_R2_A2_SIGNATURE, 
"IN_R2/A2" },
 
  244  { RTS_PDU_IN_R2_A3, FALSE, &RTS_PDU_IN_R2_A3_SIGNATURE, 
"IN_R2/A3" },
 
  245  { RTS_PDU_IN_R2_A4, TRUE, &RTS_PDU_IN_R2_A4_SIGNATURE, 
"IN_R2/A4" },
 
  246  { RTS_PDU_IN_R2_A5, FALSE, &RTS_PDU_IN_R2_A5_SIGNATURE, 
"IN_R2/A5" },
 
  248  { RTS_PDU_OUT_R1_A1, FALSE, &RTS_PDU_OUT_R1_A1_SIGNATURE, 
"OUT_R1/A1" },
 
  249  { RTS_PDU_OUT_R1_A2, TRUE, &RTS_PDU_OUT_R1_A2_SIGNATURE, 
"OUT_R1/A2" },
 
  250  { RTS_PDU_OUT_R1_A3, FALSE, &RTS_PDU_OUT_R1_A3_SIGNATURE, 
"OUT_R1/A3" },
 
  251  { RTS_PDU_OUT_R1_A4, FALSE, &RTS_PDU_OUT_R1_A4_SIGNATURE, 
"OUT_R1/A4" },
 
  252  { RTS_PDU_OUT_R1_A5, FALSE, &RTS_PDU_OUT_R1_A5_SIGNATURE, 
"OUT_R1/A5" },
 
  253  { RTS_PDU_OUT_R1_A6, TRUE, &RTS_PDU_OUT_R1_A6_SIGNATURE, 
"OUT_R1/A6" },
 
  254  { RTS_PDU_OUT_R1_A7, FALSE, &RTS_PDU_OUT_R1_A7_SIGNATURE, 
"OUT_R1/A7" },
 
  255  { RTS_PDU_OUT_R1_A8, FALSE, &RTS_PDU_OUT_R1_A8_SIGNATURE, 
"OUT_R1/A8" },
 
  256  { RTS_PDU_OUT_R1_A9, FALSE, &RTS_PDU_OUT_R1_A9_SIGNATURE, 
"OUT_R1/A9" },
 
  257  { RTS_PDU_OUT_R1_A10, TRUE, &RTS_PDU_OUT_R1_A10_SIGNATURE, 
"OUT_R1/A10" },
 
  258  { RTS_PDU_OUT_R1_A11, FALSE, &RTS_PDU_OUT_R1_A11_SIGNATURE, 
"OUT_R1/A11" },
 
  260  { RTS_PDU_OUT_R2_A1, FALSE, &RTS_PDU_OUT_R2_A1_SIGNATURE, 
"OUT_R2/A1" },
 
  261  { RTS_PDU_OUT_R2_A2, TRUE, &RTS_PDU_OUT_R2_A2_SIGNATURE, 
"OUT_R2/A2" },
 
  262  { RTS_PDU_OUT_R2_A3, FALSE, &RTS_PDU_OUT_R2_A3_SIGNATURE, 
"OUT_R2/A3" },
 
  263  { RTS_PDU_OUT_R2_A4, FALSE, &RTS_PDU_OUT_R2_A4_SIGNATURE, 
"OUT_R2/A4" },
 
  264  { RTS_PDU_OUT_R2_A5, FALSE, &RTS_PDU_OUT_R2_A5_SIGNATURE, 
"OUT_R2/A5" },
 
  265  { RTS_PDU_OUT_R2_A6, TRUE, &RTS_PDU_OUT_R2_A6_SIGNATURE, 
"OUT_R2/A6" },
 
  266  { RTS_PDU_OUT_R2_A7, FALSE, &RTS_PDU_OUT_R2_A7_SIGNATURE, 
"OUT_R2/A7" },
 
  267  { RTS_PDU_OUT_R2_A8, FALSE, &RTS_PDU_OUT_R2_A8_SIGNATURE, 
"OUT_R2/A8" },
 
  269  { RTS_PDU_OUT_R2_B1, FALSE, &RTS_PDU_OUT_R2_B1_SIGNATURE, 
"OUT_R2/B1" },
 
  270  { RTS_PDU_OUT_R2_B2, FALSE, &RTS_PDU_OUT_R2_B2_SIGNATURE, 
"OUT_R2/B2" },
 
  271  { RTS_PDU_OUT_R2_B3, TRUE, &RTS_PDU_OUT_R2_B3_SIGNATURE, 
"OUT_R2/B3" },
 
  273  { RTS_PDU_OUT_R2_C1, FALSE, &RTS_PDU_OUT_R2_C1_SIGNATURE, 
"OUT_R2/C1" },
 
  275  { RTS_PDU_KEEP_ALIVE, TRUE, &RTS_PDU_KEEP_ALIVE_SIGNATURE, 
"Keep-Alive" },
 
  276  { RTS_PDU_PING_TRAFFIC_SENT_NOTIFY, TRUE, &RTS_PDU_PING_TRAFFIC_SENT_NOTIFY_SIGNATURE,
 
  277    "Ping Traffic Sent Notify" },
 
  278  { RTS_PDU_ECHO, TRUE, &RTS_PDU_ECHO_SIGNATURE, 
"Echo" },
 
  279  { RTS_PDU_PING, TRUE, &RTS_PDU_PING_SIGNATURE, 
"Ping" },
 
  280  { RTS_PDU_FLOW_CONTROL_ACK, TRUE, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, 
"FlowControlAck" },
 
  281  { RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION, TRUE,
 
  282    &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, 
"FlowControlAckWithDestination" }
 
  288  return rts_match_pdu_signature_ex(signature, src, header, NULL, FALSE);
 
  297  WINPR_ASSERT(signature);
 
  300  if (!rts_extract_pdu_signature_ex(&extracted, src, header, silent))
 
  304    *found_signature = extracted;
 
  305  return memcmp(signature, &extracted, 
sizeof(extracted)) == 0;
 
  311  return rts_extract_pdu_signature_ex(signature, src, header, FALSE);
 
  322  WINPR_ASSERT(signature);
 
  325  wStream* s = Stream_StaticInit(&sbuffer, Stream_Pointer(src), Stream_GetRemainingLength(src));
 
  328    if (!rts_read_pdu_header_ex(s, &rheader, silent))
 
  336  signature->Flags = rts->Flags;
 
  337  signature->NumberOfCommands = rts->NumberOfCommands;
 
  339  for (UINT16 i = 0; i < rts->NumberOfCommands; i++)
 
  341    UINT32 CommandType = 0;
 
  342    size_t CommandLength = 0;
 
  344    if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
 
  347    Stream_Read_UINT32(s, CommandType); 
 
  350    if (i < ARRAYSIZE(signature->CommandTypes))
 
  351      signature->CommandTypes[i] = CommandType;
 
  353    if (!rts_command_length(CommandType, s, &CommandLength, silent))
 
  355    if (!Stream_ConditionalSafeSeek(s, CommandLength, silent))
 
  361  rts_free_pdu_header(&rheader, FALSE);
 
  371  for (
size_t i = 0; i < ARRAYSIZE(RTS_PDU_SIGNATURE_TABLE); i++)
 
  376    if (!current->SignatureClient)
 
  379    if (signature->Flags != pSignature->Flags)
 
  382    if (signature->NumberOfCommands != pSignature->NumberOfCommands)
 
  385    for (
size_t j = 0; j < signature->NumberOfCommands; j++)
 
  387      if (signature->CommandTypes[j] != pSignature->CommandTypes[j])
 
  394    return current->SignatureId;
 
  400BOOL rts_print_pdu_signature(wLog* log, DWORD level, 
const RtsPduSignature* signature)
 
  402  UINT32 SignatureId = 0;
 
  408  WLog_Print(log, level,
 
  409             "RTS PDU Signature: Flags: 0x%04" PRIX16 
" NumberOfCommands: %" PRIu16 
"",
 
  410             signature->Flags, signature->NumberOfCommands);
 
  411  SignatureId = rts_identify_pdu_signature(signature, &entry);
 
  414    WLog_Print(log, level, 
"Identified %s RTS PDU", entry->PduName);