20#include <freerdp/config.h> 
   22#include <freerdp/log.h> 
   25#include <winpr/wtypes.h> 
   26#include <winpr/assert.h> 
   27#include <winpr/cast.h> 
   28#include <winpr/print.h> 
   29#include <winpr/synch.h> 
   30#include <winpr/thread.h> 
   31#include <winpr/stream.h> 
   34#include "ncacn_http.h" 
   38#include "rpc_client.h" 
   39#include "rts_signature.h" 
   45#define TAG FREERDP_TAG("core.gateway.rpc") 
   47static const char* rpc_client_state_str(RPC_CLIENT_STATE state)
 
   50  const char* str = 
"RPC_CLIENT_STATE_UNKNOWN";
 
   54    case RPC_CLIENT_STATE_INITIAL:
 
   55      str = 
"RPC_CLIENT_STATE_INITIAL";
 
   58    case RPC_CLIENT_STATE_ESTABLISHED:
 
   59      str = 
"RPC_CLIENT_STATE_ESTABLISHED";
 
   62    case RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK:
 
   63      str = 
"RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK";
 
   66    case RPC_CLIENT_STATE_WAIT_UNSECURE_BIND_ACK:
 
   67      str = 
"RPC_CLIENT_STATE_WAIT_UNSECURE_BIND_ACK";
 
   70    case RPC_CLIENT_STATE_WAIT_SECURE_ALTER_CONTEXT_RESPONSE:
 
   71      str = 
"RPC_CLIENT_STATE_WAIT_SECURE_ALTER_CONTEXT_RESPONSE";
 
   74    case RPC_CLIENT_STATE_CONTEXT_NEGOTIATED:
 
   75      str = 
"RPC_CLIENT_STATE_CONTEXT_NEGOTIATED";
 
   78    case RPC_CLIENT_STATE_WAIT_RESPONSE:
 
   79      str = 
"RPC_CLIENT_STATE_WAIT_RESPONSE";
 
   82    case RPC_CLIENT_STATE_FINAL:
 
   83      str = 
