FreeRDP
rts.c
1 
20 #include <freerdp/config.h>
21 
22 #include <winpr/assert.h>
23 #include <winpr/cast.h>
24 #include <winpr/crt.h>
25 #include <winpr/crypto.h>
26 
27 #include <freerdp/log.h>
28 
29 #include "ncacn_http.h"
30 #include "rpc_client.h"
31 #include "rts_signature.h"
32 
33 #include "rts.h"
34 
35 #define TAG FREERDP_TAG("core.gateway.rts")
36 
70 static int rts_destination_command_read(rdpRpc* rpc, wStream* buffer, UINT32* Destination);
71 
72 static const char* rts_command_to_string(UINT32 cmd, char* buffer, size_t len)
73 {
74  const char* str = NULL;
75 
76 #undef ENTRY
77 #define ENTRY(x) \
78  case x: \
79  str = "#x"; \
80  break
81 
82  switch (cmd)
83  {
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);
91  ENTRY(RTS_CMD_EMPTY);
92  ENTRY(RTS_CMD_PADDING);
93  ENTRY(RTS_CMD_NEGATIVE_ANCE);
94  ENTRY(RTS_CMD_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);
100  default:
101  str = "RTS_CMD_UNKNOWN";
102  break;
103  }
104 
105 #undef ENTRY
106 
107  (void)_snprintf(buffer, len, "%s [0x%08" PRIx32 "]", str, cmd);
108  return buffer;
109 }
110 
111 static const char* rts_pdu_ptype_to_string(UINT32 ptype)
112 {
113  switch (ptype)
114  {
115  case PTYPE_REQUEST:
116  return "PTYPE_REQUEST";
117  case PTYPE_PING:
118  return "PTYPE_PING";
119  case PTYPE_RESPONSE:
120  return "PTYPE_RESPONSE";
121  case PTYPE_FAULT:
122  return "PTYPE_FAULT";
123  case PTYPE_WORKING:
124  return "PTYPE_WORKING";
125  case PTYPE_NOCALL:
126  return "PTYPE_NOCALL";
127  case PTYPE_REJECT:
128  return "PTYPE_REJECT";
129  case PTYPE_ACK:
130  return "PTYPE_ACK";
131  case PTYPE_CL_CANCEL:
132  return "PTYPE_CL_CANCEL";
133  case PTYPE_FACK:
134  return "PTYPE_FACK";
135  case PTYPE_CANCEL_ACK:
136  return "PTYPE_CANCEL_ACK";
137  case PTYPE_BIND:
138  return "PTYPE_BIND";
139  case PTYPE_BIND_ACK:
140  return "PTYPE_BIND_ACK";
141  case PTYPE_BIND_NAK:
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";
149  case PTYPE_SHUTDOWN:
150  return "PTYPE_SHUTDOWN";
151  case PTYPE_CO_CANCEL:
152  return "PTYPE_CO_CANCEL";
153  case PTYPE_ORPHANED:
154  return "PTYPE_ORPHANED";
155  case PTYPE_RTS:
156  return "PTYPE_RTS";
157  default:
158  return "UNKNOWN";
159  }
160 }
161 
162 static rpcconn_rts_hdr_t rts_pdu_header_init(void)
163 {
164  rpcconn_rts_hdr_t header = { 0 };
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;
175 
176  return header;
177 }
178 
179 static BOOL rts_align_stream(wStream* s, size_t alignment, BOOL silent)
180 {
181  size_t pos = 0;
182  size_t pad = 0;
183 
184  WINPR_ASSERT(s);
185  WINPR_ASSERT(alignment > 0);
186 
187  pos = Stream_GetPosition(s);
188  pad = rpc_offset_align(&pos, alignment);
189  return Stream_ConditionalSafeSeek(s, pad, silent);
190 }
191 
192 static char* sdup(const void* src, size_t length)
193 {
194  char* dst = NULL;
195  WINPR_ASSERT(src || (length == 0));
196  if (length == 0)
197  return NULL;
198 
199  dst = calloc(length + 1, sizeof(char));
200  if (!dst)
201  return NULL;
202  memcpy(dst, src, length);
203  return dst;
204 }
205 
206 static BOOL rts_write_common_pdu_header(wStream* s, const rpcconn_common_hdr_t* header)
207 {
208  WINPR_ASSERT(s);
209  WINPR_ASSERT(header);
210  if (!Stream_EnsureRemainingCapacity(s, sizeof(rpcconn_common_hdr_t)))
211  return FALSE;
212 
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);
221  return TRUE;
222 }
223 
224 BOOL rts_read_common_pdu_header(wStream* s, rpcconn_common_hdr_t* header, BOOL ignoreErrors)
225 {
226  WINPR_ASSERT(s);
227  WINPR_ASSERT(header);
228 
229  if (!ignoreErrors)
230  {
231  if (!Stream_CheckAndLogRequiredLength(TAG, s, sizeof(rpcconn_common_hdr_t)))
232  return FALSE;
233  }
234  else
235  {
236  const size_t sz = Stream_GetRemainingLength(s);
237  if (sz < sizeof(rpcconn_common_hdr_t))
238  return FALSE;
239  }
240 
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);
249 
250  if (header->frag_length < sizeof(rpcconn_common_hdr_t))
251  {
252  if (!ignoreErrors)
253  WLog_WARN(TAG, "Invalid header->frag_length of %" PRIu16 ", expected %" PRIuz,
254  header->frag_length, sizeof(rpcconn_common_hdr_t));
255  return FALSE;
256  }
257 
258  if (!ignoreErrors)
259  {
260  if (!Stream_CheckAndLogRequiredLength(TAG, s,
261  header->frag_length - sizeof(rpcconn_common_hdr_t)))
262  return FALSE;
263  }
264  else
265  {
266  const size_t sz2 = Stream_GetRemainingLength(s);
267  if (sz2 < header->frag_length - sizeof(rpcconn_common_hdr_t))
268  return FALSE;
269  }
270  return TRUE;
271 }
272 
273 static BOOL rts_read_auth_verifier_no_checks(wStream* s, auth_verifier_co_t* auth,
274  const rpcconn_common_hdr_t* header, size_t* startPos,
275  BOOL silent)
276 {
277  WINPR_ASSERT(s);
278  WINPR_ASSERT(auth);
279  WINPR_ASSERT(header);
280 
281  WINPR_ASSERT(header->frag_length > header->auth_length + 8);
282 
283  if (startPos)
284  *startPos = Stream_GetPosition(s);
285 
286  /* Read the auth verifier and check padding matches frag_length */
287  {
288  const size_t expected = header->frag_length - header->auth_length - 8;
289 
290  Stream_SetPosition(s, expected);
291  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 8, silent))
292  return FALSE;
293 
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);
299  }
300 
301  if (header->auth_length != 0)
302  {
303  const void* ptr = Stream_Pointer(s);
304  if (!Stream_ConditionalSafeSeek(s, header->auth_length, silent))
305  return FALSE;
306  auth->auth_value = (BYTE*)sdup(ptr, header->auth_length);
307  if (auth->auth_value == NULL)
308  return FALSE;
309  }
310 
311  return TRUE;
312 }
313 
314 static BOOL rts_read_auth_verifier(wStream* s, auth_verifier_co_t* auth,
315  const rpcconn_common_hdr_t* header, BOOL silent)
316 {
317  size_t pos = 0;
318  WINPR_ASSERT(s);
319  WINPR_ASSERT(auth);
320  WINPR_ASSERT(header);
321 
322  if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
323  return FALSE;
324 
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;
328 }
329 
330 static BOOL rts_read_auth_verifier_with_stub(wStream* s, auth_verifier_co_t* auth,
331  rpcconn_common_hdr_t* header, BOOL silent)
332 {
333  size_t pos = 0;
334  size_t alloc_hint = 0;
335  BYTE** ptr = NULL;
336 
337  if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
338  return FALSE;
339 
340  switch (header->ptype)
341  {
342  case PTYPE_FAULT:
343  {
345  alloc_hint = hdr->alloc_hint;
346  ptr = &hdr->stub_data;
347  }
348  break;
349  case PTYPE_RESPONSE:
350  {
352  alloc_hint = hdr->alloc_hint;
353  ptr = &hdr->stub_data;
354  }
355  break;
356  case PTYPE_REQUEST:
357  {
359  alloc_hint = hdr->alloc_hint;
360  ptr = &hdr->stub_data;
361  }
362  break;
363  default:
364  return FALSE;
365  }
366 
367  if (alloc_hint > 0)
368  {
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;
372 
373  if (off > header->frag_length)
374  WLog_WARN(TAG,
375  "Unexpected alloc_hint(%" PRIuz ") for PDU %s: size %" PRIuz
376  ", offset %" PRIuz,
377  alloc_hint, rts_pdu_ptype_to_string(header->ptype), header->frag_length, off);
378  *ptr = (BYTE*)sdup(src, size);
379  if (!*ptr)
380  return FALSE;
381  }
382 
383  return TRUE;
384 }
385 
386 static void rts_free_auth_verifier(auth_verifier_co_t* auth)
387 {
388  if (!auth)
389  return;
390  free(auth->auth_value);
391 }
392 
393 static BOOL rts_write_auth_verifier(wStream* s, const auth_verifier_co_t* auth,
394  const rpcconn_common_hdr_t* header)
395 {
396  size_t pos = 0;
397  UINT8 auth_pad_length = 0;
398 
399  WINPR_ASSERT(s);
400  WINPR_ASSERT(auth);
401  WINPR_ASSERT(header);
402 
403  /* Align start to a multiple of 4 */
404  pos = Stream_GetPosition(s);
405  if ((pos % 4) != 0)
406  {
407  auth_pad_length = 4 - (pos % 4);
408  if (!Stream_EnsureRemainingCapacity(s, auth_pad_length))
409  return FALSE;
410  Stream_Zero(s, auth_pad_length);
411  }
412 
413 #if defined(WITH_VERBOSE_WINPR_ASSERT) && (WITH_VERBOSE_WINPR_ASSERT != 0)
414  WINPR_ASSERT(header->frag_length + 8ull > header->auth_length);
415  {
416  size_t apos = Stream_GetPosition(s);
417  size_t expected = header->frag_length - header->auth_length - 8;
418 
419  WINPR_ASSERT(apos == expected);
420  }
421 #endif
422 
423  if (!Stream_EnsureRemainingCapacity(s, sizeof(auth_verifier_co_t)))
424  return FALSE;
425 
426  Stream_Write_UINT8(s, auth->auth_type);
427  Stream_Write_UINT8(s, auth->auth_level);
428  Stream_Write_UINT8(s, auth_pad_length);
429  Stream_Write_UINT8(s, 0); /* auth->auth_reserved */
430  Stream_Write_UINT32(s, auth->auth_context_id);
431 
432  if (!Stream_EnsureRemainingCapacity(s, header->auth_length))
433  return FALSE;
434  Stream_Write(s, auth->auth_value, header->auth_length);
435  return TRUE;
436 }
437 
438 static BOOL rts_read_version(wStream* s, p_rt_version_t* version, BOOL silent)
439 {
440  WINPR_ASSERT(s);
441  WINPR_ASSERT(version);
442 
443  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2 * sizeof(UINT8), silent))
444  return FALSE;
445  Stream_Read_UINT8(s, version->major);
446  Stream_Read_UINT8(s, version->minor);
447  return TRUE;
448 }
449 
450 static void rts_free_supported_versions(p_rt_versions_supported_t* versions)
451 {
452  if (!versions)
453  return;
454  free(versions->p_protocols);
455  versions->p_protocols = NULL;
456 }
457 
458 static BOOL rts_read_supported_versions(wStream* s, p_rt_versions_supported_t* versions,
459  BOOL silent)
460 {
461  WINPR_ASSERT(s);
462  WINPR_ASSERT(versions);
463 
464  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, sizeof(UINT8), silent))
465  return FALSE;
466 
467  Stream_Read_UINT8(s, versions->n_protocols); /* count */
468 
469  if (versions->n_protocols > 0)
470  {
471  versions->p_protocols = calloc(versions->n_protocols, sizeof(p_rt_version_t));
472  if (!versions->p_protocols)
473  return FALSE;
474  }
475  for (BYTE x = 0; x < versions->n_protocols; x++)
476  {
477  p_rt_version_t* version = &versions->p_protocols[x];
478  if (!rts_read_version(s, version, silent)) /* size_is(n_protocols) */
479  {
480  rts_free_supported_versions(versions);
481  return FALSE;
482  }
483  }
484 
485  return TRUE;
486 }
487 
488 static BOOL rts_read_port_any(wStream* s, port_any_t* port, BOOL silent)
489 {
490  WINPR_ASSERT(s);
491  WINPR_ASSERT(port);
492 
493  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, sizeof(UINT16), silent))
494  return FALSE;
495 
496  Stream_Read_UINT16(s, port->length);
497  if (port->length == 0)
498  return TRUE;
499 
500  const void* ptr = Stream_ConstPointer(s);
501  if (!Stream_ConditionalSafeSeek(s, port->length, silent))
502  return FALSE;
503  port->port_spec = sdup(ptr, port->length);
504  return port->port_spec != NULL;
505 }
506 
507 static void rts_free_port_any(port_any_t* port)
508 {
509  if (!port)
510  return;
511  free(port->port_spec);
512 }
513 
514 static BOOL rts_read_uuid(wStream* s, p_uuid_t* uuid, BOOL silent)
515 {
516  WINPR_ASSERT(s);
517  WINPR_ASSERT(uuid);
518 
519  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, sizeof(p_uuid_t), silent))
520  return FALSE;
521 
522  Stream_Read_UINT32(s, uuid->time_low);
523  Stream_Read_UINT16(s, uuid->time_mid);
524  Stream_Read_UINT16(s, uuid->time_hi_and_version);
525  Stream_Read_UINT8(s, uuid->clock_seq_hi_and_reserved);
526  Stream_Read_UINT8(s, uuid->clock_seq_low);
527  Stream_Read(s, uuid->node, ARRAYSIZE(uuid->node));
528  return TRUE;
529 }
530 
531 static BOOL rts_write_uuid(wStream* s, const p_uuid_t* uuid)
532 {
533  WINPR_ASSERT(s);
534  WINPR_ASSERT(uuid);
535 
536  if (!Stream_EnsureRemainingCapacity(s, sizeof(p_uuid_t)))
537  return FALSE;
538 
539  Stream_Write_UINT32(s, uuid->time_low);
540  Stream_Write_UINT16(s, uuid->time_mid);
541  Stream_Write_UINT16(s, uuid->time_hi_and_version);
542  Stream_Write_UINT8(s, uuid->clock_seq_hi_and_reserved);
543  Stream_Write_UINT8(s, uuid->clock_seq_low);
544  Stream_Write(s, uuid->node, ARRAYSIZE(uuid->node));
545  return TRUE;
546 }
547 
548 static p_syntax_id_t* rts_syntax_id_new(size_t count)
549 {
550  return calloc(count, sizeof(p_syntax_id_t));
551 }
552 
553 static void rts_syntax_id_free(p_syntax_id_t* ptr)
554 {
555  free(ptr);
556 }
557 
558 static BOOL rts_read_syntax_id(wStream* s, p_syntax_id_t* syntax_id, BOOL silent)
559 {
560  WINPR_ASSERT(s);
561  WINPR_ASSERT(syntax_id);
562 
563  if (!rts_read_uuid(s, &syntax_id->if_uuid, silent))
564  return FALSE;
565 
566  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
567  return FALSE;
568 
569  Stream_Read_UINT32(s, syntax_id->if_version);
570  return TRUE;
571 }
572 
573 static BOOL rts_write_syntax_id(wStream* s, const p_syntax_id_t* syntax_id)
574 {
575  WINPR_ASSERT(s);
576  WINPR_ASSERT(syntax_id);
577 
578  if (!rts_write_uuid(s, &syntax_id->if_uuid))
579  return FALSE;
580 
581  if (!Stream_EnsureRemainingCapacity(s, 4))
582  return FALSE;
583 
584  Stream_Write_UINT32(s, syntax_id->if_version);
585  return TRUE;
586 }
587 
588 static p_cont_elem_t* rts_context_elem_new(size_t count)
589 {
590  p_cont_elem_t* ctx = calloc(count, sizeof(p_cont_elem_t));
591  return ctx;
592 }
593 
594 static void rts_context_elem_free(p_cont_elem_t* ptr)
595 {
596  if (!ptr)
597  return;
598  rts_syntax_id_free(ptr->transfer_syntaxes);
599  free(ptr);
600 }
601 
602 static BOOL rts_read_context_elem(wStream* s, p_cont_elem_t* element, BOOL silent)
603 {
604  WINPR_ASSERT(s);
605  WINPR_ASSERT(element);
606 
607  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
608  return FALSE;
609 
610  Stream_Read_UINT16(s, element->p_cont_id);
611  Stream_Read_UINT8(s, element->n_transfer_syn); /* number of items */
612  Stream_Read_UINT8(s, element->reserved); /* alignment pad, m.b.z. */
613 
614  if (!rts_read_syntax_id(s, &element->abstract_syntax, silent)) /* transfer syntax list */
615  return FALSE;
616 
617  if (element->n_transfer_syn > 0)
618  {
619  element->transfer_syntaxes = rts_syntax_id_new(element->n_transfer_syn);
620  if (!element->transfer_syntaxes)
621  return FALSE;
622  for (BYTE x = 0; x < element->n_transfer_syn; x++)
623  {
624  p_syntax_id_t* syn = &element->transfer_syntaxes[x];
625  if (!rts_read_syntax_id(s, syn, silent)) /* size_is(n_transfer_syn) */
626  return FALSE;
627  }
628  }
629 
630  return TRUE;
631 }
632 
633 static BOOL rts_write_context_elem(wStream* s, const p_cont_elem_t* element)
634 {
635  WINPR_ASSERT(s);
636  WINPR_ASSERT(element);
637 
638  if (!Stream_EnsureRemainingCapacity(s, 4))
639  return FALSE;
640  Stream_Write_UINT16(s, element->p_cont_id);
641  Stream_Write_UINT8(s, element->n_transfer_syn); /* number of items */
642  Stream_Write_UINT8(s, element->reserved); /* alignment pad, m.b.z. */
643  if (!rts_write_syntax_id(s, &element->abstract_syntax)) /* transfer syntax list */
644  return FALSE;
645 
646  for (BYTE x = 0; x < element->n_transfer_syn; x++)
647  {
648  const p_syntax_id_t* syn = &element->transfer_syntaxes[x];
649  if (!rts_write_syntax_id(s, syn)) /* size_is(n_transfer_syn) */
650  return FALSE;
651  }
652 
653  return TRUE;
654 }
655 
656 static BOOL rts_read_context_list(wStream* s, p_cont_list_t* list, BOOL silent)
657 {
658  WINPR_ASSERT(s);
659  WINPR_ASSERT(list);
660 
661  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
662  return FALSE;
663  Stream_Read_UINT8(s, list->n_context_elem); /* number of items */
664  Stream_Read_UINT8(s, list->reserved); /* alignment pad, m.b.z. */
665  Stream_Read_UINT16(s, list->reserved2); /* alignment pad, m.b.z. */
666 
667  if (list->n_context_elem > 0)
668  {
669  list->p_cont_elem = rts_context_elem_new(list->n_context_elem);
670  if (!list->p_cont_elem)
671  return FALSE;
672  for (BYTE x = 0; x < list->n_context_elem; x++)
673  {
674  p_cont_elem_t* element = &list->p_cont_elem[x];
675  if (!rts_read_context_elem(s, element, silent))
676  return FALSE;
677  }
678  }
679  return TRUE;
680 }
681 
682 static void rts_free_context_list(p_cont_list_t* list)
683 {
684  if (!list)
685  return;
686  rts_context_elem_free(list->p_cont_elem);
687 }
688 
689 static BOOL rts_write_context_list(wStream* s, const p_cont_list_t* list)
690 {
691  WINPR_ASSERT(s);
692  WINPR_ASSERT(list);
693 
694  if (!Stream_EnsureRemainingCapacity(s, 4))
695  return FALSE;
696  Stream_Write_UINT8(s, list->n_context_elem); /* number of items */
697  Stream_Write_UINT8(s, 0); /* alignment pad, m.b.z. */
698  Stream_Write_UINT16(s, 0); /* alignment pad, m.b.z. */
699 
700  for (BYTE x = 0; x < list->n_context_elem; x++)
701  {
702  const p_cont_elem_t* element = &list->p_cont_elem[x];
703  if (!rts_write_context_elem(s, element))
704  return FALSE;
705  }
706  return TRUE;
707 }
708 
709 static p_result_t* rts_result_new(size_t count)
710 {
711  return calloc(count, sizeof(p_result_t));
712 }
713 
714 static void rts_result_free(p_result_t* results)
715 {
716  if (!results)
717  return;
718  free(results);
719 }
720 
721 static BOOL rts_read_result(wStream* s, p_result_t* result, BOOL silent)
722 {
723  WINPR_ASSERT(s);
724  WINPR_ASSERT(result);
725 
726  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2, silent))
727  return FALSE;
728  Stream_Read_UINT16(s, result->result);
729  Stream_Read_UINT16(s, result->reason);
730 
731  return rts_read_syntax_id(s, &result->transfer_syntax, silent);
732 }
733 
734 static void rts_free_result(p_result_t* result)
735 {
736  if (!result)
737  return;
738 }
739 
740 static BOOL rts_read_result_list(wStream* s, p_result_list_t* list, BOOL silent)
741 {
742  WINPR_ASSERT(s);
743  WINPR_ASSERT(list);
744 
745  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
746  return FALSE;
747  Stream_Read_UINT8(s, list->n_results); /* count */
748  Stream_Read_UINT8(s, list->reserved); /* alignment pad, m.b.z. */
749  Stream_Read_UINT16(s, list->reserved2); /* alignment pad, m.b.z. */
750 
751  if (list->n_results > 0)
752  {
753  list->p_results = rts_result_new(list->n_results);
754  if (!list->p_results)
755  return FALSE;
756 
757  for (BYTE x = 0; x < list->n_results; x++)
758  {
759  p_result_t* result = &list->p_results[x]; /* size_is(n_results) */
760  if (!rts_read_result(s, result, silent))
761  return FALSE;
762  }
763  }
764 
765  return TRUE;
766 }
767 
768 static void rts_free_result_list(p_result_list_t* list)
769 {
770  if (!list)
771  return;
772  for (BYTE x = 0; x < list->n_results; x++)
773  {
774  p_result_t* result = &list->p_results[x];
775  rts_free_result(result);
776  }
777  rts_result_free(list->p_results);
778 }
779 
780 static void rts_free_pdu_alter_context(rpcconn_alter_context_hdr_t* ctx)
781 {
782  if (!ctx)
783  return;
784 
785  rts_free_context_list(&ctx->p_context_elem);
786  rts_free_auth_verifier(&ctx->auth_verifier);
787 }
788 
789 static BOOL rts_read_pdu_alter_context(wStream* s, rpcconn_alter_context_hdr_t* ctx, BOOL silent)
790 {
791  WINPR_ASSERT(s);
792  WINPR_ASSERT(ctx);
793 
794  if (!Stream_ConditionalCheckAndLogRequiredLength(
795  TAG, s, sizeof(rpcconn_alter_context_hdr_t) - sizeof(rpcconn_common_hdr_t), silent))
796  return FALSE;
797 
798  Stream_Read_UINT16(s, ctx->max_xmit_frag);
799  Stream_Read_UINT16(s, ctx->max_recv_frag);
800  Stream_Read_UINT32(s, ctx->assoc_group_id);
801 
802  if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
803  return FALSE;
804 
805  if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
806  return FALSE;
807 
808  return TRUE;
809 }
810 
811 static BOOL rts_read_pdu_alter_context_response(wStream* s,
813  BOOL silent)
814 {
815  WINPR_ASSERT(s);
816  WINPR_ASSERT(ctx);
817 
818  if (!Stream_ConditionalCheckAndLogRequiredLength(
820  silent))
821  return FALSE;
822  Stream_Read_UINT16(s, ctx->max_xmit_frag);
823  Stream_Read_UINT16(s, ctx->max_recv_frag);
824  Stream_Read_UINT32(s, ctx->assoc_group_id);
825 
826  if (!rts_read_port_any(s, &ctx->sec_addr, silent))
827  return FALSE;
828 
829  if (!rts_align_stream(s, 4, silent))
830  return FALSE;
831 
832  if (!rts_read_result_list(s, &ctx->p_result_list, silent))
833  return FALSE;
834 
835  if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
836  return FALSE;
837 
838  return TRUE;
839 }
840 
841 static void rts_free_pdu_alter_context_response(rpcconn_alter_context_response_hdr_t* ctx)
842 {
843  if (!ctx)
844  return;
845 
846  rts_free_port_any(&ctx->sec_addr);
847  rts_free_result_list(&ctx->p_result_list);
848  rts_free_auth_verifier(&ctx->auth_verifier);
849 }
850 
851 static BOOL rts_read_pdu_bind(wStream* s, rpcconn_bind_hdr_t* ctx, BOOL silent)
852 {
853  WINPR_ASSERT(s);
854  WINPR_ASSERT(ctx);
855 
856  if (!Stream_ConditionalCheckAndLogRequiredLength(
857  TAG, s, sizeof(rpcconn_bind_hdr_t) - sizeof(rpcconn_common_hdr_t), silent))
858  return FALSE;
859  Stream_Read_UINT16(s, ctx->max_xmit_frag);
860  Stream_Read_UINT16(s, ctx->max_recv_frag);
861  Stream_Read_UINT32(s, ctx->assoc_group_id);
862 
863  if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
864  return FALSE;
865 
866  if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
867  return FALSE;
868 
869  return TRUE;
870 }
871 
872 static void rts_free_pdu_bind(rpcconn_bind_hdr_t* ctx)
873 {
874  if (!ctx)
875  return;
876  rts_free_context_list(&ctx->p_context_elem);
877  rts_free_auth_verifier(&ctx->auth_verifier);
878 }
879 
880 static BOOL rts_read_pdu_bind_ack(wStream* s, rpcconn_bind_ack_hdr_t* ctx, BOOL silent)
881 {
882  WINPR_ASSERT(s);
883  WINPR_ASSERT(ctx);
884 
885  if (!Stream_CheckAndLogRequiredLength(
886  TAG, s, sizeof(rpcconn_bind_ack_hdr_t) - sizeof(rpcconn_common_hdr_t)))
887  return FALSE;
888  Stream_Read_UINT16(s, ctx->max_xmit_frag);
889  Stream_Read_UINT16(s, ctx->max_recv_frag);
890  Stream_Read_UINT32(s, ctx->assoc_group_id);
891 
892  if (!rts_read_port_any(s, &ctx->sec_addr, silent))
893  return FALSE;
894 
895  if (!rts_align_stream(s, 4, silent))
896  return FALSE;
897 
898  if (!rts_read_result_list(s, &ctx->p_result_list, silent))
899  return FALSE;
900 
901  return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
902 }
903 
904 static void rts_free_pdu_bind_ack(rpcconn_bind_ack_hdr_t* ctx)
905 {
906  if (!ctx)
907  return;
908  rts_free_port_any(&ctx->sec_addr);
909  rts_free_result_list(&ctx->p_result_list);
910  rts_free_auth_verifier(&ctx->auth_verifier);
911 }
912 
913 static BOOL rts_read_pdu_bind_nak(wStream* s, rpcconn_bind_nak_hdr_t* ctx, BOOL silent)
914 {
915  WINPR_ASSERT(s);
916  WINPR_ASSERT(ctx);
917 
918  if (!Stream_ConditionalCheckAndLogRequiredLength(
919  TAG, s, sizeof(rpcconn_bind_nak_hdr_t) - sizeof(rpcconn_common_hdr_t), silent))
920  return FALSE;
921  Stream_Read_UINT16(s, ctx->provider_reject_reason);
922  return rts_read_supported_versions(s, &ctx->versions, silent);
923 }
924 
925 static void rts_free_pdu_bind_nak(rpcconn_bind_nak_hdr_t* ctx)
926 {
927  if (!ctx)
928  return;
929 
930  rts_free_supported_versions(&ctx->versions);
931 }
932 
933 static BOOL rts_read_pdu_auth3(wStream* s, rpcconn_rpc_auth_3_hdr_t* ctx, BOOL silent)
934 {
935  WINPR_ASSERT(s);
936  WINPR_ASSERT(ctx);
937 
938  if (!Stream_ConditionalCheckAndLogRequiredLength(
939  TAG, s, sizeof(rpcconn_rpc_auth_3_hdr_t) - sizeof(rpcconn_common_hdr_t), silent))
940  return FALSE;
941  Stream_Read_UINT16(s, ctx->max_xmit_frag);
942  Stream_Read_UINT16(s, ctx->max_recv_frag);
943 
944  return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
945 }
946 
947 static void rts_free_pdu_auth3(rpcconn_rpc_auth_3_hdr_t* ctx)
948 {
949  if (!ctx)
950  return;
951  rts_free_auth_verifier(&ctx->auth_verifier);
952 }
953 
954 static BOOL rts_read_pdu_fault(wStream* s, rpcconn_fault_hdr_t* ctx, BOOL silent)
955 {
956  WINPR_ASSERT(s);
957  WINPR_ASSERT(ctx);
958 
959  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 12, silent))
960  return FALSE;
961  Stream_Read_UINT32(s, ctx->alloc_hint);
962  Stream_Read_UINT16(s, ctx->p_cont_id);
963  Stream_Read_UINT8(s, ctx->cancel_count);
964  Stream_Read_UINT8(s, ctx->reserved);
965  Stream_Read_UINT32(s, ctx->status);
966 
967  WLog_WARN(TAG, "status=%s", Win32ErrorCode2Tag(ctx->status & 0xFFFF));
968  return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
969 }
970 
971 static void rts_free_pdu_fault(rpcconn_fault_hdr_t* ctx)
972 {
973  if (!ctx)
974  return;
975  rts_free_auth_verifier(&ctx->auth_verifier);
976 }
977 
978 static BOOL rts_read_pdu_cancel_ack(wStream* s, rpcconn_cancel_hdr_t* ctx, BOOL silent)
979 {
980  WINPR_ASSERT(s);
981  WINPR_ASSERT(ctx);
982 
983  if (!Stream_ConditionalCheckAndLogRequiredLength(
984  TAG, s, sizeof(rpcconn_cancel_hdr_t) - sizeof(rpcconn_common_hdr_t), silent))
985  return FALSE;
986  return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
987 }
988 
989 static void rts_free_pdu_cancel_ack(rpcconn_cancel_hdr_t* ctx)
990 {
991  if (!ctx)
992  return;
993  rts_free_auth_verifier(&ctx->auth_verifier);
994 }
995 
996 static BOOL rts_read_pdu_orphaned(wStream* s, rpcconn_orphaned_hdr_t* ctx, BOOL silent)
997 {
998  WINPR_ASSERT(s);
999  WINPR_ASSERT(ctx);
1000 
1001  if (!Stream_ConditionalCheckAndLogRequiredLength(
1002  TAG, s, sizeof(rpcconn_orphaned_hdr_t) - sizeof(rpcconn_common_hdr_t), silent))
1003  return FALSE;
1004  return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1005 }
1006 
1007 static void rts_free_pdu_orphaned(rpcconn_orphaned_hdr_t* ctx)
1008 {
1009  if (!ctx)
1010  return;
1011  rts_free_auth_verifier(&ctx->auth_verifier);
1012 }
1013 
1014 static BOOL rts_read_pdu_request(wStream* s, rpcconn_request_hdr_t* ctx, BOOL silent)
1015 {
1016  WINPR_ASSERT(s);
1017  WINPR_ASSERT(ctx);
1018 
1019  if (!Stream_ConditionalCheckAndLogRequiredLength(
1020  TAG, s, sizeof(rpcconn_request_hdr_t) - sizeof(rpcconn_common_hdr_t), silent))
1021  return FALSE;
1022  Stream_Read_UINT32(s, ctx->alloc_hint);
1023  Stream_Read_UINT16(s, ctx->p_cont_id);
1024  Stream_Read_UINT16(s, ctx->opnum);
1025  if (!rts_read_uuid(s, &ctx->object, silent))
1026  return FALSE;
1027 
1028  return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1029 }
1030 
1031 static void rts_free_pdu_request(rpcconn_request_hdr_t* ctx)
1032 {
1033  if (!ctx)
1034  return;
1035  rts_free_auth_verifier(&ctx->auth_verifier);
1036 }
1037 
1038 static BOOL rts_read_pdu_response(wStream* s, rpcconn_response_hdr_t* ctx, BOOL silent)
1039 {
1040  WINPR_ASSERT(s);
1041  WINPR_ASSERT(ctx);
1042 
1043  if (!Stream_ConditionalCheckAndLogRequiredLength(
1044  TAG, s, sizeof(rpcconn_response_hdr_t) - sizeof(rpcconn_common_hdr_t), silent))
1045  return FALSE;
1046  Stream_Read_UINT32(s, ctx->alloc_hint);
1047  Stream_Read_UINT16(s, ctx->p_cont_id);
1048  Stream_Read_UINT8(s, ctx->cancel_count);
1049  Stream_Read_UINT8(s, ctx->reserved);
1050 
1051  if (!rts_align_stream(s, 8, silent))
1052  return FALSE;
1053 
1054  return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1055 }
1056 
1057 static void rts_free_pdu_response(rpcconn_response_hdr_t* ctx)
1058 {
1059  if (!ctx)
1060  return;
1061  free(ctx->stub_data);
1062  rts_free_auth_verifier(&ctx->auth_verifier);
1063 }
1064 
1065 static BOOL rts_read_pdu_rts(wStream* s, rpcconn_rts_hdr_t* ctx, BOOL silent)
1066 {
1067  WINPR_ASSERT(s);
1068  WINPR_ASSERT(ctx);
1069 
1070  if (!Stream_ConditionalCheckAndLogRequiredLength(
1071  TAG, s, sizeof(rpcconn_rts_hdr_t) - sizeof(rpcconn_common_hdr_t), silent))
1072  return FALSE;
1073 
1074  Stream_Read_UINT16(s, ctx->Flags);
1075  Stream_Read_UINT16(s, ctx->NumberOfCommands);
1076  return TRUE;
1077 }
1078 
1079 static void rts_free_pdu_rts(rpcconn_rts_hdr_t* ctx)
1080 {
1081  WINPR_UNUSED(ctx);
1082 }
1083 
1084 void rts_free_pdu_header(rpcconn_hdr_t* header, BOOL allocated)
1085 {
1086  if (!header)
1087  return;
1088 
1089  switch (header->common.ptype)
1090  {
1091  case PTYPE_ALTER_CONTEXT:
1092  rts_free_pdu_alter_context(&header->alter_context);
1093  break;
1094  case PTYPE_ALTER_CONTEXT_RESP:
1095  rts_free_pdu_alter_context_response(&header->alter_context_response);
1096  break;
1097  case PTYPE_BIND:
1098  rts_free_pdu_bind(&header->bind);
1099  break;
1100  case PTYPE_BIND_ACK:
1101  rts_free_pdu_bind_ack(&header->bind_ack);
1102  break;
1103  case PTYPE_BIND_NAK:
1104  rts_free_pdu_bind_nak(&header->bind_nak);
1105  break;
1106  case PTYPE_RPC_AUTH_3:
1107  rts_free_pdu_auth3(&header->rpc_auth_3);
1108  break;
1109  case PTYPE_CANCEL_ACK:
1110  rts_free_pdu_cancel_ack(&header->cancel);
1111  break;
1112  case PTYPE_FAULT:
1113  rts_free_pdu_fault(&header->fault);
1114  break;
1115  case PTYPE_ORPHANED:
1116  rts_free_pdu_orphaned(&header->orphaned);
1117  break;
1118  case PTYPE_REQUEST:
1119  rts_free_pdu_request(&header->request);
1120  break;
1121  case PTYPE_RESPONSE:
1122  rts_free_pdu_response(&header->response);
1123  break;
1124  case PTYPE_RTS:
1125  rts_free_pdu_rts(&header->rts);
1126  break;
1127  /* No extra fields */
1128  case PTYPE_SHUTDOWN:
1129  break;
1130 
1131  /* not handled */
1132  case PTYPE_PING:
1133  case PTYPE_WORKING:
1134  case PTYPE_NOCALL:
1135  case PTYPE_REJECT:
1136  case PTYPE_ACK:
1137  case PTYPE_CL_CANCEL:
1138  case PTYPE_FACK:
1139  case PTYPE_CO_CANCEL:
1140  default:
1141  break;
1142  }
1143 
1144  if (allocated)
1145  free(header);
1146 }
1147 
1148 BOOL rts_read_pdu_header(wStream* s, rpcconn_hdr_t* header)
1149 {
1150  return rts_read_pdu_header_ex(s, header, FALSE);
1151 }
1152 
1153 BOOL rts_read_pdu_header_ex(wStream* s, rpcconn_hdr_t* header, BOOL silent)
1154 {
1155  BOOL rc = FALSE;
1156  WINPR_ASSERT(s);
1157  WINPR_ASSERT(header);
1158 
1159  if (!rts_read_common_pdu_header(s, &header->common, silent))
1160  return FALSE;
1161 
1162  WLog_DBG(TAG, "Reading PDU type %s", rts_pdu_ptype_to_string(header->common.ptype));
1163 
1164  switch (header->common.ptype)
1165  {
1166  case PTYPE_ALTER_CONTEXT:
1167  rc = rts_read_pdu_alter_context(s, &header->alter_context, silent);
1168  break;
1169  case PTYPE_ALTER_CONTEXT_RESP:
1170  rc = rts_read_pdu_alter_context_response(s, &header->alter_context_response, silent);
1171  break;
1172  case PTYPE_BIND:
1173  rc = rts_read_pdu_bind(s, &header->bind, silent);
1174  break;
1175  case PTYPE_BIND_ACK:
1176  rc = rts_read_pdu_bind_ack(s, &header->bind_ack, silent);
1177  break;
1178  case PTYPE_BIND_NAK:
1179  rc = rts_read_pdu_bind_nak(s, &header->bind_nak, silent);
1180  break;
1181  case PTYPE_RPC_AUTH_3:
1182  rc = rts_read_pdu_auth3(s, &header->rpc_auth_3, silent);
1183  break;
1184  case PTYPE_CANCEL_ACK:
1185  rc = rts_read_pdu_cancel_ack(s, &header->cancel, silent);
1186  break;
1187  case PTYPE_FAULT:
1188  rc = rts_read_pdu_fault(s, &header->fault, silent);
1189  break;
1190  case PTYPE_ORPHANED:
1191  rc = rts_read_pdu_orphaned(s, &header->orphaned, silent);
1192  break;
1193  case PTYPE_REQUEST:
1194  rc = rts_read_pdu_request(s, &header->request, silent);
1195  break;
1196  case PTYPE_RESPONSE:
1197  rc = rts_read_pdu_response(s, &header->response, silent);
1198  break;
1199  case PTYPE_RTS:
1200  rc = rts_read_pdu_rts(s, &header->rts, silent);
1201  break;
1202  case PTYPE_SHUTDOWN:
1203  rc = TRUE; /* No extra fields */
1204  break;
1205 
1206  /* not handled */
1207  case PTYPE_PING:
1208  case PTYPE_WORKING:
1209  case PTYPE_NOCALL:
1210  case PTYPE_REJECT:
1211  case PTYPE_ACK:
1212  case PTYPE_CL_CANCEL:
1213  case PTYPE_FACK:
1214  case PTYPE_CO_CANCEL:
1215  default:
1216  break;
1217  }
1218 
1219  return rc;
1220 }
1221 
1222 static BOOL rts_write_pdu_header(wStream* s, const rpcconn_rts_hdr_t* header)
1223 {
1224  WINPR_ASSERT(s);
1225  WINPR_ASSERT(header);
1226  if (!Stream_EnsureRemainingCapacity(s, sizeof(rpcconn_rts_hdr_t)))
1227  return FALSE;
1228 
1229  if (!rts_write_common_pdu_header(s, &header->header))
1230  return FALSE;
1231 
1232  Stream_Write_UINT16(s, header->Flags);
1233  Stream_Write_UINT16(s, header->NumberOfCommands);
1234  return TRUE;
1235 }
1236 
1237 static BOOL rts_receive_window_size_command_read(rdpRpc* rpc, wStream* buffer,
1238  UINT64* ReceiveWindowSize)
1239 {
1240  WINPR_ASSERT(rpc);
1241  WINPR_ASSERT(buffer);
1242 
1243  if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1244  return FALSE;
1245  const UINT64 val = Stream_Get_UINT64(buffer);
1246  if (ReceiveWindowSize)
1247  *ReceiveWindowSize = val; /* ReceiveWindowSize (8 bytes) */
1248 
1249  return TRUE;
1250 }
1251 
1252 static BOOL rts_receive_window_size_command_write(wStream* s, UINT32 ReceiveWindowSize)
1253 {
1254  WINPR_ASSERT(s);
1255 
1256  if (!Stream_EnsureRemainingCapacity(s, 2 * sizeof(UINT32)))
1257  return FALSE;
1258 
1259  Stream_Write_UINT32(s, RTS_CMD_RECEIVE_WINDOW_SIZE); /* CommandType (4 bytes) */
1260  Stream_Write_UINT32(s, ReceiveWindowSize); /* ReceiveWindowSize (4 bytes) */
1261 
1262  return TRUE;
1263 }
1264 
1265 static int rts_flow_control_ack_command_read(rdpRpc* rpc, wStream* buffer, UINT32* BytesReceived,
1266  UINT32* AvailableWindow, BYTE* ChannelCookie)
1267 {
1268  UINT32 val = 0;
1269  UINT32 Command = 0;
1270 
1271  WINPR_ASSERT(rpc);
1272  WINPR_ASSERT(buffer);
1273 
1274  int rc = rts_destination_command_read(rpc, buffer, &Command);
1275  if (rc < 0)
1276  return rc;
1277 
1278  if (Command != RTS_CMD_FLOW_CONTROL_ACK)
1279  {
1280  char buffer1[64] = { 0 };
1281  char buffer2[64] = { 0 };
1282  WLog_Print(rpc->log, WLOG_ERROR, "got command %s, expected %s",
1283  rts_command_to_string(Command, buffer1, sizeof(buffer1)),
1284  rts_command_to_string(RTS_CMD_FLOW_CONTROL_ACK, buffer2, sizeof(buffer2)));
1285  return -1;
1286  }
1287 
1288  /* Ack (24 bytes) */
1289  if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 24))
1290  return -1;
1291 
1292  Stream_Read_UINT32(buffer, val);
1293  if (BytesReceived)
1294  *BytesReceived = val; /* BytesReceived (4 bytes) */
1295 
1296  Stream_Read_UINT32(buffer, val);
1297  if (AvailableWindow)
1298  *AvailableWindow = val; /* AvailableWindow (4 bytes) */
1299 
1300  if (ChannelCookie)
1301  Stream_Read(buffer, ChannelCookie, 16); /* ChannelCookie (16 bytes) */
1302  else
1303  Stream_Seek(buffer, 16);
1304  return 24;
1305 }
1306 
1307 static BOOL rts_flow_control_ack_command_write(wStream* s, UINT32 BytesReceived,
1308  UINT32 AvailableWindow, BYTE* ChannelCookie)
1309 {
1310  WINPR_ASSERT(s);
1311 
1312  if (!Stream_EnsureRemainingCapacity(s, 28))
1313  return FALSE;
1314 
1315  Stream_Write_UINT32(s, RTS_CMD_FLOW_CONTROL_ACK); /* CommandType (4 bytes) */
1316  Stream_Write_UINT32(s, BytesReceived); /* BytesReceived (4 bytes) */
1317  Stream_Write_UINT32(s, AvailableWindow); /* AvailableWindow (4 bytes) */
1318  Stream_Write(s, ChannelCookie, 16); /* ChannelCookie (16 bytes) */
1319 
1320  return TRUE;
1321 }
1322 
1323 static BOOL rts_connection_timeout_command_read(rdpRpc* rpc, wStream* buffer,
1324  UINT64* ConnectionTimeout)
1325 {
1326  WINPR_ASSERT(rpc);
1327  WINPR_ASSERT(buffer);
1328 
1329  if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1330  return FALSE;
1331 
1332  UINT64 val = Stream_Get_UINT64(buffer);
1333  if (ConnectionTimeout)
1334  *ConnectionTimeout = val; /* ConnectionTimeout (8 bytes) */
1335 
1336  return TRUE;
1337 }
1338 
1339 static BOOL rts_cookie_command_write(wStream* s, const BYTE* Cookie)
1340 {
1341  WINPR_ASSERT(s);
1342 
1343  if (!Stream_EnsureRemainingCapacity(s, 20))
1344  return FALSE;
1345 
1346  Stream_Write_UINT32(s, RTS_CMD_COOKIE); /* CommandType (4 bytes) */
1347  Stream_Write(s, Cookie, 16); /* Cookie (16 bytes) */
1348 
1349  return TRUE;
1350 }
1351 
1352 static BOOL rts_channel_lifetime_command_write(wStream* s, UINT32 ChannelLifetime)
1353 {
1354  WINPR_ASSERT(s);
1355 
1356  if (!Stream_EnsureRemainingCapacity(s, 8))
1357  return FALSE;
1358  Stream_Write_UINT32(s, RTS_CMD_CHANNEL_LIFETIME); /* CommandType (4 bytes) */
1359  Stream_Write_UINT32(s, ChannelLifetime); /* ChannelLifetime (4 bytes) */
1360 
1361  return TRUE;
1362 }
1363 
1364 static BOOL rts_client_keepalive_command_write(wStream* s, UINT32 ClientKeepalive)
1365 {
1366  WINPR_ASSERT(s);
1367 
1368  if (!Stream_EnsureRemainingCapacity(s, 8))
1369  return FALSE;
1376  Stream_Write_UINT32(s, RTS_CMD_CLIENT_KEEPALIVE); /* CommandType (4 bytes) */
1377  Stream_Write_UINT32(s, ClientKeepalive); /* ClientKeepalive (4 bytes) */
1378 
1379  return TRUE;
1380 }
1381 
1382 static BOOL rts_version_command_read(rdpRpc* rpc, wStream* buffer)
1383 {
1384  WINPR_ASSERT(rpc);
1385  WINPR_ASSERT(buffer);
1386 
1387  if (!Stream_SafeSeek(buffer, 8))
1388  return FALSE;
1389 
1390  /* command (4 bytes) */
1391  /* Version (4 bytes) */
1392  return TRUE;
1393 }
1394 
1395 static BOOL rts_version_command_write(wStream* buffer)
1396 {
1397  WINPR_ASSERT(buffer);
1398 
1399  if (!Stream_EnsureRemainingCapacity((buffer), 8))
1400  return FALSE;
1401 
1402  Stream_Write_UINT32(buffer, RTS_CMD_VERSION); /* CommandType (4 bytes) */
1403  Stream_Write_UINT32(buffer, 1); /* Version (4 bytes) */
1404 
1405  return TRUE;
1406 }
1407 
1408 static BOOL rts_empty_command_write(wStream* s)
1409 {
1410  WINPR_ASSERT(s);
1411 
1412  if (!Stream_EnsureRemainingCapacity(s, 8))
1413  return FALSE;
1414 
1415  Stream_Write_UINT32(s, RTS_CMD_EMPTY); /* CommandType (4 bytes) */
1416 
1417  return TRUE;
1418 }
1419 
1420 static BOOL rts_padding_command_read(wStream* s, size_t* length, BOOL silent)
1421 {
1422  UINT32 ConformanceCount = 0;
1423  WINPR_ASSERT(s);
1424  WINPR_ASSERT(length);
1425  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1426  return FALSE;
1427  Stream_Read_UINT32(s, ConformanceCount); /* ConformanceCount (4 bytes) */
1428  *length = ConformanceCount + 4;
1429  return TRUE;
1430 }
1431 
1432 static BOOL rts_client_address_command_read(wStream* s, size_t* length, BOOL silent)
1433 {
1434  UINT32 AddressType = 0;
1435 
1436  WINPR_ASSERT(s);
1437  WINPR_ASSERT(length);
1438 
1439  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1440  return FALSE;
1441  Stream_Read_UINT32(s, AddressType); /* AddressType (4 bytes) */
1442 
1443  if (AddressType == 0)
1444  {
1445  /* ClientAddress (4 bytes) */
1446  /* padding (12 bytes) */
1447  *length = 4 + 4 + 12;
1448  }
1449  else
1450  {
1451  /* ClientAddress (16 bytes) */
1452  /* padding (12 bytes) */
1453  *length = 4 + 16 + 12;
1454  }
1455  return TRUE;
1456 }
1457 
1458 static BOOL rts_association_group_id_command_write(wStream* s, const BYTE* AssociationGroupId)
1459 {
1460  WINPR_ASSERT(s);
1461 
1462  if (!Stream_EnsureRemainingCapacity(s, 20))
1463  return FALSE;
1464 
1465  Stream_Write_UINT32(s, RTS_CMD_ASSOCIATION_GROUP_ID); /* CommandType (4 bytes) */
1466  Stream_Write(s, AssociationGroupId, 16); /* AssociationGroupId (16 bytes) */
1467 
1468  return TRUE;
1469 }
1470 
1471 static int rts_destination_command_read(rdpRpc* rpc, wStream* buffer, UINT32* Destination)
1472 {
1473  UINT32 val = 0;
1474  WINPR_ASSERT(rpc);
1475  WINPR_ASSERT(buffer);
1476 
1477  if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 4))
1478  return -1;
1479  Stream_Read_UINT32(buffer, val);
1480  if (Destination)
1481  *Destination = val; /* Destination (4 bytes) */
1482 
1483  return 4;
1484 }
1485 
1486 static BOOL rts_destination_command_write(wStream* s, UINT32 Destination)
1487 {
1488  WINPR_ASSERT(s);
1489 
1490  if (!Stream_EnsureRemainingCapacity(s, 8))
1491  return FALSE;
1492 
1493  Stream_Write_UINT32(s, RTS_CMD_DESTINATION); /* CommandType (4 bytes) */
1494  Stream_Write_UINT32(s, Destination); /* Destination (4 bytes) */
1495 
1496  return TRUE;
1497 }
1498 
1499 void rts_generate_cookie(BYTE* cookie)
1500 {
1501  WINPR_ASSERT(cookie);
1502  winpr_RAND(cookie, 16);
1503 }
1504 
1505 static BOOL rts_send_buffer(RpcChannel* channel, wStream* s, size_t frag_length)
1506 {
1507  BOOL status = FALSE;
1508  SSIZE_T rc = 0;
1509 
1510  WINPR_ASSERT(channel);
1511  WINPR_ASSERT(s);
1512 
1513  Stream_SealLength(s);
1514  if (Stream_Length(s) < sizeof(rpcconn_common_hdr_t))
1515  goto fail;
1516  if (Stream_Length(s) != frag_length)
1517  goto fail;
1518 
1519  rc = rpc_channel_write(channel, Stream_Buffer(s), Stream_Length(s));
1520  if (rc < 0)
1521  goto fail;
1522  if ((size_t)rc != Stream_Length(s))
1523  goto fail;
1524  status = TRUE;
1525 fail:
1526  return status;
1527 }
1528 
1529 /* CONN/A Sequence */
1530 
1531 BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc)
1532 {
1533  BOOL status = FALSE;
1534  wStream* buffer = NULL;
1535  rpcconn_rts_hdr_t header = rts_pdu_header_init();
1536  UINT32 ReceiveWindowSize = 0;
1537  BYTE* OUTChannelCookie = NULL;
1538  BYTE* VirtualConnectionCookie = NULL;
1539  RpcVirtualConnection* connection = NULL;
1540  RpcOutChannel* outChannel = NULL;
1541 
1542  WINPR_ASSERT(rpc);
1543 
1544  connection = rpc->VirtualConnection;
1545  WINPR_ASSERT(connection);
1546 
1547  outChannel = connection->DefaultOutChannel;
1548  WINPR_ASSERT(outChannel);
1549 
1550  header.header.frag_length = 76;
1551  header.Flags = RTS_FLAG_NONE;
1552  header.NumberOfCommands = 4;
1553 
1554  WLog_DBG(TAG, "Sending CONN/A1 RTS PDU");
1555  VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1556  OUTChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1557  ReceiveWindowSize = outChannel->ReceiveWindow;
1558 
1559  buffer = Stream_New(NULL, header.header.frag_length);
1560 
1561  if (!buffer)
1562  return -1;
1563 
1564  if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */
1565  goto fail;
1566  status = rts_version_command_write(buffer); /* Version (8 bytes) */
1567  if (!status)
1568  goto fail;
1569  status = rts_cookie_command_write(
1570  buffer, VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */
1571  if (!status)
1572  goto fail;
1573  status = rts_cookie_command_write(buffer, OUTChannelCookie); /* OUTChannelCookie (20 bytes) */
1574  if (!status)
1575  goto fail;
1576  status = rts_receive_window_size_command_write(
1577  buffer, ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
1578  if (!status)
1579  goto fail;
1580  status = rts_send_buffer(&outChannel->common, buffer, header.header.frag_length);
1581 fail:
1582  Stream_Free(buffer, TRUE);
1583  return status;
1584 }
1585 
1586 BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc, wStream* buffer)
1587 {
1588  BOOL rc = 0;
1589  UINT64 ConnectionTimeout = 0;
1590 
1591  if (!Stream_SafeSeek(buffer, 20))
1592  return FALSE;
1593 
1594  rc = rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout);
1595  if (!rc || (ConnectionTimeout > UINT32_MAX))
1596  return rc;
1597 
1598  WLog_DBG(TAG, "Receiving CONN/A3 RTS PDU: ConnectionTimeout: %" PRIu64 "", ConnectionTimeout);
1599 
1600  WINPR_ASSERT(rpc);
1601  WINPR_ASSERT(rpc->VirtualConnection);
1602  WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1603 
1604  rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout =
1605  (UINT32)ConnectionTimeout;
1606  return TRUE;
1607 }
1608 
1609 /* CONN/B Sequence */
1610 
1611 BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc)
1612 {
1613  BOOL status = FALSE;
1614  wStream* buffer = NULL;
1615  rpcconn_rts_hdr_t header = rts_pdu_header_init();
1616  BYTE* INChannelCookie = NULL;
1617  BYTE* AssociationGroupId = NULL;
1618  BYTE* VirtualConnectionCookie = NULL;
1619  RpcVirtualConnection* connection = NULL;
1620  RpcInChannel* inChannel = NULL;
1621 
1622  WINPR_ASSERT(rpc);
1623 
1624  connection = rpc->VirtualConnection;
1625  WINPR_ASSERT(connection);
1626 
1627  inChannel = connection->DefaultInChannel;
1628  WINPR_ASSERT(inChannel);
1629 
1630  header.header.frag_length = 104;
1631  header.Flags = RTS_FLAG_NONE;
1632  header.NumberOfCommands = 6;
1633 
1634  WLog_DBG(TAG, "Sending CONN/B1 RTS PDU");
1635 
1636  VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1637  INChannelCookie = (BYTE*)&(inChannel->common.Cookie);
1638  AssociationGroupId = (BYTE*)&(connection->AssociationGroupId);
1639  buffer = Stream_New(NULL, header.header.frag_length);
1640 
1641  if (!buffer)
1642  goto fail;
1643  if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */
1644  goto fail;
1645  if (!rts_version_command_write(buffer)) /* Version (8 bytes) */
1646  goto fail;
1647  if (!rts_cookie_command_write(buffer,
1648  VirtualConnectionCookie)) /* VirtualConnectionCookie (20 bytes) */
1649  goto fail;
1650  if (!rts_cookie_command_write(buffer, INChannelCookie)) /* INChannelCookie (20 bytes) */
1651  goto fail;
1652  if (!rts_channel_lifetime_command_write(buffer,
1653  rpc->ChannelLifetime)) /* ChannelLifetime (8 bytes) */
1654  goto fail;
1655  if (!rts_client_keepalive_command_write(buffer,
1656  rpc->KeepAliveInterval)) /* ClientKeepalive (8 bytes) */
1657  goto fail;
1658  if (!rts_association_group_id_command_write(
1659  buffer, AssociationGroupId)) /* AssociationGroupId (20 bytes) */
1660  goto fail;
1661  status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1662 fail:
1663  Stream_Free(buffer, TRUE);
1664  return status;
1665 }
1666 
1667 /* CONN/C Sequence */
1668 
1669 BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc, wStream* buffer)
1670 {
1671  BOOL rc = FALSE;
1672  UINT64 ReceiveWindowSize = 0;
1673  UINT64 ConnectionTimeout = 0;
1674 
1675  WINPR_ASSERT(rpc);
1676  WINPR_ASSERT(buffer);
1677 
1678  if (!Stream_SafeSeek(buffer, 20))
1679  return FALSE;
1680 
1681  rc = rts_version_command_read(rpc, buffer);
1682  if (!rc)
1683  return rc;
1684  rc = rts_receive_window_size_command_read(rpc, buffer, &ReceiveWindowSize);
1685  if (!rc || (ReceiveWindowSize > UINT32_MAX))
1686  return rc;
1687  rc = rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout);
1688  if (!rc || (ConnectionTimeout > UINT32_MAX))
1689  return rc;
1690 
1691  WLog_DBG(TAG,
1692  "Receiving CONN/C2 RTS PDU: ConnectionTimeout: %" PRIu64 " ReceiveWindowSize: %" PRIu64
1693  "",
1694  ConnectionTimeout, ReceiveWindowSize);
1695 
1696  WINPR_ASSERT(rpc);
1697  WINPR_ASSERT(rpc->VirtualConnection);
1698  WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1699 
1700  rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout =
1701  (UINT32)ConnectionTimeout;
1702  rpc->VirtualConnection->DefaultInChannel->PeerReceiveWindow = (UINT32)ReceiveWindowSize;
1703  return TRUE;
1704 }
1705 
1706 /* Out-of-Sequence PDUs */
1707 
1708 BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc)
1709 {
1710  BOOL status = FALSE;
1711  wStream* buffer = NULL;
1712  rpcconn_rts_hdr_t header = rts_pdu_header_init();
1713  UINT32 BytesReceived = 0;
1714  UINT32 AvailableWindow = 0;
1715  BYTE* ChannelCookie = NULL;
1716  RpcVirtualConnection* connection = NULL;
1717  RpcInChannel* inChannel = NULL;
1718  RpcOutChannel* outChannel = NULL;
1719 
1720  WINPR_ASSERT(rpc);
1721 
1722  connection = rpc->VirtualConnection;
1723  WINPR_ASSERT(connection);
1724 
1725  inChannel = connection->DefaultInChannel;
1726  WINPR_ASSERT(inChannel);
1727 
1728  outChannel = connection->DefaultOutChannel;
1729  WINPR_ASSERT(outChannel);
1730 
1731  header.header.frag_length = 56;
1732  header.Flags = RTS_FLAG_OTHER_CMD;
1733  header.NumberOfCommands = 2;
1734 
1735  WLog_DBG(TAG, "Sending FlowControlAck RTS PDU");
1736 
1737  BytesReceived = outChannel->BytesReceived;
1738  AvailableWindow = outChannel->AvailableWindowAdvertised;
1739  ChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1740  outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
1741  buffer = Stream_New(NULL, header.header.frag_length);
1742 
1743  if (!buffer)
1744  goto fail;
1745 
1746  if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */
1747  goto fail;
1748  if (!rts_destination_command_write(buffer, FDOutProxy)) /* Destination Command (8 bytes) */
1749  goto fail;
1750 
1751  /* FlowControlAck Command (28 bytes) */
1752  if (!rts_flow_control_ack_command_write(buffer, BytesReceived, AvailableWindow, ChannelCookie))
1753  goto fail;
1754 
1755  status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1756 fail:
1757  Stream_Free(buffer, TRUE);
1758  return status;
1759 }
1760 
1761 static int rts_recv_flow_control_ack_pdu(rdpRpc* rpc, wStream* buffer)
1762 {
1763  int rc = 0;
1764  UINT32 BytesReceived = 0;
1765  UINT32 AvailableWindow = 0;
1766  BYTE ChannelCookie[16] = { 0 };
1767 
1768  rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1769  (BYTE*)&ChannelCookie);
1770  if (rc < 0)
1771  return rc;
1772  WLog_ERR(TAG,
1773  "Receiving FlowControlAck RTS PDU: BytesReceived: %" PRIu32
1774  " AvailableWindow: %" PRIu32 "",
1775  BytesReceived, AvailableWindow);
1776 
1777  WINPR_ASSERT(rpc->VirtualConnection);
1778  WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1779 
1780  rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1781  AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1782  return 1;
1783 }
1784 
1785 static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, wStream* buffer)
1786 {
1787  UINT32 Command = 0;
1788  UINT32 Destination = 0;
1789  UINT32 BytesReceived = 0;
1790  UINT32 AvailableWindow = 0;
1791  BYTE ChannelCookie[16] = { 0 };
1809  int rc = rts_destination_command_read(rpc, buffer, &Command);
1810  if (rc < 0)
1811  return rc;
1812 
1813  if (Command != RTS_CMD_DESTINATION)
1814  {
1815  char buffer1[64] = { 0 };
1816  char buffer2[64] = { 0 };
1817  WLog_Print(rpc->log, WLOG_ERROR, "got command %s, expected %s",
1818  rts_command_to_string(Command, buffer1, sizeof(buffer1)),
1819  rts_command_to_string(RTS_CMD_DESTINATION, buffer2, sizeof(buffer2)));
1820  return -1;
1821  }
1822 
1823  rc = rts_destination_command_read(rpc, buffer, &Destination);
1824  if (rc < 0)
1825  return rc;
1826 
1827  switch (Destination)
1828  {
1829  case FDClient:
1830  break;
1831  case FDInProxy:
1832  break;
1833  case FDServer:
1834  break;
1835  case FDOutProxy:
1836  break;
1837  default:
1838  WLog_Print(rpc->log, WLOG_ERROR,
1839  "got destination %" PRIu32
1840  ", expected one of [FDClient[0]|FDInProxy[1]|FDServer[2]|FDOutProxy[3]",
1841  Destination);
1842  return -1;
1843  }
1844 
1845  rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1846  ChannelCookie);
1847  if (rc < 0)
1848  return rc;
1849 
1850  WLog_DBG(TAG,
1851  "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %" PRIu32
1852  " AvailableWindow: %" PRIu32 "",
1853  BytesReceived, AvailableWindow);
1854 
1855  WINPR_ASSERT(rpc->VirtualConnection);
1856  WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1857  rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1858  AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1859  return 1;
1860 }
1861 
1862 BOOL rts_recv_ping_pdu(rdpRpc* rpc, wStream* s)
1863 {
1864  BOOL rc = FALSE;
1865  rpcconn_hdr_t header = { 0 };
1866 
1867  WINPR_ASSERT(rpc);
1868  WINPR_ASSERT(rpc->auth);
1869  WINPR_ASSERT(s);
1870 
1871  if (!rts_read_pdu_header(s, &header))
1872  goto fail;
1873 
1874  rc = TRUE;
1875  if (header.common.ptype != PTYPE_RTS)
1876  {
1877  WLog_Print(rpc->log, WLOG_ERROR, "received invalid ping PDU, type is 0x%" PRIx32,
1878  header.common.ptype);
1879  rc = FALSE;
1880  }
1881  if (header.rts.Flags != RTS_FLAG_PING)
1882  {
1883  WLog_Print(rpc->log, WLOG_ERROR, "received unexpected ping PDU::Flags 0x%" PRIx32,
1884  header.rts.Flags);
1885  rc = FALSE;
1886  }
1887 fail:
1888  rts_free_pdu_header(&header, FALSE);
1889  return rc;
1890 }
1891 
1892 static int rts_send_ping_pdu(rdpRpc* rpc)
1893 {
1894  BOOL status = FALSE;
1895  wStream* buffer = NULL;
1896  rpcconn_rts_hdr_t header = rts_pdu_header_init();
1897  RpcInChannel* inChannel = NULL;
1898 
1899  WINPR_ASSERT(rpc);
1900  WINPR_ASSERT(rpc->VirtualConnection);
1901 
1902  inChannel = rpc->VirtualConnection->DefaultInChannel;
1903  WINPR_ASSERT(inChannel);
1904 
1905  header.header.frag_length = 20;
1906  header.Flags = RTS_FLAG_PING;
1907  header.NumberOfCommands = 0;
1908 
1909  WLog_DBG(TAG, "Sending Ping RTS PDU");
1910  buffer = Stream_New(NULL, header.header.frag_length);
1911 
1912  if (!buffer)
1913  goto fail;
1914 
1915  if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */
1916  goto fail;
1917  status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1918 fail:
1919  Stream_Free(buffer, TRUE);
1920  return (status) ? 1 : -1;
1921 }
1922 
1923 BOOL rts_command_length(UINT32 CommandType, wStream* s, size_t* length, BOOL silent)
1924 {
1925  size_t padding = 0;
1926  size_t CommandLength = 0;
1927 
1928  WINPR_ASSERT(s);
1929 
1930  switch (CommandType)
1931  {
1932  case RTS_CMD_RECEIVE_WINDOW_SIZE:
1933  CommandLength = RTS_CMD_RECEIVE_WINDOW_SIZE_LENGTH;
1934  break;
1935 
1936  case RTS_CMD_FLOW_CONTROL_ACK:
1937  CommandLength = RTS_CMD_FLOW_CONTROL_ACK_LENGTH;
1938  break;
1939 
1940  case RTS_CMD_CONNECTION_TIMEOUT:
1941  CommandLength = RTS_CMD_CONNECTION_TIMEOUT_LENGTH;
1942  break;
1943 
1944  case RTS_CMD_COOKIE:
1945  CommandLength = RTS_CMD_COOKIE_LENGTH;
1946  break;
1947 
1948  case RTS_CMD_CHANNEL_LIFETIME:
1949  CommandLength = RTS_CMD_CHANNEL_LIFETIME_LENGTH;
1950  break;
1951 
1952  case RTS_CMD_CLIENT_KEEPALIVE:
1953  CommandLength = RTS_CMD_CLIENT_KEEPALIVE_LENGTH;
1954  break;
1955 
1956  case RTS_CMD_VERSION:
1957  CommandLength = RTS_CMD_VERSION_LENGTH;
1958  break;
1959 
1960  case RTS_CMD_EMPTY:
1961  CommandLength = RTS_CMD_EMPTY_LENGTH;
1962  break;
1963 
1964  case RTS_CMD_PADDING: /* variable-size */
1965  if (!rts_padding_command_read(s, &padding, silent))
1966  return FALSE;
1967  break;
1968 
1969  case RTS_CMD_NEGATIVE_ANCE:
1970  CommandLength = RTS_CMD_NEGATIVE_ANCE_LENGTH;
1971  break;
1972 
1973  case RTS_CMD_ANCE:
1974  CommandLength = RTS_CMD_ANCE_LENGTH;
1975  break;
1976 
1977  case RTS_CMD_CLIENT_ADDRESS: /* variable-size */
1978  if (!rts_client_address_command_read(s, &CommandLength, silent))
1979  return FALSE;
1980  break;
1981 
1982  case RTS_CMD_ASSOCIATION_GROUP_ID:
1983  CommandLength = RTS_CMD_ASSOCIATION_GROUP_ID_LENGTH;
1984  break;
1985 
1986  case RTS_CMD_DESTINATION:
1987  CommandLength = RTS_CMD_DESTINATION_LENGTH;
1988  break;
1989 
1990  case RTS_CMD_PING_TRAFFIC_SENT_NOTIFY:
1991  CommandLength = RTS_CMD_PING_TRAFFIC_SENT_NOTIFY_LENGTH;
1992  break;
1993 
1994  default:
1995  WLog_ERR(TAG, "Error: Unknown RTS Command Type: 0x%" PRIx32 "", CommandType);
1996  return FALSE;
1997  }
1998 
1999  CommandLength += padding;
2000  if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, CommandLength, silent))
2001  return FALSE;
2002 
2003  if (length)
2004  *length = CommandLength;
2005  return TRUE;
2006 }
2007 
2008 static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
2009 {
2010  BOOL status = FALSE;
2011  wStream* buffer = NULL;
2012  rpcconn_rts_hdr_t header = rts_pdu_header_init();
2013  BYTE* SuccessorChannelCookie = NULL;
2014  RpcInChannel* inChannel = NULL;
2015  RpcOutChannel* nextOutChannel = NULL;
2016 
2017  WINPR_ASSERT(rpc);
2018  WINPR_ASSERT(rpc->VirtualConnection);
2019 
2020  inChannel = rpc->VirtualConnection->DefaultInChannel;
2021  WINPR_ASSERT(inChannel);
2022 
2023  nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2024  WINPR_ASSERT(nextOutChannel);
2025 
2026  header.header.frag_length = 56;
2027  header.Flags = RTS_FLAG_OUT_CHANNEL;
2028  header.NumberOfCommands = 3;
2029 
2030  WLog_DBG(TAG, "Sending OUT_R2/A7 RTS PDU");
2031 
2032  SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2033  buffer = Stream_New(NULL, header.header.frag_length);
2034 
2035  if (!buffer)
2036  return -1;
2037 
2038  if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */
2039  goto fail;
2040  if (!rts_destination_command_write(buffer, FDServer)) /* Destination (8 bytes)*/
2041  goto fail;
2042  if (!rts_cookie_command_write(buffer,
2043  SuccessorChannelCookie)) /* SuccessorChannelCookie (20 bytes) */
2044  goto fail;
2045  if (!rts_version_command_write(buffer)) /* Version (8 bytes) */
2046  goto fail;
2047  status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2048 fail:
2049  Stream_Free(buffer, TRUE);
2050  return (status) ? 1 : -1;
2051 }
2052 
2053 static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc)
2054 {
2055  BOOL status = FALSE;
2056  wStream* buffer = NULL;
2057  rpcconn_rts_hdr_t header = rts_pdu_header_init();
2058  RpcOutChannel* nextOutChannel = NULL;
2059 
2060  WINPR_ASSERT(rpc);
2061  WINPR_ASSERT(rpc->VirtualConnection);
2062 
2063  nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2064  WINPR_ASSERT(nextOutChannel);
2065 
2066  header.header.frag_length = 24;
2067  header.Flags = RTS_FLAG_PING;
2068  header.NumberOfCommands = 1;
2069 
2070  WLog_DBG(TAG, "Sending OUT_R2/C1 RTS PDU");
2071  buffer = Stream_New(NULL, header.header.frag_length);
2072 
2073  if (!buffer)
2074  return -1;
2075 
2076  if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */
2077  goto fail;
2078 
2079  if (!rts_empty_command_write(buffer)) /* Empty command (4 bytes) */
2080  goto fail;
2081  status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2082 fail:
2083  Stream_Free(buffer, TRUE);
2084  return (status) ? 1 : -1;
2085 }
2086 
2087 BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
2088 {
2089  BOOL status = FALSE;
2090  wStream* buffer = NULL;
2091  rpcconn_rts_hdr_t header = rts_pdu_header_init();
2092  UINT32 ReceiveWindowSize = 0;
2093  BYTE* VirtualConnectionCookie = NULL;
2094  BYTE* PredecessorChannelCookie = NULL;
2095  BYTE* SuccessorChannelCookie = NULL;
2096  RpcVirtualConnection* connection = NULL;
2097  RpcOutChannel* outChannel = NULL;
2098  RpcOutChannel* nextOutChannel = NULL;
2099 
2100  WINPR_ASSERT(rpc);
2101 
2102  connection = rpc->VirtualConnection;
2103  WINPR_ASSERT(connection);
2104 
2105  outChannel = connection->DefaultOutChannel;
2106  WINPR_ASSERT(outChannel);
2107 
2108  nextOutChannel = connection->NonDefaultOutChannel;
2109  WINPR_ASSERT(nextOutChannel);
2110 
2111  header.header.frag_length = 96;
2112  header.Flags = RTS_FLAG_RECYCLE_CHANNEL;
2113  header.NumberOfCommands = 5;
2114 
2115  WLog_DBG(TAG, "Sending OUT_R1/A3 RTS PDU");
2116 
2117  VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
2118  PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie);
2119  SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2120  ReceiveWindowSize = outChannel->ReceiveWindow;
2121  buffer = Stream_New(NULL, header.header.frag_length);
2122 
2123  if (!buffer)
2124  return -1;
2125 
2126  if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */
2127  goto fail;
2128  if (!rts_version_command_write(buffer)) /* Version (8 bytes) */
2129  goto fail;
2130  if (!rts_cookie_command_write(buffer,
2131  VirtualConnectionCookie)) /* VirtualConnectionCookie (20 bytes) */
2132  goto fail;
2133  if (!rts_cookie_command_write(
2134  buffer, PredecessorChannelCookie)) /* PredecessorChannelCookie (20 bytes) */
2135  goto fail;
2136  if (!rts_cookie_command_write(buffer,
2137  SuccessorChannelCookie)) /* SuccessorChannelCookie (20 bytes) */
2138  goto fail;
2139  if (!rts_receive_window_size_command_write(buffer,
2140  ReceiveWindowSize)) /* ReceiveWindowSize (8 bytes) */
2141  goto fail;
2142 
2143  status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2144 fail:
2145  Stream_Free(buffer, TRUE);
2146  return status;
2147 }
2148 
2149 static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, wStream* buffer)
2150 {
2151  int status = 0;
2152  UINT32 Destination = 0;
2153  RpcVirtualConnection* connection = NULL;
2154  WINPR_ASSERT(rpc);
2155  WINPR_ASSERT(buffer);
2156 
2157  connection = rpc->VirtualConnection;
2158  WINPR_ASSERT(connection);
2159 
2160  WLog_DBG(TAG, "Receiving OUT R1/A2 RTS PDU");
2161 
2162  status = rts_destination_command_read(rpc, buffer, &Destination);
2163  if (status < 0)
2164  return status;
2165 
2166  connection->NonDefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
2167 
2168  if (!connection->NonDefaultOutChannel)
2169  return -1;
2170 
2171  status = rpc_out_channel_replacement_connect(connection->NonDefaultOutChannel, 5000);
2172 
2173  if (status < 0)
2174  {
2175  WLog_ERR(TAG, "rpc_out_channel_replacement_connect failure");
2176  return -1;
2177  }
2178 
2179  rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2180  CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
2181  return 1;
2182 }
2183 
2184 static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, wStream* buffer)
2185 {
2186  int status = 0;
2187  RpcVirtualConnection* connection = NULL;
2188 
2189  WINPR_ASSERT(rpc);
2190  WINPR_ASSERT(buffer);
2191 
2192  connection = rpc->VirtualConnection;
2193  WINPR_ASSERT(connection);
2194 
2195  WLog_DBG(TAG, "Receiving OUT R2/A6 RTS PDU");
2196  status = rts_send_OUT_R2_C1_pdu(rpc);
2197 
2198  if (status < 0)
2199  {
2200  WLog_ERR(TAG, "rts_send_OUT_R2_C1_pdu failure");
2201  return -1;
2202  }
2203 
2204  status = rts_send_OUT_R2_A7_pdu(rpc);
2205 
2206  if (status < 0)
2207  {
2208  WLog_ERR(TAG, "rts_send_OUT_R2_A7_pdu failure");
2209  return -1;
2210  }
2211 
2212  rpc_out_channel_transition_to_state(connection->NonDefaultOutChannel,
2213  CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2214  rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2215  CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2216  return 1;
2217 }
2218 
2219 static int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc, wStream* buffer)
2220 {
2221  RpcVirtualConnection* connection = NULL;
2222 
2223  WINPR_ASSERT(rpc);
2224  WINPR_ASSERT(buffer);
2225 
2226  connection = rpc->VirtualConnection;
2227  WINPR_ASSERT(connection);
2228 
2229  WLog_DBG(TAG, "Receiving OUT R2/B3 RTS PDU");
2230  rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2231  CLIENT_OUT_CHANNEL_STATE_RECYCLED);
2232  return 1;
2233 }
2234 
2235 BOOL rts_recv_out_of_sequence_pdu(rdpRpc* rpc, wStream* buffer, const rpcconn_hdr_t* header)
2236 {
2237  BOOL status = FALSE;
2238  size_t length = 0;
2239  RtsPduSignature signature = { 0 };
2240  RpcVirtualConnection* connection = NULL;
2241 
2242  WINPR_ASSERT(rpc);
2243  WINPR_ASSERT(buffer);
2244  WINPR_ASSERT(header);
2245 
2246  wLog* log = WLog_Get(TAG);
2247 
2248  const size_t total = Stream_Length(buffer);
2249  length = header->common.frag_length;
2250  if (total < length)
2251  {
2252  WLog_Print(log, WLOG_ERROR, "PDU length %" PRIuz " does not match available data %" PRIuz,
2253  length, total);
2254  return FALSE;
2255  }
2256 
2257  connection = rpc->VirtualConnection;
2258 
2259  if (!connection)
2260  {
2261  WLog_Print(log, WLOG_ERROR, "not connected, aborting");
2262  return FALSE;
2263  }
2264 
2265  if (!rts_extract_pdu_signature(&signature, buffer, header))
2266  return FALSE;
2267 
2268  rts_print_pdu_signature(log, WLOG_TRACE, &signature);
2269 
2270  if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, sizeof(signature)) == 0)
2271  {
2272  status = rts_recv_flow_control_ack_pdu(rpc, buffer);
2273  }
2274  else if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE,
2275  sizeof(signature)) == 0)
2276  {
2277  status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer);
2278  }
2279  else if (memcmp(&signature, &RTS_PDU_PING_SIGNATURE, sizeof(signature)) == 0)
2280  {
2281  status = rts_send_ping_pdu(rpc);
2282  }
2283  else
2284  {
2285  if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
2286  {
2287  if (memcmp(&signature, &RTS_PDU_OUT_R1_A2_SIGNATURE, sizeof(signature)) == 0)
2288  {
2289  status = rts_recv_OUT_R1_A2_pdu(rpc, buffer);
2290  }
2291  }
2292  else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_A6W)
2293  {
2294  if (memcmp(&signature, &RTS_PDU_OUT_R2_A6_SIGNATURE, sizeof(signature)) == 0)
2295  {
2296  status = rts_recv_OUT_R2_A6_pdu(rpc, buffer);
2297  }
2298  }
2299  else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_B3W)
2300  {
2301  if (memcmp(&signature, &RTS_PDU_OUT_R2_B3_SIGNATURE, sizeof(signature)) == 0)
2302  {
2303  status = rts_recv_OUT_R2_B3_pdu(rpc, buffer);
2304  }
2305  }
2306  }
2307 
2308  if (!status)
2309  {
2310  const UINT32 SignatureId = rts_identify_pdu_signature(&signature, NULL);
2311  WLog_Print(log, WLOG_ERROR, "error parsing RTS PDU with signature id: 0x%08" PRIX32 "",
2312  SignatureId);
2313  rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2314  }
2315 
2316  const size_t rem = Stream_GetRemainingLength(buffer);
2317  if (rem > 0)
2318  {
2319  WLog_Print(log, WLOG_ERROR, "%" PRIuz " bytes or %" PRIuz " total not parsed, aborting",
2320  rem, total);
2321  rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2322  return FALSE;
2323  }
2324 
2325  return status;
2326 }
2327 
2328 BOOL rts_write_pdu_auth3(wStream* s, const rpcconn_rpc_auth_3_hdr_t* auth)
2329 {
2330  WINPR_ASSERT(s);
2331  WINPR_ASSERT(auth);
2332 
2333  if (!rts_write_common_pdu_header(s, &auth->header))
2334  return FALSE;
2335 
2336  if (!Stream_EnsureRemainingCapacity(s, 2 * sizeof(UINT16)))
2337  return FALSE;
2338 
2339  Stream_Write_UINT16(s, auth->max_xmit_frag);
2340  Stream_Write_UINT16(s, auth->max_recv_frag);
2341 
2342  return rts_write_auth_verifier(s, &auth->auth_verifier, &auth->header);
2343 }
2344 
2345 BOOL rts_write_pdu_bind(wStream* s, const rpcconn_bind_hdr_t* bind)
2346 {
2347 
2348  WINPR_ASSERT(s);
2349  WINPR_ASSERT(bind);
2350 
2351  if (!rts_write_common_pdu_header(s, &bind->header))
2352  return FALSE;
2353 
2354  if (!Stream_EnsureRemainingCapacity(s, 8))
2355  return FALSE;
2356 
2357  Stream_Write_UINT16(s, bind->max_xmit_frag);
2358  Stream_Write_UINT16(s, bind->max_recv_frag);
2359  Stream_Write_UINT32(s, bind->assoc_group_id);
2360 
2361  if (!rts_write_context_list(s, &bind->p_context_elem))
2362  return FALSE;
2363 
2364  return rts_write_auth_verifier(s, &bind->auth_verifier, &bind->header);
2365 }
2366 
2367 BOOL rts_conditional_check_and_log(const char* tag, wStream* s, size_t size, BOOL silent,
2368  const char* fkt, const char* file, size_t line)
2369 {
2370  if (silent)
2371  {
2372  const size_t rem = Stream_GetRemainingLength(s);
2373  if (rem < size)
2374  return FALSE;
2375  return TRUE;
2376  }
2377 
2378  return Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, size, 1, "%s(%s:%" PRIuz ")", fkt,
2379  file, line);
2380 }
2381 
2382 BOOL rts_conditional_safe_seek(wStream* s, size_t size, BOOL silent, const char* fkt,
2383  const char* file, size_t line)
2384 {
2385  if (silent)
2386  {
2387  const size_t rem = Stream_GetRemainingLength(s);
2388  if (rem < size)
2389  return FALSE;
2390  }
2391  return Stream_SafeSeekEx(s, size, file, line, fkt);
2392 }