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