"RPC_CLIENT_STATE_FINAL";
 
   91static void rpc_pdu_reset(
RPC_PDU* pdu)
 
   96  Stream_SetPosition(pdu->s, 0);
 
   97  Stream_SetLength(pdu->s, 0);
 
  100static RPC_PDU* rpc_pdu_new(
void)
 
  108  pdu->s = Stream_New(NULL, 4096);
 
  120static void rpc_pdu_free(
RPC_PDU* pdu)
 
  125  Stream_Free(pdu->s, TRUE);
 
  129static int rpc_client_receive_pipe_write(
RpcClient* client, 
const BYTE* buffer, 
size_t length)
 
  133  if (!client || !buffer)
 
  136  EnterCriticalSection(&(client->PipeLock));
 
  138  if (ringbuffer_write(&(client->ReceivePipe), buffer, length))
 
  139    status += (int)length;
 
  141  if (ringbuffer_used(&(client->ReceivePipe)) > 0)
 
  142    (
void)SetEvent(client->PipeEvent);
 
  144  LeaveCriticalSection(&(client->PipeLock));
 
  148int rpc_client_receive_pipe_read(
RpcClient* client, BYTE* buffer, 
size_t length)
 
  154  if (!client || !buffer)
 
  157  EnterCriticalSection(&(client->PipeLock));
 
  158  nchunks = ringbuffer_peek(&(client->ReceivePipe), chunks, length);
 
  160  for (
int index = 0; index < nchunks; index++)
 
  162    CopyMemory(&buffer[status], chunks[index].data, chunks[index].size);
 
  163    status += chunks[index].size;
 
  167    ringbuffer_commit_read_bytes(&(client->ReceivePipe), status);
 
  169  if (ringbuffer_used(&(client->ReceivePipe)) < 1)
 
  170    (void)ResetEvent(client->PipeEvent);
 
  172  LeaveCriticalSection(&(client->PipeLock));
 
  174  if (status > INT_MAX)
 
  179static int rpc_client_transition_to_state(rdpRpc* rpc, RPC_CLIENT_STATE state)
 
  184  WLog_DBG(TAG, 
"%s", rpc_client_state_str(state));
 
  188static int rpc_client_recv_pdu_int(rdpRpc* rpc, 
RPC_PDU* pdu)
 
  196  rdpTsg* tsg = transport_get_tsg(rpc->transport);
 
  198  WLog_Print(rpc->log, WLOG_TRACE, 
"client state %s, vc state %s",
 
  199             rpc_client_state_str(rpc->State), rpc_vc_state_str(rpc->VirtualConnection->State));
 
  201  const BOOL rc = rts_match_pdu_signature_ex(&RTS_PDU_PING_SIGNATURE, pdu->s, NULL, &found, TRUE);
 
  202  rts_print_pdu_signature(rpc->log, WLOG_TRACE, &found);
 
  204    return rts_recv_ping_pdu(rpc, pdu->s);
 
  206  if (rpc->VirtualConnection->State < VIRTUAL_CONNECTION_STATE_OPENED)
 
  208    switch (rpc->VirtualConnection->State)
 
  210      case VIRTUAL_CONNECTION_STATE_INITIAL:
 
  213      case VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT:
 
  216      case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
 
  217        if (memcmp(&found, &RTS_PDU_CONN_A3_SIGNATURE, 
sizeof(found)) != 0)
 
  219          WLog_Print(rpc->log, WLOG_ERROR, 
"unexpected RTS PDU: Expected CONN/A3");
 
  220          rts_print_pdu_signature(rpc->log, WLOG_ERROR, &found);
 
  224        if (!rts_recv_CONN_A3_pdu(rpc, pdu->s))
 
  226          WLog_Print(rpc->log, WLOG_ERROR, 
"rts_recv_CONN_A3_pdu failure");
 
  230        rpc_virtual_connection_transition_to_state(rpc, rpc->VirtualConnection,
 
  231                                                   VIRTUAL_CONNECTION_STATE_WAIT_C2);
 
  235      case VIRTUAL_CONNECTION_STATE_WAIT_C2:
 
  236        if (memcmp(&found, &RTS_PDU_CONN_C2_SIGNATURE, 
sizeof(found)) != 0)
 
  238          WLog_Print(rpc->log, WLOG_ERROR, 
"unexpected RTS PDU: Expected CONN/C2");
 
  239          rts_print_pdu_signature(rpc->log, WLOG_ERROR, &found);
 
  243        if (!rts_recv_CONN_C2_pdu(rpc, pdu->s))
 
  245          WLog_Print(rpc->log, WLOG_ERROR, 
"rts_recv_CONN_C2_pdu failure");
 
  249        rpc_virtual_connection_transition_to_state(rpc, rpc->VirtualConnection,
 
  250                                                   VIRTUAL_CONNECTION_STATE_OPENED);
 
  251        rpc_client_transition_to_state(rpc, RPC_CLIENT_STATE_ESTABLISHED);
 
  253        if (rpc_send_bind_pdu(rpc, TRUE) < 0)
 
  255          WLog_Print(rpc->log, WLOG_ERROR, 
"rpc_send_bind_pdu failure");
 
  259        rpc_client_transition_to_state(rpc, RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK);
 
  263      case VIRTUAL_CONNECTION_STATE_OPENED:
 
  266      case VIRTUAL_CONNECTION_STATE_FINAL:
 
  272  else if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
 
  274    if (rpc->State == RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK)
 
  276      if (pdu->Type == PTYPE_BIND_ACK || pdu->Type == PTYPE_ALTER_CONTEXT_RESP)
 
  278        if (!rpc_recv_bind_ack_pdu(rpc, pdu->s))
 
  280          WLog_Print(rpc->log, WLOG_ERROR, 
"rpc_recv_bind_ack_pdu failure");
 
  286        WLog_Print(rpc->log, WLOG_ERROR,
 
  287                   "RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK unexpected pdu type: 0x%08" PRIX32
 
  293      switch (rpc_bind_state(rpc))
 
  295        case RPC_BIND_STATE_INCOMPLETE:
 
  296          if (rpc_send_bind_pdu(rpc, FALSE) < 0)
 
  298            WLog_Print(rpc->log, WLOG_ERROR, 
"rpc_send_bind_pdu failure");
 
  302        case RPC_BIND_STATE_LAST_LEG:
 
  303          if (rpc_send_rpc_auth_3_pdu(rpc) < 0)
 
  305            WLog_Print(rpc->log, WLOG_ERROR,
 
  306                       "rpc_secure_bind: error sending rpc_auth_3 pdu!");
 
  311        case RPC_BIND_STATE_COMPLETE:
 
  312          rpc_client_transition_to_state(rpc, RPC_CLIENT_STATE_CONTEXT_NEGOTIATED);
 
  314          if (!tsg_proxy_begin(tsg))
 
  316            WLog_Print(rpc->log, WLOG_ERROR, 
"tsg_proxy_begin failure");
 
  328      WLog_Print(rpc->log, WLOG_ERROR, 
"invalid rpc->State: %u", rpc->State);
 
  331  else if (rpc->State >= RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
 
  333    if (!tsg_recv_pdu(tsg, pdu))
 
  342static int rpc_client_recv_pdu(rdpRpc* rpc, 
RPC_PDU* pdu)
 
  347  Stream_SealLength(pdu->s);
 
  348  Stream_SetPosition(pdu->s, 0);
 
  350  const size_t before = Stream_GetRemainingLength(pdu->s);
 
  351  WLog_Print(rpc->log, WLOG_TRACE, 
"RPC PDU parsing %" PRIuz 
" bytes", before);
 
  352  const int rc = rpc_client_recv_pdu_int(rpc, pdu);
 
  355  const size_t after = Stream_GetRemainingLength(pdu->s);
 
  359    WLog_Print(rpc->log, WLOG_WARN, 
"Incompletely parsed RPC PDU (%" PRIuz 
" bytes remain)",
 
  366static int rpc_client_recv_fragment(rdpRpc* rpc, 
wStream* fragment)
 
  370  size_t StubOffset = 0;
 
  371  size_t StubLength = 0;
 
  376  WINPR_ASSERT(rpc->client);
 
  377  WINPR_ASSERT(fragment);
 
  379  pdu = rpc->client->pdu;
 
  382  Stream_SealLength(fragment);
 
  383  Stream_SetPosition(fragment, 0);
 
  385  if (!rts_read_pdu_header(fragment, &header))
 
  388  if (header.common.ptype == PTYPE_RESPONSE)
 
  390    rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header.common.frag_length;
 
  391    rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -=
 
  392        header.common.frag_length;
 
  394    if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow <
 
  395        (rpc->ReceiveWindow / 2))
 
  397      if (!rts_send_flow_control_ack_pdu(rpc))
 
  401    if (!rpc_get_stub_data_info(rpc, &header, &StubOffset, &StubLength))
 
  403      WLog_ERR(TAG, 
"expected stub");
 
  409      if ((header.common.call_id == rpc->PipeCallId) &&
 
  410          (header.common.pfc_flags & PFC_LAST_FRAG))
 
  413        TerminateEventArgs e;
 
  414        rdpContext* context = transport_get_context(rpc->transport);
 
  415        rdpTsg* tsg = transport_get_tsg(rpc->transport);
 
  417        WINPR_ASSERT(context);
 
  419        if (Stream_Length(fragment) < StubOffset + 4)
 
  421        Stream_SetPosition(fragment, StubOffset);
 
  422        Stream_Read_UINT32(fragment, rpc->result);
 
  424        utils_abort_connect(context->rdp);
 
  425        tsg_set_state(tsg, TSG_STATE_TUNNEL_CLOSE_PENDING);
 
  426        EventArgsInit(&e, 
"freerdp");
 
  428        PubSub_OnTerminate(context->rdp->pubSub, context, &e);
 
  433      if (header.common.call_id != rpc->PipeCallId)
 
  441    if (rpc->StubFragCount == 0)
 
  442      rpc->StubCallId = header.common.call_id;
 
  444    if (rpc->StubCallId != header.common.call_id)
 
  447               "invalid call_id: actual: %" PRIu32 
", expected: %" PRIu32
 
  448               ", frag_count: %" PRIu32 
"",
 
  449               rpc->StubCallId, header.common.call_id, rpc->StubFragCount);
 
  452    call = rpc_client_call_find_by_id(rpc->client, rpc->StubCallId);
 
  457    if (call->OpNum != TsProxySetupReceivePipeOpnum)
 
  461      if (!Stream_EnsureCapacity(pdu->s, response->alloc_hint))
 
  464      if (Stream_Length(fragment) < StubOffset + StubLength)
 
  467      Stream_SetPosition(fragment, StubOffset);
 
  468      Stream_Write(pdu->s, Stream_ConstPointer(fragment), StubLength);
 
  469      rpc->StubFragCount++;
 
  471      if (response->alloc_hint == StubLength)
 
  473        pdu->Flags = RPC_PDU_FLAG_STUB;
 
  474        pdu->Type = PTYPE_RESPONSE;
 
  475        pdu->CallId = rpc->StubCallId;
 
  477        if (rpc_client_recv_pdu(rpc, pdu) < 0)
 
  480        rpc->StubFragCount = 0;
 
  487      if (Stream_Length(fragment) < StubOffset + StubLength)
 
  489      Stream_SetPosition(fragment, StubOffset);
 
  490      rpc_client_receive_pipe_write(rpc->client, Stream_ConstPointer(fragment), StubLength);
 
  491      rpc->StubFragCount++;
 
  493      if (response->alloc_hint == StubLength)
 
  495        rpc->StubFragCount = 0;
 
  502  else if (header.common.ptype == PTYPE_RTS)
 
  504    if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
 
  507      pdu->Type = header.common.ptype;
 
  508      pdu->CallId = header.common.call_id;
 
  510      const size_t len = Stream_Length(fragment);
 
  511      if (!Stream_EnsureCapacity(pdu->s, len))
 
  514      Stream_Write(pdu->s, Stream_Buffer(fragment), len);
 
  516      if (rpc_client_recv_pdu(rpc, pdu) < 0)
 
  523      if (!rts_recv_out_of_sequence_pdu(rpc, fragment, &header))
 
  529  else if (header.common.ptype == PTYPE_BIND_ACK ||
 
  530           header.common.ptype == PTYPE_ALTER_CONTEXT_RESP)
 
  533    pdu->Type = header.common.ptype;
 
  534    pdu->CallId = header.common.call_id;
 
  536    const size_t len = Stream_Length(fragment);
 
  537    if (!Stream_EnsureCapacity(pdu->s, len))
 
  540    Stream_Write(pdu->s, Stream_Buffer(fragment), len);
 
  542    if (rpc_client_recv_pdu(rpc, pdu) < 0)
 
  548  else if (header.common.ptype == PTYPE_FAULT)
 
  551    rpc_recv_fault_pdu(fault->status);
 
  556    WLog_ERR(TAG, 
"unexpected RPC PDU type 0x%02" PRIX8 
"", header.common.ptype);
 
  561  rc = (rc < 0) ? 1 : 0; 
 
  564  rts_free_pdu_header(&header, FALSE);
 
  568static SSIZE_T rpc_client_default_out_channel_recv(rdpRpc* rpc)
 
  571  HttpResponse* response = NULL;
 
  574  HANDLE outChannelEvent = NULL;
 
  576  inChannel = connection->DefaultInChannel;
 
  577  outChannel = connection->DefaultOutChannel;
 
  578  BIO_get_event(outChannel->common.tls->bio, &outChannelEvent);
 
  580  if (outChannel->State < CLIENT_OUT_CHANNEL_STATE_OPENED)
 
  582    if (WaitForSingleObject(outChannelEvent, 0) != WAIT_OBJECT_0)
 
  585    response = http_response_recv(outChannel->common.tls, TRUE);
 
  590    if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_SECURITY)
 
  593      if (!rpc_ncacn_http_recv_out_channel_response(&outChannel->common, response))
 
  595        http_response_free(response);
 
  596        WLog_ERR(TAG, 
"rpc_ncacn_http_recv_out_channel_response failure");
 
  602      if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
 
  604        http_response_free(response);
 
  605        WLog_ERR(TAG, 
"rpc_ncacn_http_send_out_channel_request failure");
 
  609      if (rpc_ncacn_http_is_final_request(&outChannel->common))
 
  611        rpc_ncacn_http_auth_uninit(&outChannel->common);
 
  612        rpc_out_channel_transition_to_state(outChannel,
 
  613                                            CLIENT_OUT_CHANNEL_STATE_NEGOTIATED);
 
  617        if (!rts_send_CONN_A1_pdu(rpc))
 
  619          http_response_free(response);
 
  620          WLog_ERR(TAG, 
"rpc_send_CONN_A1_pdu error!");
 
  624        rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_OPENED);
 
  626        if (inChannel->State == CLIENT_IN_CHANNEL_STATE_OPENED)
 
  628          rpc_virtual_connection_transition_to_state(
 
  629              rpc, connection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
 
  636    http_response_free(response);
 
  638  else if (connection->State == VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT)
 
  641    if (WaitForSingleObject(outChannelEvent, 0) != WAIT_OBJECT_0)
 
  644    response = http_response_recv(outChannel->common.tls, FALSE);
 
  649    const UINT16 statusCode = http_response_get_status_code(response);
 
  650    if (statusCode != HTTP_STATUS_OK)
 
  652      http_response_log_error_status(WLog_Get(TAG), WLOG_ERROR, response);
 
  654      if (statusCode == HTTP_STATUS_DENIED)
 
  656        rdpContext* context = transport_get_context(rpc->transport);
 
  657        freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
 
  660      http_response_free(response);
 
  664    http_response_free(response);
 
  665    rpc_virtual_connection_transition_to_state(rpc, rpc->VirtualConnection,
 
  666                                               VIRTUAL_CONNECTION_STATE_WAIT_A3W);
 
  671    wStream* fragment = rpc->client->ReceiveFragment;
 
  678      while (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
 
  680        status = rpc_channel_read(&outChannel->common, fragment,
 
  681                                  RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(fragment));
 
  686        if (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
 
  690      pos = Stream_GetPosition(fragment);
 
  691      Stream_SetPosition(fragment, 0);
 
  694      rts_read_common_pdu_header(fragment, &header, TRUE);
 
  695      Stream_SetPosition(fragment, pos);
 
  697      if (header.frag_length > rpc->max_recv_frag)
 
  700                 "rpc_client_recv: invalid fragment size: %" PRIu16 
" (max: %" PRIu16 
")",
 
  701                 header.frag_length, rpc->max_recv_frag);
 
  702        winpr_HexDump(TAG, WLOG_ERROR, Stream_Buffer(fragment),
 
  703                      Stream_GetPosition(fragment));
 
  707      while (Stream_GetPosition(fragment) < header.frag_length)
 
  709        status = rpc_channel_read(&outChannel->common, fragment,
 
  710                                  header.frag_length - Stream_GetPosition(fragment));
 
  714          WLog_ERR(TAG, 
"error reading fragment body");
 
  718        if (Stream_GetPosition(fragment) < header.frag_length)
 
  724        status = rpc_client_recv_fragment(rpc, fragment);
 
  730        if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_RECYCLED &&
 
  731            connection->NonDefaultOutChannel)
 
  733          rpc_channel_free(&connection->DefaultOutChannel->common);
 
  734          connection->DefaultOutChannel = connection->NonDefaultOutChannel;
 
  735          connection->NonDefaultOutChannel = NULL;
 
  736          rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
 
  737                                              CLIENT_OUT_CHANNEL_STATE_OPENED);
 
  738          rpc_virtual_connection_transition_to_state(
 
  739              rpc, connection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
 
  743        Stream_SetPosition(fragment, 0);
 
  751static SSIZE_T rpc_client_nondefault_out_channel_recv(rdpRpc* rpc)
 
  754  HttpResponse* response = NULL;
 
  756  HANDLE nextOutChannelEvent = NULL;
 
  757  nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
 
  758  BIO_get_event(nextOutChannel->common.tls->bio, &nextOutChannelEvent);
 
  760  if (WaitForSingleObject(nextOutChannelEvent, 0) != WAIT_OBJECT_0)
 
  763  response = http_response_recv(nextOutChannel->common.tls, TRUE);
 
  767    switch (nextOutChannel->State)
 
  769      case CLIENT_OUT_CHANNEL_STATE_SECURITY:
 
  770        if (rpc_ncacn_http_recv_out_channel_response(&nextOutChannel->common, response))
 
  772          if (rpc_ncacn_http_send_out_channel_request(&nextOutChannel->common, TRUE))
 
  774            if (rpc_ncacn_http_is_final_request(&nextOutChannel->common))
 
  776              rpc_ncacn_http_auth_uninit(&nextOutChannel->common);
 
  778              if (rts_send_OUT_R1_A3_pdu(rpc))
 
  781                rpc_out_channel_transition_to_state(
 
  782                    nextOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
 
  786                WLog_ERR(TAG, 
"rts_send_OUT_R1/A3_pdu failure");
 
  796            WLog_ERR(TAG, 
"rpc_ncacn_http_send_out_channel_request failure");
 
  801          WLog_ERR(TAG, 
"rpc_ncacn_http_recv_out_channel_response failure");
 
  806      case CLIENT_OUT_CHANNEL_STATE_INITIAL:
 
  807      case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
 
  808      case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
 
  811                 "rpc_client_nondefault_out_channel_recv: Unexpected message %08" PRIx32,
 
  812                 nextOutChannel->State);
 
  816    http_response_free(response);
 
  822int rpc_client_out_channel_recv(rdpRpc* rpc)
 
  827  if (connection->DefaultOutChannel)
 
  829    status = rpc_client_default_out_channel_recv(rpc);
 
  835  if (connection->NonDefaultOutChannel)
 
  837    status = rpc_client_nondefault_out_channel_recv(rpc);
 
  846int rpc_client_in_channel_recv(rdpRpc* rpc)
 
  849  HttpResponse* response = NULL;
 
  852  HANDLE InChannelEvent = NULL;
 
  854  inChannel = connection->DefaultInChannel;
 
  855  outChannel = connection->DefaultOutChannel;
 
  856  BIO_get_event(inChannel->common.tls->bio, &InChannelEvent);
 
  858  if (WaitForSingleObject(InChannelEvent, 0) != WAIT_OBJECT_0)
 
  861  if (inChannel->State < CLIENT_IN_CHANNEL_STATE_OPENED)
 
  863    response = http_response_recv(inChannel->common.tls, TRUE);
 
  868    if (inChannel->State == CLIENT_IN_CHANNEL_STATE_SECURITY)
 
  870      if (!rpc_ncacn_http_recv_in_channel_response(&inChannel->common, response))
 
  872        WLog_ERR(TAG, 
"rpc_ncacn_http_recv_in_channel_response failure");
 
  873        http_response_free(response);
 
  879      if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
 
  881        WLog_ERR(TAG, 
"rpc_ncacn_http_send_in_channel_request failure");
 
  882        http_response_free(response);
 
  886      if (rpc_ncacn_http_is_final_request(&inChannel->common))
 
  888        rpc_ncacn_http_auth_uninit(&inChannel->common);
 
  889        rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_NEGOTIATED);
 
  893        if (!rts_send_CONN_B1_pdu(rpc))
 
  895          WLog_ERR(TAG, 
"rpc_send_CONN_B1_pdu error!");
 
  896          http_response_free(response);
 
  900        rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_OPENED);
 
  902        if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
 
  904          rpc_virtual_connection_transition_to_state(
 
  905              rpc, connection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
 
  912    http_response_free(response);
 
  916    response = http_response_recv(inChannel->common.tls, TRUE);
 
  922    http_response_free(response);
 
  940  ArrayList_Lock(client->ClientCallList);
 
  941  const size_t count = ArrayList_Count(client->ClientCallList);
 
  943  for (
size_t index = 0; index < count; index++)
 
  945    clientCall = (
RpcClientCall*)ArrayList_GetItem(client->ClientCallList, index);
 
  947    if (clientCall->CallId == CallId)
 
  951  ArrayList_Unlock(client->ClientCallList);
 
  955RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum)
 
  963  clientCall->CallId = CallId;
 
  964  clientCall->OpNum = OpNum;
 
  965  clientCall->State = RPC_CLIENT_CALL_STATE_SEND_PDUS;
 
  974static void rpc_array_client_call_free(
void* call)
 
  979int rpc_in_channel_send_pdu(
RpcInChannel* inChannel, 
const BYTE* buffer, 
size_t length)
 
  986  status = rpc_channel_write(&inChannel->common, buffer, length);
 
  991  Stream_StaticConstInit(&s, buffer, length);
 
  992  if (!rts_read_common_pdu_header(&s, &header, FALSE))
 
  995  clientCall = rpc_client_call_find_by_id(inChannel->common.client, header.call_id);
 
  999  clientCall->State = RPC_CLIENT_CALL_STATE_DISPATCHED;
 
 1008  if (header.ptype == PTYPE_REQUEST)
 
 1010    const uint32_t ustatus = WINPR_ASSERTING_INT_CAST(uint32_t, status);
 
 1011    inChannel->BytesSent += ustatus;
 
 1012    inChannel->SenderAvailableWindow -= ustatus;
 
 1015  if (status > INT32_MAX)
 
 1020BOOL rpc_client_write_call(rdpRpc* rpc, 
wStream* s, UINT16 opnum)
 
 1023  BYTE* buffer = NULL;
 
 1024  size_t stub_data_pad = 0;
 
 1028  rdpCredsspAuth* auth = NULL;
 
 1041  connection = rpc->VirtualConnection;
 
 1045    WLog_ERR(TAG, 
"invalid auth context");
 
 1052  inChannel = connection->DefaultInChannel;
 
 1057  Stream_SealLength(s);
 
 1058  const size_t length = Stream_Length(s);
 
 1059  if (length > UINT32_MAX)
 
 1062  const size_t asize = credssp_auth_trailer_size(auth);
 
 1064  request_pdu.header = rpc_pdu_header_init(rpc);
 
 1065  request_pdu.header.ptype = PTYPE_REQUEST;
 
 1066  request_pdu.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
 
 1067  request_pdu.header.auth_length = (UINT16)asize;
 
 1068  request_pdu.header.call_id = rpc->CallId++;
 
 1069  request_pdu.alloc_hint = (UINT32)length;
 
 1070  request_pdu.p_cont_id = 0x0000;
 
 1071  request_pdu.opnum = opnum;
 
 1072  clientCall = rpc_client_call_new(request_pdu.header.call_id, request_pdu.opnum);
 
 1077  if (!ArrayList_Append(rpc->client->ClientCallList, clientCall))
 
 1079    rpc_client_call_free(clientCall);
 
 1084  if (request_pdu.opnum == TsProxySetupReceivePipeOpnum)
 
 1085    rpc->PipeCallId = request_pdu.header.call_id;
 
 1087  request_pdu.stub_data = Stream_Buffer(s);
 
 1089  stub_data_pad = rpc_offset_align(&offset, 8);
 
 1092  const size_t alg = rpc_offset_align(&offset, 4);
 
 1093  WINPR_ASSERT(alg <= UINT8_MAX);
 
 1094  request_pdu.auth_verifier.auth_pad_length = (UINT8)alg;
 
 1095  request_pdu.auth_verifier.auth_type =
 
 1096      rpc_auth_pkg_to_security_provider(credssp_auth_pkg_name(rpc->auth));
 
 1097  request_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
 
 1098  request_pdu.auth_verifier.auth_reserved = 0x00;
 
 1099  request_pdu.auth_verifier.auth_context_id = 0x00000000;
 
 1100  offset += (8 + request_pdu.header.auth_length);
 
 1102  if (offset > UINT16_MAX)
 
 1104  request_pdu.header.frag_length = (UINT16)offset;
 
 1105  buffer = (BYTE*)calloc(1, request_pdu.header.frag_length);
 
 1110  CopyMemory(buffer, &request_pdu, 24);
 
 1112  rpc_offset_pad(&offset, stub_data_pad);
 
 1113  CopyMemory(&buffer[offset], request_pdu.stub_data, length);
 
 1115  rpc_offset_pad(&offset, request_pdu.auth_verifier.auth_pad_length);
 
 1116  CopyMemory(&buffer[offset], &request_pdu.auth_verifier.auth_type, 8);
 
 1119  if (offset > request_pdu.header.frag_length)
 
 1122  plaintext.pvBuffer = buffer;
 
 1123  plaintext.cbBuffer = (UINT32)offset;
 
 1124  plaintext.BufferType = SECBUFFER_READONLY;
 
 1127  if (!credssp_auth_encrypt(auth, &plaintext, &ciphertext, &size, rpc->SendSeqNum++))
 
 1130  if (offset + size > request_pdu.header.frag_length)
 
 1132    sspi_SecBufferFree(&ciphertext);
 
 1136  CopyMemory(&buffer[offset], ciphertext.pvBuffer, size);
 
 1139  sspi_SecBufferFree(&ciphertext);
 
 1141  if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu.header.frag_length) < 0)
 
 1147  Stream_Free(s, TRUE);
 
 1151static BOOL rpc_client_resolve_gateway(rdpSettings* settings, 
char** host, UINT16* port,
 
 1154  struct addrinfo* result = NULL;
 
 1156  if (!settings || !host || !port || !isProxy)
 
 1164    *isProxy = proxy_prepare(settings, &peerHostname, port, &proxyUsername, &proxyPassword);
 
 1165    result = freerdp_tcp_resolve_host(peerHostname, *port, 0);
 
 1171        freerdp_tcp_address_to_string((
const struct sockaddr_storage*)result->ai_addr, NULL);
 
 1172    freeaddrinfo(result);
 
 1177RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag)
 
 1185  if (!rpc_client_resolve_gateway(context->settings, &client->host, &client->port,
 
 1189  client->context = context;
 
 1191  if (!client->context)
 
 1194  client->pdu = rpc_pdu_new();
 
 1199  client->ReceiveFragment = Stream_New(NULL, max_recv_frag);
 
 1201  if (!client->ReceiveFragment)
 
 1204  client->PipeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 
 1206  if (!client->PipeEvent)
 
 1209  if (!ringbuffer_init(&(client->ReceivePipe), 4096))
 
 1212  if (!InitializeCriticalSectionAndSpinCount(&(client->PipeLock), 4000))
 
 1215  client->ClientCallList = ArrayList_New(TRUE);
 
 1217  if (!client->ClientCallList)
 
 1220  obj = ArrayList_Object(client->ClientCallList);
 
 1221  obj->fnObjectFree = rpc_array_client_call_free;
 
 1224  WINPR_PRAGMA_DIAG_PUSH
 
 1225  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
 
 1226  rpc_client_free(client);
 
 1227  WINPR_PRAGMA_DIAG_POP
 
 1238  if (client->ReceiveFragment)
 
 1239    Stream_Free(client->ReceiveFragment, TRUE);
 
 1241  if (client->PipeEvent)
 
 1242    (void)CloseHandle(client->PipeEvent);
 
 1244  ringbuffer_destroy(&(client->ReceivePipe));
 
 1245  DeleteCriticalSection(&(client->PipeLock));
 
 1248    rpc_pdu_free(client->pdu);
 
 1250  if (client->ClientCallList)
 
 1251    ArrayList_Free(client->ClientCallList);
 
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
 
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
 
a piece of data in the ring buffer, exactly like a glibc iovec
 
This struct contains function pointer to initialize/free objects.