FreeRDP
rpc_client.c
1 
20 #include <freerdp/config.h>
21 
22 #include <freerdp/log.h>
23 
24 #include <winpr/crt.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>
32 
33 #include "http.h"
34 #include "ncacn_http.h"
35 
36 #include "rpc_bind.h"
37 #include "rpc_fault.h"
38 #include "rpc_client.h"
39 #include "rts_signature.h"
40 
41 #include "../utils.h"
42 #include "../rdp.h"
43 #include "../proxy.h"
44 
45 #define TAG FREERDP_TAG("core.gateway.rpc")
46 
47 static const char* rpc_client_state_str(RPC_CLIENT_STATE state)
48 {
49  // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
50  const char* str = "RPC_CLIENT_STATE_UNKNOWN";
51 
52  switch (state)
53  {
54  case RPC_CLIENT_STATE_INITIAL:
55  str = "RPC_CLIENT_STATE_INITIAL";
56  break;
57 
58  case RPC_CLIENT_STATE_ESTABLISHED:
59  str = "RPC_CLIENT_STATE_ESTABLISHED";
60  break;
61 
62  case RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK:
63  str = "RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK";
64  break;
65 
66  case RPC_CLIENT_STATE_WAIT_UNSECURE_BIND_ACK:
67  str = "RPC_CLIENT_STATE_WAIT_UNSECURE_BIND_ACK";
68  break;
69 
70  case RPC_CLIENT_STATE_WAIT_SECURE_ALTER_CONTEXT_RESPONSE:
71  str = "RPC_CLIENT_STATE_WAIT_SECURE_ALTER_CONTEXT_RESPONSE";
72  break;
73 
74  case RPC_CLIENT_STATE_CONTEXT_NEGOTIATED:
75  str = "RPC_CLIENT_STATE_CONTEXT_NEGOTIATED";
76  break;
77 
78  case RPC_CLIENT_STATE_WAIT_RESPONSE:
79  str = "RPC_CLIENT_STATE_WAIT_RESPONSE";
80  break;
81 
82  case RPC_CLIENT_STATE_FINAL:
83  str = "RPC_CLIENT_STATE_FINAL";
84  break;
85  default:
86  break;
87  }
88  return str;
89 }
90 
91 static void rpc_pdu_reset(RPC_PDU* pdu)
92 {
93  pdu->Type = 0;
94  pdu->Flags = 0;
95  pdu->CallId = 0;
96  Stream_SetPosition(pdu->s, 0);
97  Stream_SetLength(pdu->s, 0);
98 }
99 
100 static RPC_PDU* rpc_pdu_new(void)
101 {
102  RPC_PDU* pdu = NULL;
103  pdu = (RPC_PDU*)malloc(sizeof(RPC_PDU));
104 
105  if (!pdu)
106  return NULL;
107 
108  pdu->s = Stream_New(NULL, 4096);
109 
110  if (!pdu->s)
111  {
112  free(pdu);
113  return NULL;
114  }
115 
116  rpc_pdu_reset(pdu);
117  return pdu;
118 }
119 
120 static void rpc_pdu_free(RPC_PDU* pdu)
121 {
122  if (!pdu)
123  return;
124 
125  Stream_Free(pdu->s, TRUE);
126  free(pdu);
127 }
128 
129 static int rpc_client_receive_pipe_write(RpcClient* client, const BYTE* buffer, size_t length)
130 {
131  int status = 0;
132 
133  if (!client || !buffer)
134  return -1;
135 
136  EnterCriticalSection(&(client->PipeLock));
137 
138  if (ringbuffer_write(&(client->ReceivePipe), buffer, length))
139  status += (int)length;
140 
141  if (ringbuffer_used(&(client->ReceivePipe)) > 0)
142  (void)SetEvent(client->PipeEvent);
143 
144  LeaveCriticalSection(&(client->PipeLock));
145  return status;
146 }
147 
148 int rpc_client_receive_pipe_read(RpcClient* client, BYTE* buffer, size_t length)
149 {
150  size_t status = 0;
151  int nchunks = 0;
152  DataChunk chunks[2];
153 
154  if (!client || !buffer)
155  return -1;
156 
157  EnterCriticalSection(&(client->PipeLock));
158  nchunks = ringbuffer_peek(&(client->ReceivePipe), chunks, length);
159 
160  for (int index = 0; index < nchunks; index++)
161  {
162  CopyMemory(&buffer[status], chunks[index].data, chunks[index].size);
163  status += chunks[index].size;
164  }
165 
166  if (status > 0)
167  ringbuffer_commit_read_bytes(&(client->ReceivePipe), status);
168 
169  if (ringbuffer_used(&(client->ReceivePipe)) < 1)
170  (void)ResetEvent(client->PipeEvent);
171 
172  LeaveCriticalSection(&(client->PipeLock));
173 
174  if (status > INT_MAX)
175  return -1;
176  return (int)status;
177 }
178 
179 static int rpc_client_transition_to_state(rdpRpc* rpc, RPC_CLIENT_STATE state)
180 {
181  int status = 1;
182 
183  rpc->State = state;
184  WLog_DBG(TAG, "%s", rpc_client_state_str(state));
185  return status;
186 }
187 
188 static int rpc_client_recv_pdu_int(rdpRpc* rpc, RPC_PDU* pdu)
189 {
190  int status = -1;
191  RtsPduSignature found = { 0 };
192 
193  WINPR_ASSERT(rpc);
194  WINPR_ASSERT(pdu);
195 
196  rdpTsg* tsg = transport_get_tsg(rpc->transport);
197 
198  WLog_VRB(TAG, "client state %s, vc state %s", rpc_client_state_str(rpc->State),
199  rpc_vc_state_str(rpc->VirtualConnection->State));
200 
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);
203  if (rc)
204  return rts_recv_ping_pdu(rpc, pdu->s);
205 
206  if (rpc->VirtualConnection->State < VIRTUAL_CONNECTION_STATE_OPENED)
207  {
208  switch (rpc->VirtualConnection->State)
209  {
210  case VIRTUAL_CONNECTION_STATE_INITIAL:
211  break;
212 
213  case VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT:
214  break;
215 
216  case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
217  if (memcmp(&found, &RTS_PDU_CONN_A3_SIGNATURE, sizeof(found)) != 0)
218  {
219  wLog* log = WLog_Get(TAG);
220  WLog_Print(log, WLOG_ERROR, "unexpected RTS PDU: Expected CONN/A3");
221  rts_print_pdu_signature(log, WLOG_ERROR, &found);
222  return -1;
223  }
224 
225  if (!rts_recv_CONN_A3_pdu(rpc, pdu->s))
226  {
227  WLog_ERR(TAG, "rts_recv_CONN_A3_pdu failure");
228  return -1;
229  }
230 
231  rpc_virtual_connection_transition_to_state(rpc, rpc->VirtualConnection,
232  VIRTUAL_CONNECTION_STATE_WAIT_C2);
233  status = 1;
234  break;
235 
236  case VIRTUAL_CONNECTION_STATE_WAIT_C2:
237  if (memcmp(&found, &RTS_PDU_CONN_C2_SIGNATURE, sizeof(found)) != 0)
238  {
239  wLog* log = WLog_Get(TAG);
240  WLog_Print(log, WLOG_ERROR, "unexpected RTS PDU: Expected CONN/C2");
241  rts_print_pdu_signature(log, WLOG_ERROR, &found);
242  return -1;
243  }
244 
245  if (!rts_recv_CONN_C2_pdu(rpc, pdu->s))
246  {
247  WLog_ERR(TAG, "rts_recv_CONN_C2_pdu failure");
248  return -1;
249  }
250 
251  rpc_virtual_connection_transition_to_state(rpc, rpc->VirtualConnection,
252  VIRTUAL_CONNECTION_STATE_OPENED);
253  rpc_client_transition_to_state(rpc, RPC_CLIENT_STATE_ESTABLISHED);
254 
255  if (rpc_send_bind_pdu(rpc, TRUE) < 0)
256  {
257  WLog_ERR(TAG, "rpc_send_bind_pdu failure");
258  return -1;
259  }
260 
261  rpc_client_transition_to_state(rpc, RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK);
262  status = 1;
263  break;
264 
265  case VIRTUAL_CONNECTION_STATE_OPENED:
266  break;
267 
268  case VIRTUAL_CONNECTION_STATE_FINAL:
269  break;
270  default:
271  break;
272  }
273  }
274  else if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
275  {
276  if (rpc->State == RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK)
277  {
278  if (pdu->Type == PTYPE_BIND_ACK || pdu->Type == PTYPE_ALTER_CONTEXT_RESP)
279  {
280  if (!rpc_recv_bind_ack_pdu(rpc, pdu->s))
281  {
282  WLog_ERR(TAG, "rpc_recv_bind_ack_pdu failure");
283  return -1;
284  }
285  }
286  else
287  {
288  WLog_ERR(TAG,
289  "RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK unexpected pdu type: 0x%08" PRIX32
290  "",
291  pdu->Type);
292  return -1;
293  }
294 
295  switch (rpc_bind_state(rpc))
296  {
297  case RPC_BIND_STATE_INCOMPLETE:
298  if (rpc_send_bind_pdu(rpc, FALSE) < 0)
299  {
300  WLog_ERR(TAG, "rpc_send_bind_pdu failure");
301  return -1;
302  }
303  break;
304  case RPC_BIND_STATE_LAST_LEG:
305  if (rpc_send_rpc_auth_3_pdu(rpc) < 0)
306  {
307  WLog_ERR(TAG, "rpc_secure_bind: error sending rpc_auth_3 pdu!");
308  return -1;
309  }
310  /* fallthrough */
311  WINPR_FALLTHROUGH
312  case RPC_BIND_STATE_COMPLETE:
313  rpc_client_transition_to_state(rpc, RPC_CLIENT_STATE_CONTEXT_NEGOTIATED);
314 
315  if (!tsg_proxy_begin(tsg))
316  {
317  WLog_ERR(TAG, "tsg_proxy_begin failure");
318  return -1;
319  }
320  break;
321  default:
322  break;
323  }
324 
325  status = 1;
326  }
327  else
328  {
329  WLog_ERR(TAG, "invalid rpc->State: %d", rpc->State);
330  }
331  }
332  else if (rpc->State >= RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
333  {
334  if (!tsg_recv_pdu(tsg, pdu))
335  status = -1;
336  else
337  status = 1;
338  }
339 
340  return status;
341 }
342 
343 static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
344 {
345  WINPR_ASSERT(rpc);
346  WINPR_ASSERT(pdu);
347 
348  Stream_SealLength(pdu->s);
349  Stream_SetPosition(pdu->s, 0);
350 
351  const size_t before = Stream_GetRemainingLength(pdu->s);
352  WLog_VRB(TAG, "RPC PDU parsing %" PRIuz " bytes", before);
353  const int rc = rpc_client_recv_pdu_int(rpc, pdu);
354  if (rc < 0)
355  return rc;
356  const size_t after = Stream_GetRemainingLength(pdu->s);
357  if (after > 0)
358  {
359  /* Just log so we do not fail if we have some unprocessed padding bytes */
360  WLog_WARN(TAG, "Incompletely parsed RPC PDU (%" PRIuz " bytes remain)", after);
361  }
362 
363  return rc;
364 }
365 
366 static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
367 {
368  int rc = -1;
369  RPC_PDU* pdu = NULL;
370  size_t StubOffset = 0;
371  size_t StubLength = 0;
372  RpcClientCall* call = NULL;
373  rpcconn_hdr_t header = { 0 };
374 
375  WINPR_ASSERT(rpc);
376  WINPR_ASSERT(rpc->client);
377  WINPR_ASSERT(fragment);
378 
379  pdu = rpc->client->pdu;
380  WINPR_ASSERT(pdu);
381 
382  Stream_SealLength(fragment);
383  Stream_SetPosition(fragment, 0);
384 
385  if (!rts_read_pdu_header(fragment, &header))
386  goto fail;
387 
388  if (header.common.ptype == PTYPE_RESPONSE)
389  {
390  rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header.common.frag_length;
391  rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -=
392  header.common.frag_length;
393 
394  if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow <
395  (rpc->ReceiveWindow / 2))
396  {
397  if (!rts_send_flow_control_ack_pdu(rpc))
398  goto fail;
399  }
400 
401  if (!rpc_get_stub_data_info(rpc, &header, &StubOffset, &StubLength))
402  {
403  WLog_ERR(TAG, "expected stub");
404  goto fail;
405  }
406 
407  if (StubLength == 4)
408  {
409  if ((header.common.call_id == rpc->PipeCallId) &&
410  (header.common.pfc_flags & PFC_LAST_FRAG))
411  {
412  /* End of TsProxySetupReceivePipe */
413  TerminateEventArgs e;
414  rdpContext* context = transport_get_context(rpc->transport);
415  rdpTsg* tsg = transport_get_tsg(rpc->transport);
416 
417  WINPR_ASSERT(context);
418 
419  if (Stream_Length(fragment) < StubOffset + 4)
420  goto fail;
421  Stream_SetPosition(fragment, StubOffset);
422  Stream_Read_UINT32(fragment, rpc->result);
423 
424  utils_abort_connect(context->rdp);
425  tsg_set_state(tsg, TSG_STATE_TUNNEL_CLOSE_PENDING);
426  EventArgsInit(&e, "freerdp");
427  e.code = 0;
428  PubSub_OnTerminate(context->rdp->pubSub, context, &e);
429  rc = 0;
430  goto success;
431  }
432 
433  if (header.common.call_id != rpc->PipeCallId)
434  {
435  /* Ignoring non-TsProxySetupReceivePipe Response */
436  rc = 0;
437  goto success;
438  }
439  }
440 
441  if (rpc->StubFragCount == 0)
442  rpc->StubCallId = header.common.call_id;
443 
444  if (rpc->StubCallId != header.common.call_id)
445  {
446  WLog_ERR(TAG,
447  "invalid call_id: actual: %" PRIu32 ", expected: %" PRIu32
448  ", frag_count: %" PRIu32 "",
449  rpc->StubCallId, header.common.call_id, rpc->StubFragCount);
450  }
451 
452  call = rpc_client_call_find_by_id(rpc->client, rpc->StubCallId);
453 
454  if (!call)
455  goto fail;
456 
457  if (call->OpNum != TsProxySetupReceivePipeOpnum)
458  {
459  const rpcconn_response_hdr_t* response =
460  (const rpcconn_response_hdr_t*)&header.response;
461  if (!Stream_EnsureCapacity(pdu->s, response->alloc_hint))
462  goto fail;
463 
464  if (Stream_Length(fragment) < StubOffset + StubLength)
465  goto fail;
466 
467  Stream_SetPosition(fragment, StubOffset);
468  Stream_Write(pdu->s, Stream_ConstPointer(fragment), StubLength);
469  rpc->StubFragCount++;
470 
471  if (response->alloc_hint == StubLength)
472  {
473  pdu->Flags = RPC_PDU_FLAG_STUB;
474  pdu->Type = PTYPE_RESPONSE;
475  pdu->CallId = rpc->StubCallId;
476 
477  if (rpc_client_recv_pdu(rpc, pdu) < 0)
478  goto fail;
479  rpc_pdu_reset(pdu);
480  rpc->StubFragCount = 0;
481  rpc->StubCallId = 0;
482  }
483  }
484  else
485  {
486  const rpcconn_response_hdr_t* response = &header.response;
487  if (Stream_Length(fragment) < StubOffset + StubLength)
488  goto fail;
489  Stream_SetPosition(fragment, StubOffset);
490  rpc_client_receive_pipe_write(rpc->client, Stream_ConstPointer(fragment), StubLength);
491  rpc->StubFragCount++;
492 
493  if (response->alloc_hint == StubLength)
494  {
495  rpc->StubFragCount = 0;
496  rpc->StubCallId = 0;
497  }
498  }
499 
500  goto success;
501  }
502  else if (header.common.ptype == PTYPE_RTS)
503  {
504  if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
505  {
506  pdu->Flags = 0;
507  pdu->Type = header.common.ptype;
508  pdu->CallId = header.common.call_id;
509 
510  const size_t len = Stream_Length(fragment);
511  if (!Stream_EnsureCapacity(pdu->s, len))
512  goto fail;
513 
514  Stream_Write(pdu->s, Stream_Buffer(fragment), len);
515 
516  if (rpc_client_recv_pdu(rpc, pdu) < 0)
517  goto fail;
518 
519  rpc_pdu_reset(pdu);
520  }
521  else
522  {
523  if (!rts_recv_out_of_sequence_pdu(rpc, fragment, &header))
524  goto fail;
525  }
526 
527  goto success;
528  }
529  else if (header.common.ptype == PTYPE_BIND_ACK ||
530  header.common.ptype == PTYPE_ALTER_CONTEXT_RESP)
531  {
532  pdu->Flags = 0;
533  pdu->Type = header.common.ptype;
534  pdu->CallId = header.common.call_id;
535 
536  const size_t len = Stream_Length(fragment);
537  if (!Stream_EnsureCapacity(pdu->s, len))
538  goto fail;
539 
540  Stream_Write(pdu->s, Stream_Buffer(fragment), len);
541 
542  if (rpc_client_recv_pdu(rpc, pdu) < 0)
543  goto fail;
544 
545  rpc_pdu_reset(pdu);
546  goto success;
547  }
548  else if (header.common.ptype == PTYPE_FAULT)
549  {
550  const rpcconn_fault_hdr_t* fault = (const rpcconn_fault_hdr_t*)&header.fault;
551  rpc_recv_fault_pdu(fault->status);
552  goto fail;
553  }
554  else
555  {
556  WLog_ERR(TAG, "unexpected RPC PDU type 0x%02" PRIX8 "", header.common.ptype);
557  goto fail;
558  }
559 
560 success:
561  rc = (rc < 0) ? 1 : 0; /* In case of default error return change to 1, otherwise we already set
562  the return code */
563 fail:
564  rts_free_pdu_header(&header, FALSE);
565  return rc;
566 }
567 
568 static SSIZE_T rpc_client_default_out_channel_recv(rdpRpc* rpc)
569 {
570  SSIZE_T status = -1;
571  HttpResponse* response = NULL;
572  RpcInChannel* inChannel = NULL;
573  RpcOutChannel* outChannel = NULL;
574  HANDLE outChannelEvent = NULL;
575  RpcVirtualConnection* connection = rpc->VirtualConnection;
576  inChannel = connection->DefaultInChannel;
577  outChannel = connection->DefaultOutChannel;
578  BIO_get_event(outChannel->common.tls->bio, &outChannelEvent);
579 
580  if (outChannel->State < CLIENT_OUT_CHANNEL_STATE_OPENED)
581  {
582  if (WaitForSingleObject(outChannelEvent, 0) != WAIT_OBJECT_0)
583  return 1;
584 
585  response = http_response_recv(outChannel->common.tls, TRUE);
586 
587  if (!response)
588  return -1;
589 
590  if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_SECURITY)
591  {
592  /* Receive OUT Channel Response */
593  if (!rpc_ncacn_http_recv_out_channel_response(&outChannel->common, response))
594  {
595  http_response_free(response);
596  WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure");
597  return -1;
598  }
599 
600  /* Send OUT Channel Request */
601 
602  if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
603  {
604  http_response_free(response);
605  WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
606  return -1;
607  }
608 
609  if (rpc_ncacn_http_is_final_request(&outChannel->common))
610  {
611  rpc_ncacn_http_auth_uninit(&outChannel->common);
612  rpc_out_channel_transition_to_state(outChannel,
613  CLIENT_OUT_CHANNEL_STATE_NEGOTIATED);
614 
615  /* Send CONN/A1 PDU over OUT channel */
616 
617  if (!rts_send_CONN_A1_pdu(rpc))
618  {
619  http_response_free(response);
620  WLog_ERR(TAG, "rpc_send_CONN_A1_pdu error!");
621  return -1;
622  }
623 
624  rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_OPENED);
625 
626  if (inChannel->State == CLIENT_IN_CHANNEL_STATE_OPENED)
627  {
628  rpc_virtual_connection_transition_to_state(
629  rpc, connection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
630  }
631  }
632 
633  status = 1;
634  }
635 
636  http_response_free(response);
637  }
638  else if (connection->State == VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT)
639  {
640  /* Receive OUT channel response */
641  if (WaitForSingleObject(outChannelEvent, 0) != WAIT_OBJECT_0)
642  return 1;
643 
644  response = http_response_recv(outChannel->common.tls, FALSE);
645 
646  if (!response)
647  return -1;
648 
649  const INT16 statusCode = http_response_get_status_code(response);
650 
651  if (statusCode != HTTP_STATUS_OK)
652  {
653  http_response_log_error_status(WLog_Get(TAG), WLOG_ERROR, response);
654 
655  if (statusCode == HTTP_STATUS_DENIED)
656  {
657  rdpContext* context = transport_get_context(rpc->transport);
658  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
659  }
660 
661  http_response_free(response);
662  return -1;
663  }
664 
665  http_response_free(response);
666  rpc_virtual_connection_transition_to_state(rpc, rpc->VirtualConnection,
667  VIRTUAL_CONNECTION_STATE_WAIT_A3W);
668  status = 1;
669  }
670  else
671  {
672  wStream* fragment = rpc->client->ReceiveFragment;
673 
674  while (1)
675  {
676  size_t pos = 0;
677  rpcconn_common_hdr_t header = { 0 };
678 
679  while (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
680  {
681  status = rpc_channel_read(&outChannel->common, fragment,
682  RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(fragment));
683 
684  if (status < 0)
685  return -1;
686 
687  if (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
688  return 0;
689  }
690 
691  pos = Stream_GetPosition(fragment);
692  Stream_SetPosition(fragment, 0);
693 
694  /* Ignore errors, the PDU might not be complete. */
695  rts_read_common_pdu_header(fragment, &header, TRUE);
696  Stream_SetPosition(fragment, pos);
697 
698  if (header.frag_length > rpc->max_recv_frag)
699  {
700  WLog_ERR(TAG,
701  "rpc_client_recv: invalid fragment size: %" PRIu16 " (max: %" PRIu16 ")",
702  header.frag_length, rpc->max_recv_frag);
703  winpr_HexDump(TAG, WLOG_ERROR, Stream_Buffer(fragment),
704  Stream_GetPosition(fragment));
705  return -1;
706  }
707 
708  while (Stream_GetPosition(fragment) < header.frag_length)
709  {
710  status = rpc_channel_read(&outChannel->common, fragment,
711  header.frag_length - Stream_GetPosition(fragment));
712 
713  if (status < 0)
714  {
715  WLog_ERR(TAG, "error reading fragment body");
716  return -1;
717  }
718 
719  if (Stream_GetPosition(fragment) < header.frag_length)
720  return 0;
721  }
722 
723  {
724  /* complete fragment received */
725  status = rpc_client_recv_fragment(rpc, fragment);
726 
727  if (status < 0)
728  return status;
729 
730  /* channel recycling may update channel pointers */
731  if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_RECYCLED &&
732  connection->NonDefaultOutChannel)
733  {
734  rpc_channel_free(&connection->DefaultOutChannel->common);
735  connection->DefaultOutChannel = connection->NonDefaultOutChannel;
736  connection->NonDefaultOutChannel = NULL;
737  rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
738  CLIENT_OUT_CHANNEL_STATE_OPENED);
739  rpc_virtual_connection_transition_to_state(
740  rpc, connection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
741  return 0;
742  }
743 
744  Stream_SetPosition(fragment, 0);
745  }
746  }
747  }
748 
749  return status;
750 }
751 
752 static SSIZE_T rpc_client_nondefault_out_channel_recv(rdpRpc* rpc)
753 {
754  SSIZE_T status = -1;
755  HttpResponse* response = NULL;
756  RpcOutChannel* nextOutChannel = NULL;
757  HANDLE nextOutChannelEvent = NULL;
758  nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
759  BIO_get_event(nextOutChannel->common.tls->bio, &nextOutChannelEvent);
760 
761  if (WaitForSingleObject(nextOutChannelEvent, 0) != WAIT_OBJECT_0)
762  return 1;
763 
764  response = http_response_recv(nextOutChannel->common.tls, TRUE);
765 
766  if (response)
767  {
768  switch (nextOutChannel->State)
769  {
770  case CLIENT_OUT_CHANNEL_STATE_SECURITY:
771  if (rpc_ncacn_http_recv_out_channel_response(&nextOutChannel->common, response))
772  {
773  if (rpc_ncacn_http_send_out_channel_request(&nextOutChannel->common, TRUE))
774  {
775  if (rpc_ncacn_http_is_final_request(&nextOutChannel->common))
776  {
777  rpc_ncacn_http_auth_uninit(&nextOutChannel->common);
778 
779  if (rts_send_OUT_R1_A3_pdu(rpc))
780  {
781  status = 1;
782  rpc_out_channel_transition_to_state(
783  nextOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
784  }
785  else
786  {
787  WLog_ERR(TAG, "rts_send_OUT_R1/A3_pdu failure");
788  }
789  }
790  else
791  {
792  status = 1;
793  }
794  }
795  else
796  {
797  WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
798  }
799  }
800  else
801  {
802  WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure");
803  }
804 
805  break;
806 
807  case CLIENT_OUT_CHANNEL_STATE_INITIAL:
808  case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
809  case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
810  default:
811  WLog_ERR(TAG,
812  "rpc_client_nondefault_out_channel_recv: Unexpected message %08" PRIx32,
813  nextOutChannel->State);
814  status = -1;
815  }
816 
817  http_response_free(response);
818  }
819 
820  return status;
821 }
822 
823 int rpc_client_out_channel_recv(rdpRpc* rpc)
824 {
825  SSIZE_T status = 0;
826  RpcVirtualConnection* connection = rpc->VirtualConnection;
827 
828  if (connection->DefaultOutChannel)
829  {
830  status = rpc_client_default_out_channel_recv(rpc);
831 
832  if (status < 0)
833  return -1;
834  }
835 
836  if (connection->NonDefaultOutChannel)
837  {
838  status = rpc_client_nondefault_out_channel_recv(rpc);
839 
840  if (status < 0)
841  return -1;
842  }
843 
844  return 1;
845 }
846 
847 int rpc_client_in_channel_recv(rdpRpc* rpc)
848 {
849  int status = 1;
850  HttpResponse* response = NULL;
851  RpcInChannel* inChannel = NULL;
852  RpcOutChannel* outChannel = NULL;
853  HANDLE InChannelEvent = NULL;
854  RpcVirtualConnection* connection = rpc->VirtualConnection;
855  inChannel = connection->DefaultInChannel;
856  outChannel = connection->DefaultOutChannel;
857  BIO_get_event(inChannel->common.tls->bio, &InChannelEvent);
858 
859  if (WaitForSingleObject(InChannelEvent, 0) != WAIT_OBJECT_0)
860  return 1;
861 
862  if (inChannel->State < CLIENT_IN_CHANNEL_STATE_OPENED)
863  {
864  response = http_response_recv(inChannel->common.tls, TRUE);
865 
866  if (!response)
867  return -1;
868 
869  if (inChannel->State == CLIENT_IN_CHANNEL_STATE_SECURITY)
870  {
871  if (!rpc_ncacn_http_recv_in_channel_response(&inChannel->common, response))
872  {
873  WLog_ERR(TAG, "rpc_ncacn_http_recv_in_channel_response failure");
874  http_response_free(response);
875  return -1;
876  }
877 
878  /* Send IN Channel Request */
879 
880  if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
881  {
882  WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure");
883  http_response_free(response);
884  return -1;
885  }
886 
887  if (rpc_ncacn_http_is_final_request(&inChannel->common))
888  {
889  rpc_ncacn_http_auth_uninit(&inChannel->common);
890  rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_NEGOTIATED);
891 
892  /* Send CONN/B1 PDU over IN channel */
893 
894  if (!rts_send_CONN_B1_pdu(rpc))
895  {
896  WLog_ERR(TAG, "rpc_send_CONN_B1_pdu error!");
897  http_response_free(response);
898  return -1;
899  }
900 
901  rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_OPENED);
902 
903  if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
904  {
905  rpc_virtual_connection_transition_to_state(
906  rpc, connection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
907  }
908  }
909 
910  status = 1;
911  }
912 
913  http_response_free(response);
914  }
915  else
916  {
917  response = http_response_recv(inChannel->common.tls, TRUE);
918 
919  if (!response)
920  return -1;
921 
922  /* We can receive an unauthorized HTTP response on the IN channel */
923  http_response_free(response);
924  }
925 
926  return status;
927 }
928 
934 RpcClientCall* rpc_client_call_find_by_id(RpcClient* client, UINT32 CallId)
935 {
936  RpcClientCall* clientCall = NULL;
937 
938  if (!client)
939  return NULL;
940 
941  ArrayList_Lock(client->ClientCallList);
942  const size_t count = ArrayList_Count(client->ClientCallList);
943 
944  for (size_t index = 0; index < count; index++)
945  {
946  clientCall = (RpcClientCall*)ArrayList_GetItem(client->ClientCallList, index);
947 
948  if (clientCall->CallId == CallId)
949  break;
950  }
951 
952  ArrayList_Unlock(client->ClientCallList);
953  return clientCall;
954 }
955 
956 RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum)
957 {
958  RpcClientCall* clientCall = NULL;
959  clientCall = (RpcClientCall*)calloc(1, sizeof(RpcClientCall));
960 
961  if (!clientCall)
962  return NULL;
963 
964  clientCall->CallId = CallId;
965  clientCall->OpNum = OpNum;
966  clientCall->State = RPC_CLIENT_CALL_STATE_SEND_PDUS;
967  return clientCall;
968 }
969 
970 void rpc_client_call_free(RpcClientCall* clientCall)
971 {
972  free(clientCall);
973 }
974 
975 static void rpc_array_client_call_free(void* call)
976 {
977  rpc_client_call_free((RpcClientCall*)call);
978 }
979 
980 int rpc_in_channel_send_pdu(RpcInChannel* inChannel, const BYTE* buffer, size_t length)
981 {
982  SSIZE_T status = 0;
983  RpcClientCall* clientCall = NULL;
984  wStream s;
985  rpcconn_common_hdr_t header = { 0 };
986 
987  status = rpc_channel_write(&inChannel->common, buffer, length);
988 
989  if (status <= 0)
990  return -1;
991 
992  Stream_StaticConstInit(&s, buffer, length);
993  if (!rts_read_common_pdu_header(&s, &header, FALSE))
994  return -1;
995 
996  clientCall = rpc_client_call_find_by_id(inChannel->common.client, header.call_id);
997  if (!clientCall)
998  return -1;
999 
1000  clientCall->State = RPC_CLIENT_CALL_STATE_DISPATCHED;
1001 
1002  /*
1003  * This protocol specifies that only RPC PDUs are subject to the flow control abstract
1004  * data model. RTS PDUs and the HTTP request and response headers are not subject to flow
1005  * control. Implementations of this protocol MUST NOT include them when computing any of the
1006  * variables specified by this abstract data model.
1007  */
1008 
1009  if (header.ptype == PTYPE_REQUEST)
1010  {
1011  inChannel->BytesSent += status;
1012  inChannel->SenderAvailableWindow -= status;
1013  }
1014 
1015  if (status > INT32_MAX)
1016  return -1;
1017  return (int)status;
1018 }
1019 
1020 BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum)
1021 {
1022  size_t offset = 0;
1023  BYTE* buffer = NULL;
1024  size_t stub_data_pad = 0;
1025  SecBuffer plaintext;
1026  SecBuffer ciphertext = { 0 };
1027  RpcClientCall* clientCall = NULL;
1028  rdpCredsspAuth* auth = NULL;
1029  rpcconn_request_hdr_t request_pdu = { 0 };
1030  RpcVirtualConnection* connection = NULL;
1031  RpcInChannel* inChannel = NULL;
1032  BOOL rc = FALSE;
1033 
1034  if (!s)
1035  return FALSE;
1036 
1037  if (!rpc)
1038  goto fail;
1039 
1040  auth = rpc->auth;
1041  connection = rpc->VirtualConnection;
1042 
1043  if (!auth)
1044  {
1045  WLog_ERR(TAG, "invalid auth context");
1046  goto fail;
1047  }
1048 
1049  if (!connection)
1050  goto fail;
1051 
1052  inChannel = connection->DefaultInChannel;
1053 
1054  if (!inChannel)
1055  goto fail;
1056 
1057  Stream_SealLength(s);
1058  const size_t length = Stream_Length(s);
1059  if (length > UINT32_MAX)
1060  goto fail;
1061 
1062  const size_t asize = credssp_auth_trailer_size(auth);
1063 
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);
1073 
1074  if (!clientCall)
1075  goto fail;
1076 
1077  if (!ArrayList_Append(rpc->client->ClientCallList, clientCall))
1078  {
1079  rpc_client_call_free(clientCall);
1080  goto fail;
1081  }
1082 
1083  // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): ArrayList_Append takes ownership of clientCall
1084  if (request_pdu.opnum == TsProxySetupReceivePipeOpnum)
1085  rpc->PipeCallId = request_pdu.header.call_id;
1086 
1087  request_pdu.stub_data = Stream_Buffer(s);
1088  offset = 24;
1089  stub_data_pad = rpc_offset_align(&offset, 8);
1090  offset += length;
1091 
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);
1101 
1102  if (offset > UINT16_MAX)
1103  goto fail;
1104  request_pdu.header.frag_length = (UINT16)offset;
1105  buffer = (BYTE*)calloc(1, request_pdu.header.frag_length);
1106 
1107  if (!buffer)
1108  goto fail;
1109 
1110  CopyMemory(buffer, &request_pdu, 24);
1111  offset = 24;
1112  rpc_offset_pad(&offset, stub_data_pad);
1113  CopyMemory(&buffer[offset], request_pdu.stub_data, length);
1114  offset += length;
1115  rpc_offset_pad(&offset, request_pdu.auth_verifier.auth_pad_length);
1116  CopyMemory(&buffer[offset], &request_pdu.auth_verifier.auth_type, 8);
1117  offset += 8;
1118 
1119  if (offset > UINT32_MAX)
1120  goto fail;
1121 
1122  plaintext.pvBuffer = buffer;
1123  plaintext.cbBuffer = (UINT32)offset;
1124  plaintext.BufferType = SECBUFFER_READONLY;
1125 
1126  size_t size = 0;
1127  if (!credssp_auth_encrypt(auth, &plaintext, &ciphertext, &size, rpc->SendSeqNum++))
1128  goto fail;
1129 
1130  CopyMemory(&buffer[offset], ciphertext.pvBuffer, size);
1131  offset += size;
1132 
1133  sspi_SecBufferFree(&ciphertext);
1134 
1135  if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu.header.frag_length) < 0)
1136  goto fail;
1137 
1138  rc = TRUE;
1139 fail:
1140  free(buffer);
1141  Stream_Free(s, TRUE);
1142  return rc;
1143 }
1144 
1145 static BOOL rpc_client_resolve_gateway(rdpSettings* settings, char** host, UINT16* port,
1146  BOOL* isProxy)
1147 {
1148  struct addrinfo* result = NULL;
1149 
1150  if (!settings || !host || !port || !isProxy)
1151  return FALSE;
1152  else
1153  {
1154  const char* peerHostname = freerdp_settings_get_string(settings, FreeRDP_GatewayHostname);
1155  const char* proxyUsername = freerdp_settings_get_string(settings, FreeRDP_GatewayUsername);
1156  const char* proxyPassword = freerdp_settings_get_string(settings, FreeRDP_GatewayPassword);
1157  *port = (UINT16)freerdp_settings_get_uint32(settings, FreeRDP_GatewayPort);
1158  *isProxy = proxy_prepare(settings, &peerHostname, port, &proxyUsername, &proxyPassword);
1159  result = freerdp_tcp_resolve_host(peerHostname, *port, 0);
1160 
1161  if (!result)
1162  return FALSE;
1163 
1164  *host =
1165  freerdp_tcp_address_to_string((const struct sockaddr_storage*)result->ai_addr, NULL);
1166  freeaddrinfo(result);
1167  return TRUE;
1168  }
1169 }
1170 
1171 RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag)
1172 {
1173  wObject* obj = NULL;
1174  RpcClient* client = (RpcClient*)calloc(1, sizeof(RpcClient));
1175 
1176  if (!client)
1177  return NULL;
1178 
1179  if (!rpc_client_resolve_gateway(context->settings, &client->host, &client->port,
1180  &client->isProxy))
1181  goto fail;
1182 
1183  client->context = context;
1184 
1185  if (!client->context)
1186  goto fail;
1187 
1188  client->pdu = rpc_pdu_new();
1189 
1190  if (!client->pdu)
1191  goto fail;
1192 
1193  client->ReceiveFragment = Stream_New(NULL, max_recv_frag);
1194 
1195  if (!client->ReceiveFragment)
1196  goto fail;
1197 
1198  client->PipeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1199 
1200  if (!client->PipeEvent)
1201  goto fail;
1202 
1203  if (!ringbuffer_init(&(client->ReceivePipe), 4096))
1204  goto fail;
1205 
1206  if (!InitializeCriticalSectionAndSpinCount(&(client->PipeLock), 4000))
1207  goto fail;
1208 
1209  client->ClientCallList = ArrayList_New(TRUE);
1210 
1211  if (!client->ClientCallList)
1212  goto fail;
1213 
1214  obj = ArrayList_Object(client->ClientCallList);
1215  obj->fnObjectFree = rpc_array_client_call_free;
1216  return client;
1217 fail:
1218  WINPR_PRAGMA_DIAG_PUSH
1219  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1220  rpc_client_free(client);
1221  WINPR_PRAGMA_DIAG_POP
1222  return NULL;
1223 }
1224 
1225 void rpc_client_free(RpcClient* client)
1226 {
1227  if (!client)
1228  return;
1229 
1230  free(client->host);
1231 
1232  if (client->ReceiveFragment)
1233  Stream_Free(client->ReceiveFragment, TRUE);
1234 
1235  if (client->PipeEvent)
1236  (void)CloseHandle(client->PipeEvent);
1237 
1238  ringbuffer_destroy(&(client->ReceivePipe));
1239  DeleteCriticalSection(&(client->PipeLock));
1240 
1241  if (client->pdu)
1242  rpc_pdu_free(client->pdu);
1243 
1244  if (client->ClientCallList)
1245  ArrayList_Free(client->ClientCallList);
1246 
1247  free(client);
1248 }
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
Definition: ringbuffer.h:44
This struct contains function pointer to initialize/free objects.
Definition: collections.h:57