20#include <freerdp/config.h>
22#include <winpr/assert.h>
23#include <winpr/cast.h>
25#include <winpr/crypto.h>
27#include <freerdp/log.h>
29#include "ncacn_http.h"
30#include "rpc_client.h"
31#include "rts_signature.h"
35#define TAG FREERDP_TAG("core.gateway.rts")
70static int rts_destination_command_read(rdpRpc* rpc,
wStream* buffer, UINT32* Destination);
73static const char* rts_command_to_string(UINT32 cmd,
char* buffer,
size_t len)
75 const char* str =
nullptr;
85 ENTRY(RTS_CMD_RECEIVE_WINDOW_SIZE);
86 ENTRY(RTS_CMD_FLOW_CONTROL_ACK);
87 ENTRY(RTS_CMD_CONNECTION_TIMEOUT);
88 ENTRY(RTS_CMD_COOKIE);
89 ENTRY(RTS_CMD_CHANNEL_LIFETIME);
90 ENTRY(RTS_CMD_CLIENT_KEEPALIVE);
91 ENTRY(RTS_CMD_VERSION);
93 ENTRY(RTS_CMD_PADDING);
94 ENTRY(RTS_CMD_NEGATIVE_ANCE);
96 ENTRY(RTS_CMD_CLIENT_ADDRESS);
97 ENTRY(RTS_CMD_ASSOCIATION_GROUP_ID);
98 ENTRY(RTS_CMD_DESTINATION);
99 ENTRY(RTS_CMD_PING_TRAFFIC_SENT_NOTIFY);
100 ENTRY(RTS_CMD_LAST_ID);
102 str =
"RTS_CMD_UNKNOWN";
108 (void)_snprintf(buffer, len,
"%s [0x%08" PRIx32
"]", str, cmd);
113static const char* rts_pdu_ptype_to_string(UINT32 ptype)
118 return "PTYPE_REQUEST";
122 return "PTYPE_RESPONSE";
124 return "PTYPE_FAULT";
126 return "PTYPE_WORKING";
128 return "PTYPE_NOCALL";
130 return "PTYPE_REJECT";
133 case PTYPE_CL_CANCEL:
134 return "PTYPE_CL_CANCEL";
137 case PTYPE_CANCEL_ACK:
138 return "PTYPE_CANCEL_ACK";
142 return "PTYPE_BIND_ACK";
144 return "PTYPE_BIND_NAK";
145 case PTYPE_ALTER_CONTEXT:
146 return "PTYPE_ALTER_CONTEXT";
147 case PTYPE_ALTER_CONTEXT_RESP:
148 return "PTYPE_ALTER_CONTEXT_RESP";
149 case PTYPE_RPC_AUTH_3:
150 return "PTYPE_RPC_AUTH_3";
152 return "PTYPE_SHUTDOWN";
153 case PTYPE_CO_CANCEL:
154 return "PTYPE_CO_CANCEL";
156 return "PTYPE_ORPHANED";
168 header.header.rpc_vers = 5;
169 header.header.rpc_vers_minor = 0;
170 header.header.ptype = PTYPE_RTS;
171 header.header.packed_drep[0] = 0x10;
172 header.header.packed_drep[1] = 0x00;
173 header.header.packed_drep[2] = 0x00;
174 header.header.packed_drep[3] = 0x00;
175 header.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
176 header.header.auth_length = 0;
177 header.header.call_id = 0;
183static BOOL rts_align_stream(
wStream* s,
size_t alignment, BOOL silent)
189 WINPR_ASSERT(alignment > 0);
191 pos = Stream_GetPosition(s);
192 pad = rpc_offset_align(&pos, alignment);
193 return Stream_ConditionalSafeSeek(s, pad, silent);
200 WINPR_ASSERT(header);
204 Stream_Write_UINT8(s, header->rpc_vers);
205 Stream_Write_UINT8(s, header->rpc_vers_minor);
206 Stream_Write_UINT8(s, header->ptype);
207 Stream_Write_UINT8(s, header->pfc_flags);
208 Stream_Write(s, header->packed_drep, ARRAYSIZE(header->packed_drep));
209 Stream_Write_UINT16(s, header->frag_length);
210 Stream_Write_UINT16(s, header->auth_length);
211 Stream_Write_UINT32(s, header->call_id);
219 WINPR_ASSERT(header);
224 return RTS_PDU_INCOMPLETE;
228 const size_t sz = Stream_GetRemainingLength(s);
230 return RTS_PDU_INCOMPLETE;
233 Stream_Read_UINT8(s, header->rpc_vers);
234 Stream_Read_UINT8(s, header->rpc_vers_minor);
235 Stream_Read_UINT8(s, header->ptype);
236 Stream_Read_UINT8(s, header->pfc_flags);
237 Stream_Read(s, header->packed_drep, ARRAYSIZE(header->packed_drep));
238 Stream_Read_UINT16(s, header->frag_length);
239 Stream_Read_UINT16(s, header->auth_length);
240 Stream_Read_UINT32(s, header->call_id);
245 WLog_WARN(TAG,
"Invalid header->frag_length of %" PRIu16
", expected %" PRIuz,
249 if (header->auth_length > header->frag_length - 8ull)
253 "Invalid header->auth_length(%" PRIu16
") > header->frag_length(%" PRIu16
255 header->frag_length, header->auth_length);
261 if (!Stream_CheckAndLogRequiredLength(TAG, s,
263 return RTS_PDU_INCOMPLETE;
267 const size_t sz2 = Stream_GetRemainingLength(s);
269 return RTS_PDU_INCOMPLETE;
271 return RTS_PDU_VALID;
275static BOOL rts_read_auth_verifier_no_checks(
wStream* s, auth_verifier_co_t* auth,
281 WINPR_ASSERT(header);
283 if (header->frag_length < header->auth_length + 8ull)
287 *startPos = Stream_GetPosition(s);
291 const size_t expected = header->frag_length - header->auth_length - 8;
293 if (!Stream_SetPosition(s, expected))
295 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 8, silent))
298 Stream_Read_UINT8(s, auth->auth_type);
299 Stream_Read_UINT8(s, auth->auth_level);
300 Stream_Read_UINT8(s, auth->auth_pad_length);
301 Stream_Read_UINT8(s, auth->auth_reserved);
302 Stream_Read_UINT32(s, auth->auth_context_id);
305 if (header->auth_length != 0)
307 const void* ptr = Stream_Pointer(s);
308 if (!Stream_ConditionalSafeSeek(s, header->auth_length, silent))
310 auth->auth_value = (BYTE*)strndup(ptr, header->auth_length);
311 if (auth->auth_value ==
nullptr)
319static BOOL rts_read_auth_verifier(
wStream* s, auth_verifier_co_t* auth,
325 WINPR_ASSERT(header);
327 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
330 const size_t expected = header->frag_length - header->auth_length - 8;
331 return pos + auth->auth_pad_length == expected;
335static BOOL rts_read_auth_verifier_with_stub(
wStream* s, auth_verifier_co_t* auth,
339 size_t alloc_hint = 0;
341 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
344 switch (header->ptype)
349 alloc_hint = hdr->alloc_hint;
355 alloc_hint = hdr->alloc_hint;
361 alloc_hint = hdr->alloc_hint;
370 const size_t off = header->auth_length + 8 + auth->auth_pad_length + pos;
371 const size_t size = header->frag_length - MIN(header->frag_length, off);
373 if (off > header->frag_length)
375 "Unexpected alloc_hint(%" PRIuz
") for PDU %s: size %" PRIuz
376 ", frag_length %" PRIu16
", offset %" PRIuz,
377 alloc_hint, rts_pdu_ptype_to_string(header->ptype), size, header->frag_length,
384static void rts_free_auth_verifier(auth_verifier_co_t* auth)
388 free(auth->auth_value);
389 memset(auth, 0,
sizeof(auth_verifier_co_t));
393static BOOL rts_write_auth_verifier(
wStream* s,
const auth_verifier_co_t* auth,
397 UINT8 auth_pad_length = 0;
401 WINPR_ASSERT(header);
404 pos = Stream_GetPosition(s);
407 auth_pad_length = 4 - (pos % 4);
408 if (!Stream_EnsureRemainingCapacity(s, auth_pad_length))
410 Stream_Zero(s, auth_pad_length);
413#if defined(WITH_VERBOSE_WINPR_ASSERT) && (WITH_VERBOSE_WINPR_ASSERT != 0)
414 WINPR_ASSERT(header->frag_length + 8ull > header->auth_length);
416 size_t apos = Stream_GetPosition(s);
417 size_t expected = header->frag_length - header->auth_length - 8;
419 WINPR_ASSERT(apos == expected);
423 if (!Stream_EnsureRemainingCapacity(s,
sizeof(auth_verifier_co_t)))
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);
430 Stream_Write_UINT32(s, auth->auth_context_id);
432 if (!Stream_EnsureRemainingCapacity(s, header->auth_length))
434 Stream_Write(s, auth->auth_value, header->auth_length);
442 WINPR_ASSERT(version);
444 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2 *
sizeof(UINT8), silent))
446 Stream_Read_UINT8(s, version->major);
447 Stream_Read_UINT8(s, version->minor);
455 free(versions->p_protocols);
464 WINPR_ASSERT(versions);
466 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT8), silent))
469 Stream_Read_UINT8(s, versions->n_protocols);
471 if (versions->n_protocols > 0)
473 versions->p_protocols = calloc(versions->n_protocols,
sizeof(
p_rt_version_t));
474 if (!versions->p_protocols)
477 for (BYTE x = 0; x < versions->n_protocols; x++)
480 if (!rts_read_version(s, version, silent))
482 rts_free_supported_versions(versions);
496 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT16), silent))
499 Stream_Read_UINT16(s, port->length);
500 if (port->length == 0)
503 const void* ptr = Stream_ConstPointer(s);
504 if (!Stream_ConditionalSafeSeek(s, port->length, silent))
506 port->port_spec = strndup(ptr, port->length);
507 return port->port_spec !=
nullptr;
510static void rts_free_port_any(
port_any_t* port)
514 free(port->port_spec);
524 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(
p_uuid_t), silent))
527 Stream_Read_UINT32(s, uuid->time_low);
528 Stream_Read_UINT16(s, uuid->time_mid);
529 Stream_Read_UINT16(s, uuid->time_hi_and_version);
530 Stream_Read_UINT8(s, uuid->clock_seq_hi_and_reserved);
531 Stream_Read_UINT8(s, uuid->clock_seq_low);
532 Stream_Read(s, uuid->node, ARRAYSIZE(uuid->node));
542 if (!Stream_EnsureRemainingCapacity(s,
sizeof(
p_uuid_t)))
545 Stream_Write_UINT32(s, uuid->time_low);
546 Stream_Write_UINT16(s, uuid->time_mid);
547 Stream_Write_UINT16(s, uuid->time_hi_and_version);
548 Stream_Write_UINT8(s, uuid->clock_seq_hi_and_reserved);
549 Stream_Write_UINT8(s, uuid->clock_seq_low);
550 Stream_Write(s, uuid->node, ARRAYSIZE(uuid->node));
559WINPR_ATTR_MALLOC(rts_syntax_id_free, 1)
569 WINPR_ASSERT(syntax_id);
571 if (!rts_read_uuid(s, &syntax_id->if_uuid, silent))
574 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
577 Stream_Read_UINT32(s, syntax_id->if_version);
585 WINPR_ASSERT(syntax_id);
587 if (!rts_write_uuid(s, &syntax_id->if_uuid))
590 if (!Stream_EnsureRemainingCapacity(s, 4))
593 Stream_Write_UINT32(s, syntax_id->if_version);
602 rts_syntax_id_free(ptr->transfer_syntaxes);
606WINPR_ATTR_MALLOC(rts_context_elem_free, 1)
617 WINPR_ASSERT(element);
619 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
622 Stream_Read_UINT16(s, element->p_cont_id);
623 Stream_Read_UINT8(s, element->n_transfer_syn);
624 Stream_Read_UINT8(s, element->reserved);
626 if (!rts_read_syntax_id(s, &element->abstract_syntax, silent))
629 if (element->n_transfer_syn > 0)
631 element->transfer_syntaxes = rts_syntax_id_new(element->n_transfer_syn);
632 if (!element->transfer_syntaxes)
634 for (BYTE x = 0; x < element->n_transfer_syn; x++)
637 if (!rts_read_syntax_id(s, syn, silent))
649 WINPR_ASSERT(element);
651 if (!Stream_EnsureRemainingCapacity(s, 4))
653 Stream_Write_UINT16(s, element->p_cont_id);
654 Stream_Write_UINT8(s, element->n_transfer_syn);
655 Stream_Write_UINT8(s, element->reserved);
656 if (!rts_write_syntax_id(s, &element->abstract_syntax))
659 for (BYTE x = 0; x < element->n_transfer_syn; x++)
662 if (!rts_write_syntax_id(s, syn))
675 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
677 Stream_Read_UINT8(s, list->n_context_elem);
678 Stream_Read_UINT8(s, list->reserved);
679 Stream_Read_UINT16(s, list->reserved2);
681 if (list->n_context_elem > 0)
683 list->p_cont_elem = rts_context_elem_new(list->n_context_elem);
684 if (!list->p_cont_elem)
686 for (BYTE x = 0; x < list->n_context_elem; x++)
689 if (!rts_read_context_elem(s, element, silent))
700 rts_context_elem_free(list->p_cont_elem);
710 if (!Stream_EnsureRemainingCapacity(s, 4))
712 Stream_Write_UINT8(s, list->n_context_elem);
713 Stream_Write_UINT8(s, 0);
714 Stream_Write_UINT16(s, 0);
716 for (BYTE x = 0; x < list->n_context_elem; x++)
719 if (!rts_write_context_elem(s, element))
725static void rts_result_free(
p_result_t* results)
730WINPR_ATTR_MALLOC(rts_result_free, 1)
731static
p_result_t* rts_result_new(
size_t count)
740 WINPR_ASSERT(result);
742 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2, silent))
745 const UINT16 res = Stream_Get_UINT16(s);
750 case provider_rejection:
754 WLog_ERR(TAG,
"Invalid p_cont_def_result_t %" PRIu16, res);
757 result->result = (p_cont_def_result_t)res;
759 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2, silent))
762 const UINT16 reason = Stream_Get_UINT16(s);
765 case reason_not_specified:
766 case abstract_syntax_not_supported:
767 case proposed_transfer_syntaxes_not_supported:
768 case local_limit_exceeded:
771 WLog_ERR(TAG,
"Invalid p_provider_reason_t %" PRIu16, reason);
774 result->reason = (p_provider_reason_t)reason;
775 return rts_read_syntax_id(s, &result->transfer_syntax, silent);
778static void rts_free_result(
p_result_t* result)
790 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
792 Stream_Read_UINT8(s, list->n_results);
793 Stream_Read_UINT8(s, list->reserved);
794 Stream_Read_UINT16(s, list->reserved2);
796 if (list->n_results > 0)
798 list->p_results = rts_result_new(list->n_results);
799 if (!list->p_results)
802 for (BYTE x = 0; x < list->n_results; x++)
805 if (!rts_read_result(s, result, silent))
817 for (BYTE x = 0; x < list->n_results; x++)
820 rts_free_result(result);
822 rts_result_free(list->p_results);
831 rts_free_context_list(&ctx->p_context_elem);
832 rts_free_auth_verifier(&ctx->auth_verifier);
842 if (!Stream_ConditionalCheckAndLogRequiredLength(
846 Stream_Read_UINT16(s, ctx->max_xmit_frag);
847 Stream_Read_UINT16(s, ctx->max_recv_frag);
848 Stream_Read_UINT32(s, ctx->assoc_group_id);
850 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
853 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
860static BOOL rts_read_pdu_alter_context_response(
wStream* s,
867 if (!Stream_ConditionalCheckAndLogRequiredLength(
871 Stream_Read_UINT16(s, ctx->max_xmit_frag);
872 Stream_Read_UINT16(s, ctx->max_recv_frag);
873 Stream_Read_UINT32(s, ctx->assoc_group_id);
875 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
878 if (!rts_align_stream(s, 4, silent))
881 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
884 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
895 rts_free_port_any(&ctx->sec_addr);
896 rts_free_result_list(&ctx->p_result_list);
897 rts_free_auth_verifier(&ctx->auth_verifier);
907 if (!Stream_ConditionalCheckAndLogRequiredLength(
910 Stream_Read_UINT16(s, ctx->max_xmit_frag);
911 Stream_Read_UINT16(s, ctx->max_recv_frag);
912 Stream_Read_UINT32(s, ctx->assoc_group_id);
914 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
917 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
927 rts_free_context_list(&ctx->p_context_elem);
928 rts_free_auth_verifier(&ctx->auth_verifier);
938 if (!Stream_CheckAndLogRequiredLength(
941 Stream_Read_UINT16(s, ctx->max_xmit_frag);
942 Stream_Read_UINT16(s, ctx->max_recv_frag);
943 Stream_Read_UINT32(s, ctx->assoc_group_id);
945 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
948 if (!rts_align_stream(s, 4, silent))
951 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
954 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
961 rts_free_port_any(&ctx->sec_addr);
962 rts_free_result_list(&ctx->p_result_list);
963 rts_free_auth_verifier(&ctx->auth_verifier);
973 if (!Stream_ConditionalCheckAndLogRequiredLength(
976 Stream_Read_UINT16(s, ctx->provider_reject_reason);
977 return rts_read_supported_versions(s, &ctx->versions, silent);
985 rts_free_supported_versions(&ctx->versions);
995 if (!Stream_ConditionalCheckAndLogRequiredLength(
998 Stream_Read_UINT16(s, ctx->max_xmit_frag);
999 Stream_Read_UINT16(s, ctx->max_recv_frag);
1001 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1008 rts_free_auth_verifier(&ctx->auth_verifier);
1018 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 12, silent))
1020 Stream_Read_UINT32(s, ctx->alloc_hint);
1021 Stream_Read_UINT16(s, ctx->p_cont_id);
1022 Stream_Read_UINT8(s, ctx->cancel_count);
1023 Stream_Read_UINT8(s, ctx->reserved);
1024 Stream_Read_UINT32(s, ctx->status);
1026 WLog_WARN(TAG,
"status=%s", Win32ErrorCode2Tag(ctx->status & 0xFFFF));
1027 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1034 rts_free_auth_verifier(&ctx->auth_verifier);
1044 if (!Stream_ConditionalCheckAndLogRequiredLength(
1047 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1054 rts_free_auth_verifier(&ctx->auth_verifier);
1064 if (!Stream_ConditionalCheckAndLogRequiredLength(
1067 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1074 rts_free_auth_verifier(&ctx->auth_verifier);
1084 if (!Stream_ConditionalCheckAndLogRequiredLength(
1087 Stream_Read_UINT32(s, ctx->alloc_hint);
1088 Stream_Read_UINT16(s, ctx->p_cont_id);
1089 Stream_Read_UINT16(s, ctx->opnum);
1090 if (!rts_read_uuid(s, &ctx->object, silent))
1093 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1100 rts_free_auth_verifier(&ctx->auth_verifier);
1110 if (!Stream_ConditionalCheckAndLogRequiredLength(
1113 Stream_Read_UINT32(s, ctx->alloc_hint);
1114 Stream_Read_UINT16(s, ctx->p_cont_id);
1115 Stream_Read_UINT8(s, ctx->cancel_count);
1116 Stream_Read_UINT8(s, ctx->reserved);
1118 if (!rts_align_stream(s, 8, silent))
1121 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1128 rts_free_auth_verifier(&ctx->auth_verifier);
1138 if (!Stream_ConditionalCheckAndLogRequiredLength(
1142 Stream_Read_UINT16(s, ctx->Flags);
1143 Stream_Read_UINT16(s, ctx->NumberOfCommands);
1153void rts_free_pdu_header(
rpcconn_hdr_t* header, BOOL allocated)
1158 switch (header->common.ptype)
1160 case PTYPE_ALTER_CONTEXT:
1161 rts_free_pdu_alter_context(&header->alter_context);
1163 case PTYPE_ALTER_CONTEXT_RESP:
1164 rts_free_pdu_alter_context_response(&header->alter_context_response);
1167 rts_free_pdu_bind(&header->bind);
1169 case PTYPE_BIND_ACK:
1170 rts_free_pdu_bind_ack(&header->bind_ack);
1172 case PTYPE_BIND_NAK:
1173 rts_free_pdu_bind_nak(&header->bind_nak);
1175 case PTYPE_RPC_AUTH_3:
1176 rts_free_pdu_auth3(&header->rpc_auth_3);
1178 case PTYPE_CANCEL_ACK:
1179 rts_free_pdu_cancel_ack(&header->cancel);
1182 rts_free_pdu_fault(&header->fault);
1184 case PTYPE_ORPHANED:
1185 rts_free_pdu_orphaned(&header->orphaned);
1188 rts_free_pdu_request(&header->request);
1190 case PTYPE_RESPONSE:
1191 rts_free_pdu_response(&header->response);
1194 rts_free_pdu_rts(&header->rts);
1197 case PTYPE_SHUTDOWN:
1206 case PTYPE_CL_CANCEL:
1208 case PTYPE_CO_CANCEL:
1219 return rts_read_pdu_header_ex(s, header, FALSE);
1226 WINPR_ASSERT(header);
1228 const rts_pdu_status_t status = rts_read_common_pdu_header(s, &header->common, silent);
1229 if (status != RTS_PDU_VALID)
1232 WLog_DBG(TAG,
"Reading PDU type %s", rts_pdu_ptype_to_string(header->common.ptype));
1234 switch (header->common.ptype)
1236 case PTYPE_ALTER_CONTEXT:
1237 rc = rts_read_pdu_alter_context(s, &header->alter_context, silent);
1239 case PTYPE_ALTER_CONTEXT_RESP:
1240 rc = rts_read_pdu_alter_context_response(s, &header->alter_context_response, silent);
1243 rc = rts_read_pdu_bind(s, &header->bind, silent);
1245 case PTYPE_BIND_ACK:
1246 rc = rts_read_pdu_bind_ack(s, &header->bind_ack, silent);
1248 case PTYPE_BIND_NAK:
1249 rc = rts_read_pdu_bind_nak(s, &header->bind_nak, silent);
1251 case PTYPE_RPC_AUTH_3:
1252 rc = rts_read_pdu_auth3(s, &header->rpc_auth_3, silent);
1254 case PTYPE_CANCEL_ACK:
1255 rc = rts_read_pdu_cancel_ack(s, &header->cancel, silent);
1258 rc = rts_read_pdu_fault(s, &header->fault, silent);
1260 case PTYPE_ORPHANED:
1261 rc = rts_read_pdu_orphaned(s, &header->orphaned, silent);
1264 rc = rts_read_pdu_request(s, &header->request, silent);
1266 case PTYPE_RESPONSE:
1267 rc = rts_read_pdu_response(s, &header->response, silent);
1270 rc = rts_read_pdu_rts(s, &header->rts, silent);
1272 case PTYPE_SHUTDOWN:
1282 case PTYPE_CL_CANCEL:
1284 case PTYPE_CO_CANCEL:
1296 WINPR_ASSERT(header);
1300 if (!rts_write_common_pdu_header(s, &header->header))
1303 Stream_Write_UINT16(s, header->Flags);
1304 Stream_Write_UINT16(s, header->NumberOfCommands);
1310static BOOL rts_receive_window_size_command_read(rdpRpc* rpc,
wStream* buffer,
1311 UINT32* ReceiveWindowSize)
1314 WINPR_ASSERT(buffer);
1316 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1318 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1319 if (CommandType != RTS_CMD_RECEIVE_WINDOW_SIZE)
1321 WLog_Print(rpc->log, WLOG_ERROR,
1322 "[MS-RPCH] 2.2.3.5.1 ReceiveWindowSize::CommandType must be 0x%08" PRIx32
1325 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_RECEIVE_WINDOW_SIZE), CommandType);
1328 const UINT32 val = Stream_Get_UINT32(buffer);
1329 if (ReceiveWindowSize)
1330 *ReceiveWindowSize = val;
1337static BOOL rts_receive_window_size_command_write(
wStream* s, UINT32 ReceiveWindowSize)
1341 if (!Stream_EnsureRemainingCapacity(s, 2ull *
sizeof(UINT32)))
1344 Stream_Write_UINT32(s, RTS_CMD_RECEIVE_WINDOW_SIZE);
1345 Stream_Write_UINT32(s, ReceiveWindowSize);
1352static int rts_flow_control_ack_command_read(rdpRpc* rpc,
wStream* buffer, UINT32* BytesReceived,
1353 UINT32* AvailableWindow, BYTE* ChannelCookie)
1359 WINPR_ASSERT(buffer);
1361 int rc = rts_destination_command_read(rpc, buffer, &Command);
1365 if (Command != RTS_CMD_FLOW_CONTROL_ACK)
1367 char buffer1[64] = WINPR_C_ARRAY_INIT;
1368 char buffer2[64] = WINPR_C_ARRAY_INIT;
1369 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
1370 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
1371 rts_command_to_string(RTS_CMD_FLOW_CONTROL_ACK, buffer2,
sizeof(buffer2)));
1376 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 24))
1379 Stream_Read_UINT32(buffer, val);
1381 *BytesReceived = val;
1383 Stream_Read_UINT32(buffer, val);
1384 if (AvailableWindow)
1385 *AvailableWindow = val;
1388 Stream_Read(buffer, ChannelCookie, 16);
1390 Stream_Seek(buffer, 16);
1396static BOOL rts_flow_control_ack_command_write(
wStream* s, UINT32 BytesReceived,
1397 UINT32 AvailableWindow, BYTE* ChannelCookie)
1401 if (!Stream_EnsureRemainingCapacity(s, 28))
1404 Stream_Write_UINT32(s, RTS_CMD_FLOW_CONTROL_ACK);
1405 Stream_Write_UINT32(s, BytesReceived);
1406 Stream_Write_UINT32(s, AvailableWindow);
1407 Stream_Write(s, ChannelCookie, 16);
1414static BOOL rts_connection_timeout_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc,
wStream* buffer,
1415 UINT32* ConnectionTimeout)
1418 WINPR_ASSERT(buffer);
1420 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1423 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1424 if (CommandType != RTS_CMD_CONNECTION_TIMEOUT)
1426 WLog_Print(rpc->log, WLOG_ERROR,
1427 "[MS-RPCH] 2.2.3.5.3 ConnectionTimeout::CommandType must be 0x%08" PRIx32
1430 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_CONNECTION_TIMEOUT), CommandType);
1433 const UINT32 val = Stream_Get_UINT32(buffer);
1434 if (ConnectionTimeout)
1435 *ConnectionTimeout = val;
1441static BOOL rts_cookie_command_write(
wStream* s,
const BYTE* Cookie)
1445 if (!Stream_EnsureRemainingCapacity(s, 20))
1448 Stream_Write_UINT32(s, RTS_CMD_COOKIE);
1449 Stream_Write(s, Cookie, 16);
1455static BOOL rts_channel_lifetime_command_write(
wStream* s, UINT32 ChannelLifetime)
1459 if (!Stream_EnsureRemainingCapacity(s, 8))
1461 Stream_Write_UINT32(s, RTS_CMD_CHANNEL_LIFETIME);
1462 Stream_Write_UINT32(s, ChannelLifetime);
1468static BOOL rts_client_keepalive_command_write(
wStream* s, UINT32 ClientKeepalive)
1472 if (!Stream_EnsureRemainingCapacity(s, 8))
1480 Stream_Write_UINT32(s, RTS_CMD_CLIENT_KEEPALIVE);
1481 Stream_Write_UINT32(s, ClientKeepalive);
1488static BOOL rts_version_command_read(rdpRpc* rpc,
wStream* buffer, uint32_t* pversion)
1491 WINPR_ASSERT(buffer);
1493 if (!Stream_EnsureRemainingCapacity(buffer, 8))
1496 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1497 if (CommandType != RTS_CMD_VERSION)
1499 WLog_Print(rpc->log, WLOG_ERROR,
1500 "[MS-RPCH] 2.2.3.5.7 Version::CommandType must be 0x%08" PRIx32
", got "
1502 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_VERSION), CommandType);
1505 const uint32_t version = Stream_Get_UINT32(buffer);
1508 WLog_Print(rpc->log, WLOG_WARN,
1509 "[MS-RPCH] 2.2.3.5.7 Version::Version should be 0x00000001, got 0x%08" PRIx32,
1513 *pversion = version;
1520static BOOL rts_version_command_write(
wStream* buffer)
1522 WINPR_ASSERT(buffer);
1524 if (!Stream_EnsureRemainingCapacity((buffer), 8))
1527 Stream_Write_UINT32(buffer, RTS_CMD_VERSION);
1528 Stream_Write_UINT32(buffer, 1);
1534static BOOL rts_empty_command_write(
wStream* s)
1538 if (!Stream_EnsureRemainingCapacity(s, 8))
1541 Stream_Write_UINT32(s, RTS_CMD_EMPTY);
1547static BOOL rts_padding_command_read(
wStream* s,
size_t* length, BOOL silent)
1549 UINT32 ConformanceCount = 0;
1551 WINPR_ASSERT(length);
1552 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1554 Stream_Read_UINT32(s, ConformanceCount);
1555 *length = ConformanceCount + 4;
1560static BOOL rts_client_address_command_read(
wStream* s,
size_t* length, BOOL silent)
1562 UINT32 AddressType = 0;
1565 WINPR_ASSERT(length);
1567 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1569 Stream_Read_UINT32(s, AddressType);
1571 if (AddressType == 0)
1575 *length = 4 + 4 + 12;
1581 *length = 4 + 16 + 12;
1587static BOOL rts_association_group_id_command_write(
wStream* s,
const BYTE* AssociationGroupId)
1591 if (!Stream_EnsureRemainingCapacity(s, 20))
1594 Stream_Write_UINT32(s, RTS_CMD_ASSOCIATION_GROUP_ID);
1595 Stream_Write(s, AssociationGroupId, 16);
1601static int rts_destination_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc,
wStream* buffer,
1602 UINT32* Destination)
1606 WINPR_ASSERT(buffer);
1608 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 4))
1610 Stream_Read_UINT32(buffer, val);
1618static BOOL rts_destination_command_write(
wStream* s, UINT32 Destination)
1622 if (!Stream_EnsureRemainingCapacity(s, 8))
1625 Stream_Write_UINT32(s, RTS_CMD_DESTINATION);
1626 Stream_Write_UINT32(s, Destination);
1631#define rts_send_buffer(channel, s, frag_length) \
1632 rts_send_buffer_int((channel), (s), (frag_length), __FILE__, __LINE__, __func__)
1635static BOOL rts_send_buffer_int(
RpcChannel* channel,
wStream* s,
size_t frag_length,
1636 const char* file,
size_t line,
const char* fkt)
1638 BOOL status = FALSE;
1641 WINPR_ASSERT(channel);
1642 WINPR_ASSERT(channel->rpc);
1645 Stream_SealLength(s);
1647 const DWORD level = WLOG_TRACE;
1648 if (WLog_IsLevelActive(channel->rpc->log, level))
1650 WLog_PrintTextMessage(channel->rpc->log, level, line, file, fkt,
1651 "Sending [%s] %" PRIuz
" bytes", fkt, Stream_Length(s));
1655 if (Stream_Length(s) != frag_length)
1658 rc = rpc_channel_write(channel, Stream_Buffer(s), Stream_Length(s));
1661 if ((
size_t)rc != Stream_Length(s))
1670BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc)
1672 BOOL status = FALSE;
1675 UINT32 ReceiveWindowSize = 0;
1676 BYTE* OUTChannelCookie =
nullptr;
1677 BYTE* VirtualConnectionCookie =
nullptr;
1683 connection = rpc->VirtualConnection;
1684 WINPR_ASSERT(connection);
1686 outChannel = connection->DefaultOutChannel;
1687 WINPR_ASSERT(outChannel);
1689 header.header.frag_length = 76;
1690 header.Flags = RTS_FLAG_NONE;
1691 header.NumberOfCommands = 4;
1693 WLog_DBG(TAG,
"Sending CONN/A1 RTS PDU");
1694 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1695 OUTChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1696 ReceiveWindowSize = outChannel->ReceiveWindow;
1698 buffer = Stream_New(
nullptr, header.header.frag_length);
1703 if (!rts_write_pdu_header(buffer, &header))
1705 status = rts_version_command_write(buffer);
1708 status = rts_cookie_command_write(
1709 buffer, VirtualConnectionCookie);
1712 status = rts_cookie_command_write(buffer, OUTChannelCookie);
1715 status = rts_receive_window_size_command_write(
1716 buffer, ReceiveWindowSize);
1719 status = rts_send_buffer(&outChannel->common, buffer, header.header.frag_length);
1721 Stream_Free(buffer, TRUE);
1725BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc,
wStream* buffer)
1728 UINT32 ConnectionTimeout = 0;
1731 if (!rts_read_pdu_header(buffer, &header))
1734 if (header.rts.Flags != RTS_FLAG_NONE)
1736 WLog_Print(rpc->log, WLOG_ERROR,
1737 "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected Flags=0x%08" PRIx32
1738 ", expected 0x%08" PRIx32,
1739 header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
1742 if (header.rts.NumberOfCommands != 1)
1744 WLog_Print(rpc->log, WLOG_ERROR,
1745 "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected NumberOfCommands=%" PRIu32
1747 header.rts.NumberOfCommands);
1751 if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
1754 WLog_Print(rpc->log, WLOG_DEBUG,
"Receiving CONN/A3 RTS PDU: ConnectionTimeout: %" PRIu32
"",
1758 WINPR_ASSERT(rpc->VirtualConnection);
1759 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1761 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
1766 rts_free_pdu_header(&header, FALSE);
1772BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc)
1774 BOOL status = FALSE;
1777 BYTE* INChannelCookie =
nullptr;
1778 BYTE* AssociationGroupId =
nullptr;
1779 BYTE* VirtualConnectionCookie =
nullptr;
1785 connection = rpc->VirtualConnection;
1786 WINPR_ASSERT(connection);
1788 inChannel = connection->DefaultInChannel;
1789 WINPR_ASSERT(inChannel);
1791 header.header.frag_length = 104;
1792 header.Flags = RTS_FLAG_NONE;
1793 header.NumberOfCommands = 6;
1795 WLog_DBG(TAG,
"Sending CONN/B1 RTS PDU");
1797 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1798 INChannelCookie = (BYTE*)&(inChannel->common.Cookie);
1799 AssociationGroupId = (BYTE*)&(connection->AssociationGroupId);
1800 buffer = Stream_New(
nullptr, header.header.frag_length);
1804 if (!rts_write_pdu_header(buffer, &header))
1806 if (!rts_version_command_write(buffer))
1808 if (!rts_cookie_command_write(buffer,
1809 VirtualConnectionCookie))
1811 if (!rts_cookie_command_write(buffer, INChannelCookie))
1813 if (!rts_channel_lifetime_command_write(buffer,
1814 rpc->ChannelLifetime))
1816 if (!rts_client_keepalive_command_write(buffer,
1817 rpc->KeepAliveInterval))
1819 if (!rts_association_group_id_command_write(
1820 buffer, AssociationGroupId))
1822 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1824 Stream_Free(buffer, TRUE);
1830BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc,
wStream* buffer)
1833 UINT32 ReceiveWindowSize = 0;
1834 UINT32 ConnectionTimeout = 0;
1837 WINPR_ASSERT(buffer);
1840 if (!rts_read_pdu_header(buffer, &header))
1843 if (header.rts.Flags != RTS_FLAG_NONE)
1845 WLog_Print(rpc->log, WLOG_ERROR,
1846 "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected Flags=0x%08" PRIx32
1847 ", expected 0x%08" PRIx32,
1848 header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
1851 if (header.rts.NumberOfCommands != 3)
1853 WLog_Print(rpc->log, WLOG_ERROR,
1854 "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected NumberOfCommands=%" PRIu32
1856 header.rts.NumberOfCommands);
1859 if (!rts_version_command_read(rpc, buffer,
nullptr))
1862 if (!rts_receive_window_size_command_read(rpc, buffer, &ReceiveWindowSize))
1865 if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
1868 WLog_Print(rpc->log, WLOG_DEBUG,
1869 "Receiving CONN/C2 RTS PDU: ConnectionTimeout: %" PRIu32
1870 " ReceiveWindowSize: %" PRIu32
"",
1871 ConnectionTimeout, ReceiveWindowSize);
1874 WINPR_ASSERT(rpc->VirtualConnection);
1875 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1877 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
1878 rpc->VirtualConnection->DefaultInChannel->PeerReceiveWindow = ReceiveWindowSize;
1883 rts_free_pdu_header(&header, FALSE);
1889BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc)
1891 BOOL status = FALSE;
1894 UINT32 BytesReceived = 0;
1895 UINT32 AvailableWindow = 0;
1896 BYTE* ChannelCookie =
nullptr;
1903 connection = rpc->VirtualConnection;
1904 WINPR_ASSERT(connection);
1906 inChannel = connection->DefaultInChannel;
1907 WINPR_ASSERT(inChannel);
1909 outChannel = connection->DefaultOutChannel;
1910 WINPR_ASSERT(outChannel);
1912 header.header.frag_length = 56;
1913 header.Flags = RTS_FLAG_OTHER_CMD;
1914 header.NumberOfCommands = 2;
1916 WLog_DBG(TAG,
"Sending FlowControlAck RTS PDU");
1918 BytesReceived = outChannel->BytesReceived;
1919 AvailableWindow = outChannel->AvailableWindowAdvertised;
1920 ChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1921 outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
1922 buffer = Stream_New(
nullptr, header.header.frag_length);
1927 if (!rts_write_pdu_header(buffer, &header))
1929 if (!rts_destination_command_write(buffer, FDOutProxy))
1933 if (!rts_flow_control_ack_command_write(buffer, BytesReceived, AvailableWindow, ChannelCookie))
1936 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1938 Stream_Free(buffer, TRUE);
1943static int rts_recv_flow_control_ack_pdu(rdpRpc* rpc,
wStream* buffer)
1946 UINT32 BytesReceived = 0;
1947 UINT32 AvailableWindow = 0;
1948 BYTE ChannelCookie[16] = WINPR_C_ARRAY_INIT;
1950 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1951 (BYTE*)&ChannelCookie);
1955 "Receiving FlowControlAck RTS PDU: BytesReceived: %" PRIu32
1956 " AvailableWindow: %" PRIu32
"",
1957 BytesReceived, AvailableWindow);
1959 WINPR_ASSERT(rpc->VirtualConnection);
1960 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1962 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1963 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1968static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc,
wStream* buffer)
1971 UINT32 Destination = 0;
1972 UINT32 BytesReceived = 0;
1973 UINT32 AvailableWindow = 0;
1974 BYTE ChannelCookie[16] = WINPR_C_ARRAY_INIT;
1992 int rc = rts_destination_command_read(rpc, buffer, &Command);
1996 if (Command != RTS_CMD_DESTINATION)
1998 char buffer1[64] = WINPR_C_ARRAY_INIT;
1999 char buffer2[64] = WINPR_C_ARRAY_INIT;
2000 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
2001 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
2002 rts_command_to_string(RTS_CMD_DESTINATION, buffer2,
sizeof(buffer2)));
2006 rc = rts_destination_command_read(rpc, buffer, &Destination);
2010 switch (Destination)
2021 WLog_Print(rpc->log, WLOG_ERROR,
2022 "got destination %" PRIu32
2023 ", expected one of [FDClient[0]|FDInProxy[1]|FDServer[2]|FDOutProxy[3]",
2028 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
2034 "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %" PRIu32
2035 " AvailableWindow: %" PRIu32
"",
2036 BytesReceived, AvailableWindow);
2038 WINPR_ASSERT(rpc->VirtualConnection);
2039 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
2040 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
2041 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
2045BOOL rts_recv_ping_pdu(rdpRpc* rpc,
wStream* s)
2051 WINPR_ASSERT(rpc->auth);
2054 if (!rts_read_pdu_header(s, &header))
2058 if (header.common.ptype != PTYPE_RTS)
2060 WLog_Print(rpc->log, WLOG_ERROR,
"received invalid ping PDU, type is 0x%" PRIx32,
2061 header.common.ptype);
2064 if (header.rts.Flags != RTS_FLAG_PING)
2066 WLog_Print(rpc->log, WLOG_ERROR,
"received unexpected ping PDU::Flags 0x%" PRIx32,
2071 rts_free_pdu_header(&header, FALSE);
2076static int rts_send_ping_pdu(rdpRpc* rpc)
2078 BOOL status = FALSE;
2084 WINPR_ASSERT(rpc->VirtualConnection);
2086 inChannel = rpc->VirtualConnection->DefaultInChannel;
2087 WINPR_ASSERT(inChannel);
2089 header.header.frag_length = 20;
2090 header.Flags = RTS_FLAG_PING;
2091 header.NumberOfCommands = 0;
2093 WLog_DBG(TAG,
"Sending Ping RTS PDU");
2094 buffer = Stream_New(
nullptr, header.header.frag_length);
2099 if (!rts_write_pdu_header(buffer, &header))
2101 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2103 Stream_Free(buffer, TRUE);
2104 return (status) ? 1 : -1;
2107BOOL rts_command_length(UINT32 CommandType,
wStream* s,
size_t* length, BOOL silent)
2110 size_t CommandLength = 0;
2114 switch (CommandType)
2116 case RTS_CMD_RECEIVE_WINDOW_SIZE:
2117 CommandLength = RTS_CMD_RECEIVE_WINDOW_SIZE_LENGTH;
2120 case RTS_CMD_FLOW_CONTROL_ACK:
2121 CommandLength = RTS_CMD_FLOW_CONTROL_ACK_LENGTH;
2124 case RTS_CMD_CONNECTION_TIMEOUT:
2125 CommandLength = RTS_CMD_CONNECTION_TIMEOUT_LENGTH;
2128 case RTS_CMD_COOKIE:
2129 CommandLength = RTS_CMD_COOKIE_LENGTH;
2132 case RTS_CMD_CHANNEL_LIFETIME:
2133 CommandLength = RTS_CMD_CHANNEL_LIFETIME_LENGTH;
2136 case RTS_CMD_CLIENT_KEEPALIVE:
2137 CommandLength = RTS_CMD_CLIENT_KEEPALIVE_LENGTH;
2140 case RTS_CMD_VERSION:
2141 CommandLength = RTS_CMD_VERSION_LENGTH;
2145 CommandLength = RTS_CMD_EMPTY_LENGTH;
2148 case RTS_CMD_PADDING:
2149 if (!rts_padding_command_read(s, &padding, silent))
2153 case RTS_CMD_NEGATIVE_ANCE:
2154 CommandLength = RTS_CMD_NEGATIVE_ANCE_LENGTH;
2158 CommandLength = RTS_CMD_ANCE_LENGTH;
2161 case RTS_CMD_CLIENT_ADDRESS:
2162 if (!rts_client_address_command_read(s, &CommandLength, silent))
2166 case RTS_CMD_ASSOCIATION_GROUP_ID:
2167 CommandLength = RTS_CMD_ASSOCIATION_GROUP_ID_LENGTH;
2170 case RTS_CMD_DESTINATION:
2171 CommandLength = RTS_CMD_DESTINATION_LENGTH;
2174 case RTS_CMD_PING_TRAFFIC_SENT_NOTIFY:
2175 CommandLength = RTS_CMD_PING_TRAFFIC_SENT_NOTIFY_LENGTH;
2179 WLog_ERR(TAG,
"Error: Unknown RTS Command Type: 0x%" PRIx32
"", CommandType);
2183 CommandLength += padding;
2184 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, CommandLength, silent))
2188 *length = CommandLength;
2193static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
2195 BOOL status = FALSE;
2198 BYTE* SuccessorChannelCookie =
nullptr;
2203 WINPR_ASSERT(rpc->VirtualConnection);
2205 inChannel = rpc->VirtualConnection->DefaultInChannel;
2206 WINPR_ASSERT(inChannel);
2208 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2209 WINPR_ASSERT(nextOutChannel);
2211 header.header.frag_length = 56;
2212 header.Flags = RTS_FLAG_OUT_CHANNEL;
2213 header.NumberOfCommands = 3;
2215 WLog_DBG(TAG,
"Sending OUT_R2/A7 RTS PDU");
2217 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2218 buffer = Stream_New(
nullptr, header.header.frag_length);
2223 if (!rts_write_pdu_header(buffer, &header))
2225 if (!rts_destination_command_write(buffer, FDServer))
2227 if (!rts_cookie_command_write(buffer,
2228 SuccessorChannelCookie))
2230 if (!rts_version_command_write(buffer))
2232 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2234 Stream_Free(buffer, TRUE);
2235 return (status) ? 1 : -1;
2239static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc)
2241 BOOL status = FALSE;
2247 WINPR_ASSERT(rpc->VirtualConnection);
2249 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2250 WINPR_ASSERT(nextOutChannel);
2252 header.header.frag_length = 24;
2253 header.Flags = RTS_FLAG_PING;
2254 header.NumberOfCommands = 1;
2256 WLog_DBG(TAG,
"Sending OUT_R2/C1 RTS PDU");
2257 buffer = Stream_New(
nullptr, header.header.frag_length);
2262 if (!rts_write_pdu_header(buffer, &header))
2265 if (!rts_empty_command_write(buffer))
2267 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2269 Stream_Free(buffer, TRUE);
2270 return (status) ? 1 : -1;
2273BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
2275 BOOL status = FALSE;
2278 UINT32 ReceiveWindowSize = 0;
2279 BYTE* VirtualConnectionCookie =
nullptr;
2280 BYTE* PredecessorChannelCookie =
nullptr;
2281 BYTE* SuccessorChannelCookie =
nullptr;
2288 connection = rpc->VirtualConnection;
2289 WINPR_ASSERT(connection);
2291 outChannel = connection->DefaultOutChannel;
2292 WINPR_ASSERT(outChannel);
2294 nextOutChannel = connection->NonDefaultOutChannel;
2295 WINPR_ASSERT(nextOutChannel);
2297 header.header.frag_length = 96;
2298 header.Flags = RTS_FLAG_RECYCLE_CHANNEL;
2299 header.NumberOfCommands = 5;
2301 WLog_DBG(TAG,
"Sending OUT_R1/A3 RTS PDU");
2303 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
2304 PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie);
2305 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2306 ReceiveWindowSize = outChannel->ReceiveWindow;
2307 buffer = Stream_New(
nullptr, header.header.frag_length);
2312 if (!rts_write_pdu_header(buffer, &header))
2314 if (!rts_version_command_write(buffer))
2316 if (!rts_cookie_command_write(buffer,
2317 VirtualConnectionCookie))
2319 if (!rts_cookie_command_write(
2320 buffer, PredecessorChannelCookie))
2322 if (!rts_cookie_command_write(buffer,
2323 SuccessorChannelCookie))
2325 if (!rts_receive_window_size_command_write(buffer,
2329 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2331 Stream_Free(buffer, TRUE);
2336static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc,
wStream* buffer)
2339 UINT32 Destination = 0;
2341 WINPR_ASSERT(buffer);
2344 WINPR_ASSERT(connection);
2346 WLog_DBG(TAG,
"Receiving OUT R1/A2 RTS PDU");
2348 status = rts_destination_command_read(rpc, buffer, &Destination);
2352 connection->NonDefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
2354 if (!connection->NonDefaultOutChannel)
2357 status = rpc_out_channel_replacement_connect(connection->NonDefaultOutChannel, 5000);
2361 WLog_ERR(TAG,
"rpc_out_channel_replacement_connect failure");
2365 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2366 CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
2371static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED
wStream* buffer)
2377 WINPR_ASSERT(buffer);
2379 connection = rpc->VirtualConnection;
2380 WINPR_ASSERT(connection);
2382 WLog_DBG(TAG,
"Receiving OUT R2/A6 RTS PDU");
2383 status = rts_send_OUT_R2_C1_pdu(rpc);
2387 WLog_ERR(TAG,
"rts_send_OUT_R2_C1_pdu failure");
2391 status = rts_send_OUT_R2_A7_pdu(rpc);
2395 WLog_ERR(TAG,
"rts_send_OUT_R2_A7_pdu failure");
2399 rpc_out_channel_transition_to_state(connection->NonDefaultOutChannel,
2400 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2401 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2402 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2407static int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED
wStream* buffer)
2412 WINPR_ASSERT(buffer);
2414 connection = rpc->VirtualConnection;
2415 WINPR_ASSERT(connection);
2417 WLog_DBG(TAG,
"Receiving OUT R2/B3 RTS PDU");
2418 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2419 CLIENT_OUT_CHANNEL_STATE_RECYCLED);
2425 BOOL status = FALSE;
2431 WINPR_ASSERT(buffer);
2432 WINPR_ASSERT(header);
2434 wLog* log = WLog_Get(TAG);
2436 const size_t total = Stream_Length(buffer);
2437 length = header->common.frag_length;
2440 WLog_Print(log, WLOG_ERROR,
"PDU length %" PRIuz
" does not match available data %" PRIuz,
2445 connection = rpc->VirtualConnection;
2449 WLog_Print(log, WLOG_ERROR,
"not connected, aborting");
2453 if (!rts_extract_pdu_signature(&signature, buffer, header))
2456 rts_print_pdu_signature(log, WLOG_TRACE, &signature);
2458 if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE,
sizeof(signature)) == 0)
2460 status = rts_recv_flow_control_ack_pdu(rpc, buffer);
2462 else if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE,
2463 sizeof(signature)) == 0)
2465 status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer);
2467 else if (memcmp(&signature, &RTS_PDU_PING_SIGNATURE,
sizeof(signature)) == 0)
2469 status = rts_send_ping_pdu(rpc);
2473 if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
2475 if (memcmp(&signature, &RTS_PDU_OUT_R1_A2_SIGNATURE,
sizeof(signature)) == 0)
2477 status = rts_recv_OUT_R1_A2_pdu(rpc, buffer);
2480 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_A6W)
2482 if (memcmp(&signature, &RTS_PDU_OUT_R2_A6_SIGNATURE,
sizeof(signature)) == 0)
2484 status = rts_recv_OUT_R2_A6_pdu(rpc, buffer);
2487 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_B3W)
2489 if (memcmp(&signature, &RTS_PDU_OUT_R2_B3_SIGNATURE,
sizeof(signature)) == 0)
2491 status = rts_recv_OUT_R2_B3_pdu(rpc, buffer);
2498 const UINT32 SignatureId = rts_identify_pdu_signature(&signature,
nullptr);
2499 WLog_Print(log, WLOG_ERROR,
"error parsing RTS PDU with signature id: 0x%08" PRIX32
"",
2501 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2504 const size_t rem = Stream_GetRemainingLength(buffer);
2507 WLog_Print(log, WLOG_ERROR,
"%" PRIuz
" bytes or %" PRIuz
" total not parsed, aborting",
2509 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2521 if (!rts_write_common_pdu_header(s, &auth->header))
2524 if (!Stream_EnsureRemainingCapacity(s, 2ull *
sizeof(UINT16)))
2527 Stream_Write_UINT16(s, auth->max_xmit_frag);
2528 Stream_Write_UINT16(s, auth->max_recv_frag);
2530 return rts_write_auth_verifier(s, &auth->auth_verifier, &auth->header);
2539 if (!rts_write_common_pdu_header(s, &bind->header))
2542 if (!Stream_EnsureRemainingCapacity(s, 8))
2545 Stream_Write_UINT16(s, bind->max_xmit_frag);
2546 Stream_Write_UINT16(s, bind->max_recv_frag);
2547 Stream_Write_UINT32(s, bind->assoc_group_id);
2549 if (!rts_write_context_list(s, &bind->p_context_elem))
2552 return rts_write_auth_verifier(s, &bind->auth_verifier, &bind->header);
2555BOOL rts_conditional_check_and_log(
const char* tag,
wStream* s,
size_t size, BOOL silent,
2556 const char* fkt,
const char* file,
size_t line)
2560 const size_t rem = Stream_GetRemainingLength(s);
2561 return (rem >= size);
2564 return Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, size, 1,
"%s(%s:%" PRIuz
")", fkt,
2568BOOL rts_conditional_safe_seek(
wStream* s,
size_t size, BOOL silent,
const char* fkt,
2569 const char* file,
size_t line)
2573 const size_t rem = Stream_GetRemainingLength(s);
2577 return Stream_SafeSeekEx(s, size, file, line, fkt);