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);
72static const char* rts_command_to_string(UINT32 cmd,
char* buffer,
size_t len)
74 const char* str =
nullptr;
84 ENTRY(RTS_CMD_RECEIVE_WINDOW_SIZE);
85 ENTRY(RTS_CMD_FLOW_CONTROL_ACK);
86 ENTRY(RTS_CMD_CONNECTION_TIMEOUT);
87 ENTRY(RTS_CMD_COOKIE);
88 ENTRY(RTS_CMD_CHANNEL_LIFETIME);
89 ENTRY(RTS_CMD_CLIENT_KEEPALIVE);
90 ENTRY(RTS_CMD_VERSION);
92 ENTRY(RTS_CMD_PADDING);
93 ENTRY(RTS_CMD_NEGATIVE_ANCE);
95 ENTRY(RTS_CMD_CLIENT_ADDRESS);
96 ENTRY(RTS_CMD_ASSOCIATION_GROUP_ID);
97 ENTRY(RTS_CMD_DESTINATION);
98 ENTRY(RTS_CMD_PING_TRAFFIC_SENT_NOTIFY);
99 ENTRY(RTS_CMD_LAST_ID);
101 str =
"RTS_CMD_UNKNOWN";
107 (void)_snprintf(buffer, len,
"%s [0x%08" PRIx32
"]", str, cmd);
111static const char* rts_pdu_ptype_to_string(UINT32 ptype)
116 return "PTYPE_REQUEST";
120 return "PTYPE_RESPONSE";
122 return "PTYPE_FAULT";
124 return "PTYPE_WORKING";
126 return "PTYPE_NOCALL";
128 return "PTYPE_REJECT";
131 case PTYPE_CL_CANCEL:
132 return "PTYPE_CL_CANCEL";
135 case PTYPE_CANCEL_ACK:
136 return "PTYPE_CANCEL_ACK";
140 return "PTYPE_BIND_ACK";
142 return "PTYPE_BIND_NAK";
143 case PTYPE_ALTER_CONTEXT:
144 return "PTYPE_ALTER_CONTEXT";
145 case PTYPE_ALTER_CONTEXT_RESP:
146 return "PTYPE_ALTER_CONTEXT_RESP";
147 case PTYPE_RPC_AUTH_3:
148 return "PTYPE_RPC_AUTH_3";
150 return "PTYPE_SHUTDOWN";
151 case PTYPE_CO_CANCEL:
152 return "PTYPE_CO_CANCEL";
154 return "PTYPE_ORPHANED";
165 header.header.rpc_vers = 5;
166 header.header.rpc_vers_minor = 0;
167 header.header.ptype = PTYPE_RTS;
168 header.header.packed_drep[0] = 0x10;
169 header.header.packed_drep[1] = 0x00;
170 header.header.packed_drep[2] = 0x00;
171 header.header.packed_drep[3] = 0x00;
172 header.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
173 header.header.auth_length = 0;
174 header.header.call_id = 0;
179static BOOL rts_align_stream(
wStream* s,
size_t alignment, BOOL silent)
185 WINPR_ASSERT(alignment > 0);
187 pos = Stream_GetPosition(s);
188 pad = rpc_offset_align(&pos, alignment);
189 return Stream_ConditionalSafeSeek(s, pad, silent);
192static char* sdup(
const void* src,
size_t length)
195 WINPR_ASSERT(src || (length == 0));
199 dst = calloc(length + 1,
sizeof(
char));
202 memcpy(dst, src, length);
209 WINPR_ASSERT(header);
213 Stream_Write_UINT8(s, header->rpc_vers);
214 Stream_Write_UINT8(s, header->rpc_vers_minor);
215 Stream_Write_UINT8(s, header->ptype);
216 Stream_Write_UINT8(s, header->pfc_flags);
217 Stream_Write(s, header->packed_drep, ARRAYSIZE(header->packed_drep));
218 Stream_Write_UINT16(s, header->frag_length);
219 Stream_Write_UINT16(s, header->auth_length);
220 Stream_Write_UINT32(s, header->call_id);
228 WINPR_ASSERT(header);
233 return RTS_PDU_INCOMPLETE;
237 const size_t sz = Stream_GetRemainingLength(s);
239 return RTS_PDU_INCOMPLETE;
242 Stream_Read_UINT8(s, header->rpc_vers);
243 Stream_Read_UINT8(s, header->rpc_vers_minor);
244 Stream_Read_UINT8(s, header->ptype);
245 Stream_Read_UINT8(s, header->pfc_flags);
246 Stream_Read(s, header->packed_drep, ARRAYSIZE(header->packed_drep));
247 Stream_Read_UINT16(s, header->frag_length);
248 Stream_Read_UINT16(s, header->auth_length);
249 Stream_Read_UINT32(s, header->call_id);
254 WLog_WARN(TAG,
"Invalid header->frag_length of %" PRIu16
", expected %" PRIuz,
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;
274static BOOL rts_read_auth_verifier_no_checks(
wStream* s, auth_verifier_co_t* auth,
280 WINPR_ASSERT(header);
282 WINPR_ASSERT(header->frag_length > header->auth_length + 8);
285 *startPos = Stream_GetPosition(s);
289 const size_t expected = header->frag_length - header->auth_length - 8;
291 Stream_SetPosition(s, expected);
292 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 8, silent))
295 Stream_Read_UINT8(s, auth->auth_type);
296 Stream_Read_UINT8(s, auth->auth_level);
297 Stream_Read_UINT8(s, auth->auth_pad_length);
298 Stream_Read_UINT8(s, auth->auth_reserved);
299 Stream_Read_UINT32(s, auth->auth_context_id);
302 if (header->auth_length != 0)
304 const void* ptr = Stream_Pointer(s);
305 if (!Stream_ConditionalSafeSeek(s, header->auth_length, silent))
307 auth->auth_value = (BYTE*)sdup(ptr, header->auth_length);
308 if (auth->auth_value ==
nullptr)
315static BOOL rts_read_auth_verifier(
wStream* s, auth_verifier_co_t* auth,
321 WINPR_ASSERT(header);
323 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
326 const size_t expected = header->frag_length - header->auth_length - 8;
327 WINPR_ASSERT(pos + auth->auth_pad_length == expected);
328 return pos + auth->auth_pad_length == expected;
331static BOOL rts_read_auth_verifier_with_stub(
wStream* s, auth_verifier_co_t* auth,
335 size_t alloc_hint = 0;
336 BYTE** ptr =
nullptr;
338 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
341 switch (header->ptype)
346 alloc_hint = hdr->alloc_hint;
347 ptr = &hdr->stub_data;
353 alloc_hint = hdr->alloc_hint;
354 ptr = &hdr->stub_data;
360 alloc_hint = hdr->alloc_hint;
361 ptr = &hdr->stub_data;
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);
372 const void* src = Stream_Buffer(s) + pos;
374 if (off > header->frag_length)
376 "Unexpected alloc_hint(%" PRIuz
") for PDU %s: size %" PRIuz
377 ", frag_length %" PRIu16
", offset %" PRIuz,
378 alloc_hint, rts_pdu_ptype_to_string(header->ptype), size, header->frag_length,
384 *ptr = (BYTE*)sdup(src, size);
393static void rts_free_auth_verifier(auth_verifier_co_t* auth)
397 free(auth->auth_value);
400static BOOL rts_write_auth_verifier(
wStream* s,
const auth_verifier_co_t* auth,
404 UINT8 auth_pad_length = 0;
408 WINPR_ASSERT(header);
411 pos = Stream_GetPosition(s);
414 auth_pad_length = 4 - (pos % 4);
415 if (!Stream_EnsureRemainingCapacity(s, auth_pad_length))
417 Stream_Zero(s, auth_pad_length);
420#if defined(WITH_VERBOSE_WINPR_ASSERT) && (WITH_VERBOSE_WINPR_ASSERT != 0)
421 WINPR_ASSERT(header->frag_length + 8ull > header->auth_length);
423 size_t apos = Stream_GetPosition(s);
424 size_t expected = header->frag_length - header->auth_length - 8;
426 WINPR_ASSERT(apos == expected);
430 if (!Stream_EnsureRemainingCapacity(s,
sizeof(auth_verifier_co_t)))
433 Stream_Write_UINT8(s, auth->auth_type);
434 Stream_Write_UINT8(s, auth->auth_level);
435 Stream_Write_UINT8(s, auth_pad_length);
436 Stream_Write_UINT8(s, 0);
437 Stream_Write_UINT32(s, auth->auth_context_id);
439 if (!Stream_EnsureRemainingCapacity(s, header->auth_length))
441 Stream_Write(s, auth->auth_value, header->auth_length);
448 WINPR_ASSERT(version);
450 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2 *
sizeof(UINT8), silent))
452 Stream_Read_UINT8(s, version->major);
453 Stream_Read_UINT8(s, version->minor);
461 free(versions->p_protocols);
462 versions->p_protocols =
nullptr;
469 WINPR_ASSERT(versions);
471 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT8), silent))
474 Stream_Read_UINT8(s, versions->n_protocols);
476 if (versions->n_protocols > 0)
478 versions->p_protocols = calloc(versions->n_protocols,
sizeof(
p_rt_version_t));
479 if (!versions->p_protocols)
482 for (BYTE x = 0; x < versions->n_protocols; x++)
485 if (!rts_read_version(s, version, silent))
487 rts_free_supported_versions(versions);
500 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT16), silent))
503 Stream_Read_UINT16(s, port->length);
504 if (port->length == 0)
507 const void* ptr = Stream_ConstPointer(s);
508 if (!Stream_ConditionalSafeSeek(s, port->length, silent))
510 port->port_spec = sdup(ptr, port->length);
511 return port->port_spec !=
nullptr;
514static void rts_free_port_any(
port_any_t* port)
518 free(port->port_spec);
526 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(
p_uuid_t), silent))
529 Stream_Read_UINT32(s, uuid->time_low);
530 Stream_Read_UINT16(s, uuid->time_mid);
531 Stream_Read_UINT16(s, uuid->time_hi_and_version);
532 Stream_Read_UINT8(s, uuid->clock_seq_hi_and_reserved);
533 Stream_Read_UINT8(s, uuid->clock_seq_low);
534 Stream_Read(s, uuid->node, ARRAYSIZE(uuid->node));
543 if (!Stream_EnsureRemainingCapacity(s,
sizeof(
p_uuid_t)))
546 Stream_Write_UINT32(s, uuid->time_low);
547 Stream_Write_UINT16(s, uuid->time_mid);
548 Stream_Write_UINT16(s, uuid->time_hi_and_version);
549 Stream_Write_UINT8(s, uuid->clock_seq_hi_and_reserved);
550 Stream_Write_UINT8(s, uuid->clock_seq_low);
551 Stream_Write(s, uuid->node, ARRAYSIZE(uuid->node));
568 WINPR_ASSERT(syntax_id);
570 if (!rts_read_uuid(s, &syntax_id->if_uuid, silent))
573 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
576 Stream_Read_UINT32(s, syntax_id->if_version);
583 WINPR_ASSERT(syntax_id);
585 if (!rts_write_uuid(s, &syntax_id->if_uuid))
588 if (!Stream_EnsureRemainingCapacity(s, 4))
591 Stream_Write_UINT32(s, syntax_id->if_version);
599 rts_syntax_id_free(ptr->transfer_syntaxes);
603WINPR_ATTR_MALLOC(rts_context_elem_free, 1)
614 WINPR_ASSERT(element);
616 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
619 Stream_Read_UINT16(s, element->p_cont_id);
620 Stream_Read_UINT8(s, element->n_transfer_syn);
621 Stream_Read_UINT8(s, element->reserved);
623 if (!rts_read_syntax_id(s, &element->abstract_syntax, silent))
626 if (element->n_transfer_syn > 0)
628 element->transfer_syntaxes = rts_syntax_id_new(element->n_transfer_syn);
629 if (!element->transfer_syntaxes)
631 for (BYTE x = 0; x < element->n_transfer_syn; x++)
634 if (!rts_read_syntax_id(s, syn, silent))
645 WINPR_ASSERT(element);
647 if (!Stream_EnsureRemainingCapacity(s, 4))
649 Stream_Write_UINT16(s, element->p_cont_id);
650 Stream_Write_UINT8(s, element->n_transfer_syn);
651 Stream_Write_UINT8(s, element->reserved);
652 if (!rts_write_syntax_id(s, &element->abstract_syntax))
655 for (BYTE x = 0; x < element->n_transfer_syn; x++)
658 if (!rts_write_syntax_id(s, syn))
670 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
672 Stream_Read_UINT8(s, list->n_context_elem);
673 Stream_Read_UINT8(s, list->reserved);
674 Stream_Read_UINT16(s, list->reserved2);
676 if (list->n_context_elem > 0)
678 list->p_cont_elem = rts_context_elem_new(list->n_context_elem);
679 if (!list->p_cont_elem)
681 for (BYTE x = 0; x < list->n_context_elem; x++)
684 if (!rts_read_context_elem(s, element, silent))
695 rts_context_elem_free(list->p_cont_elem);
703 if (!Stream_EnsureRemainingCapacity(s, 4))
705 Stream_Write_UINT8(s, list->n_context_elem);
706 Stream_Write_UINT8(s, 0);
707 Stream_Write_UINT16(s, 0);
709 for (BYTE x = 0; x < list->n_context_elem; x++)
712 if (!rts_write_context_elem(s, element))
718static p_result_t* rts_result_new(
size_t count)
723static void rts_result_free(
p_result_t* results)
733 WINPR_ASSERT(result);
735 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2, silent))
738 const UINT16 res = Stream_Get_UINT16(s);
743 case provider_rejection:
747 WLog_ERR(TAG,
"Invalid p_cont_def_result_t %" PRIu16, res);
750 result->result = (p_cont_def_result_t)res;
752 const UINT16 reason = Stream_Get_UINT16(s);
755 case reason_not_specified:
756 case abstract_syntax_not_supported:
757 case proposed_transfer_syntaxes_not_supported:
758 case local_limit_exceeded:
761 WLog_ERR(TAG,
"Invalid p_provider_reason_t %" PRIu16, reason);
764 result->reason = (p_provider_reason_t)reason;
765 return rts_read_syntax_id(s, &result->transfer_syntax, silent);
768static void rts_free_result(
p_result_t* result)
779 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
781 Stream_Read_UINT8(s, list->n_results);
782 Stream_Read_UINT8(s, list->reserved);
783 Stream_Read_UINT16(s, list->reserved2);
785 if (list->n_results > 0)
787 list->p_results = rts_result_new(list->n_results);
788 if (!list->p_results)
791 for (BYTE x = 0; x < list->n_results; x++)
794 if (!rts_read_result(s, result, silent))
806 for (BYTE x = 0; x < list->n_results; x++)
809 rts_free_result(result);
811 rts_result_free(list->p_results);
819 rts_free_context_list(&ctx->p_context_elem);
820 rts_free_auth_verifier(&ctx->auth_verifier);
828 if (!Stream_ConditionalCheckAndLogRequiredLength(
832 Stream_Read_UINT16(s, ctx->max_xmit_frag);
833 Stream_Read_UINT16(s, ctx->max_recv_frag);
834 Stream_Read_UINT32(s, ctx->assoc_group_id);
836 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
839 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
845static BOOL rts_read_pdu_alter_context_response(
wStream* s,
852 if (!Stream_ConditionalCheckAndLogRequiredLength(
856 Stream_Read_UINT16(s, ctx->max_xmit_frag);
857 Stream_Read_UINT16(s, ctx->max_recv_frag);
858 Stream_Read_UINT32(s, ctx->assoc_group_id);
860 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
863 if (!rts_align_stream(s, 4, silent))
866 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
869 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
880 rts_free_port_any(&ctx->sec_addr);
881 rts_free_result_list(&ctx->p_result_list);
882 rts_free_auth_verifier(&ctx->auth_verifier);
890 if (!Stream_ConditionalCheckAndLogRequiredLength(
893 Stream_Read_UINT16(s, ctx->max_xmit_frag);
894 Stream_Read_UINT16(s, ctx->max_recv_frag);
895 Stream_Read_UINT32(s, ctx->assoc_group_id);
897 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
900 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
910 rts_free_context_list(&ctx->p_context_elem);
911 rts_free_auth_verifier(&ctx->auth_verifier);
919 if (!Stream_CheckAndLogRequiredLength(
922 Stream_Read_UINT16(s, ctx->max_xmit_frag);
923 Stream_Read_UINT16(s, ctx->max_recv_frag);
924 Stream_Read_UINT32(s, ctx->assoc_group_id);
926 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
929 if (!rts_align_stream(s, 4, silent))
932 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
935 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
942 rts_free_port_any(&ctx->sec_addr);
943 rts_free_result_list(&ctx->p_result_list);
944 rts_free_auth_verifier(&ctx->auth_verifier);
952 if (!Stream_ConditionalCheckAndLogRequiredLength(
955 Stream_Read_UINT16(s, ctx->provider_reject_reason);
956 return rts_read_supported_versions(s, &ctx->versions, silent);
964 rts_free_supported_versions(&ctx->versions);
972 if (!Stream_ConditionalCheckAndLogRequiredLength(
975 Stream_Read_UINT16(s, ctx->max_xmit_frag);
976 Stream_Read_UINT16(s, ctx->max_recv_frag);
978 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
985 rts_free_auth_verifier(&ctx->auth_verifier);
993 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 12, silent))
995 Stream_Read_UINT32(s, ctx->alloc_hint);
996 Stream_Read_UINT16(s, ctx->p_cont_id);
997 Stream_Read_UINT8(s, ctx->cancel_count);
998 Stream_Read_UINT8(s, ctx->reserved);
999 Stream_Read_UINT32(s, ctx->status);
1001 WLog_WARN(TAG,
"status=%s", Win32ErrorCode2Tag(ctx->status & 0xFFFF));
1002 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1009 rts_free_auth_verifier(&ctx->auth_verifier);
1017 if (!Stream_ConditionalCheckAndLogRequiredLength(
1020 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1027 rts_free_auth_verifier(&ctx->auth_verifier);
1035 if (!Stream_ConditionalCheckAndLogRequiredLength(
1038 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1045 rts_free_auth_verifier(&ctx->auth_verifier);
1053 if (!Stream_ConditionalCheckAndLogRequiredLength(
1056 Stream_Read_UINT32(s, ctx->alloc_hint);
1057 Stream_Read_UINT16(s, ctx->p_cont_id);
1058 Stream_Read_UINT16(s, ctx->opnum);
1059 if (!rts_read_uuid(s, &ctx->object, silent))
1062 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1069 rts_free_auth_verifier(&ctx->auth_verifier);
1077 if (!Stream_ConditionalCheckAndLogRequiredLength(
1080 Stream_Read_UINT32(s, ctx->alloc_hint);
1081 Stream_Read_UINT16(s, ctx->p_cont_id);
1082 Stream_Read_UINT8(s, ctx->cancel_count);
1083 Stream_Read_UINT8(s, ctx->reserved);
1085 if (!rts_align_stream(s, 8, silent))
1088 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1095 free(ctx->stub_data);
1096 rts_free_auth_verifier(&ctx->auth_verifier);
1104 if (!Stream_ConditionalCheckAndLogRequiredLength(
1108 Stream_Read_UINT16(s, ctx->Flags);
1109 Stream_Read_UINT16(s, ctx->NumberOfCommands);
1118void rts_free_pdu_header(
rpcconn_hdr_t* header, BOOL allocated)
1123 switch (header->common.ptype)
1125 case PTYPE_ALTER_CONTEXT:
1126 rts_free_pdu_alter_context(&header->alter_context);
1128 case PTYPE_ALTER_CONTEXT_RESP:
1129 rts_free_pdu_alter_context_response(&header->alter_context_response);
1132 rts_free_pdu_bind(&header->bind);
1134 case PTYPE_BIND_ACK:
1135 rts_free_pdu_bind_ack(&header->bind_ack);
1137 case PTYPE_BIND_NAK:
1138 rts_free_pdu_bind_nak(&header->bind_nak);
1140 case PTYPE_RPC_AUTH_3:
1141 rts_free_pdu_auth3(&header->rpc_auth_3);
1143 case PTYPE_CANCEL_ACK:
1144 rts_free_pdu_cancel_ack(&header->cancel);
1147 rts_free_pdu_fault(&header->fault);
1149 case PTYPE_ORPHANED:
1150 rts_free_pdu_orphaned(&header->orphaned);
1153 rts_free_pdu_request(&header->request);
1155 case PTYPE_RESPONSE:
1156 rts_free_pdu_response(&header->response);
1159 rts_free_pdu_rts(&header->rts);
1162 case PTYPE_SHUTDOWN:
1171 case PTYPE_CL_CANCEL:
1173 case PTYPE_CO_CANCEL:
1184 return rts_read_pdu_header_ex(s, header, FALSE);
1191 WINPR_ASSERT(header);
1193 const rts_pdu_status_t status = rts_read_common_pdu_header(s, &header->common, silent);
1194 if (status != RTS_PDU_VALID)
1197 WLog_DBG(TAG,
"Reading PDU type %s", rts_pdu_ptype_to_string(header->common.ptype));
1199 switch (header->common.ptype)
1201 case PTYPE_ALTER_CONTEXT:
1202 rc = rts_read_pdu_alter_context(s, &header->alter_context, silent);
1204 case PTYPE_ALTER_CONTEXT_RESP:
1205 rc = rts_read_pdu_alter_context_response(s, &header->alter_context_response, silent);
1208 rc = rts_read_pdu_bind(s, &header->bind, silent);
1210 case PTYPE_BIND_ACK:
1211 rc = rts_read_pdu_bind_ack(s, &header->bind_ack, silent);
1213 case PTYPE_BIND_NAK:
1214 rc = rts_read_pdu_bind_nak(s, &header->bind_nak, silent);
1216 case PTYPE_RPC_AUTH_3:
1217 rc = rts_read_pdu_auth3(s, &header->rpc_auth_3, silent);
1219 case PTYPE_CANCEL_ACK:
1220 rc = rts_read_pdu_cancel_ack(s, &header->cancel, silent);
1223 rc = rts_read_pdu_fault(s, &header->fault, silent);
1225 case PTYPE_ORPHANED:
1226 rc = rts_read_pdu_orphaned(s, &header->orphaned, silent);
1229 rc = rts_read_pdu_request(s, &header->request, silent);
1231 case PTYPE_RESPONSE:
1232 rc = rts_read_pdu_response(s, &header->response, silent);
1235 rc = rts_read_pdu_rts(s, &header->rts, silent);
1237 case PTYPE_SHUTDOWN:
1247 case PTYPE_CL_CANCEL:
1249 case PTYPE_CO_CANCEL:
1260 WINPR_ASSERT(header);
1264 if (!rts_write_common_pdu_header(s, &header->header))
1267 Stream_Write_UINT16(s, header->Flags);
1268 Stream_Write_UINT16(s, header->NumberOfCommands);
1273static BOOL rts_receive_window_size_command_read(rdpRpc* rpc,
wStream* buffer,
1274 UINT32* ReceiveWindowSize)
1277 WINPR_ASSERT(buffer);
1279 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1281 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1282 if (CommandType != RTS_CMD_RECEIVE_WINDOW_SIZE)
1284 WLog_Print(rpc->log, WLOG_ERROR,
1285 "[MS-RPCH] 2.2.3.5.1 ReceiveWindowSize::CommandType must be 0x%08" PRIx32
1288 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_RECEIVE_WINDOW_SIZE), CommandType);
1291 const UINT32 val = Stream_Get_UINT32(buffer);
1292 if (ReceiveWindowSize)
1293 *ReceiveWindowSize = val;
1299static BOOL rts_receive_window_size_command_write(
wStream* s, UINT32 ReceiveWindowSize)
1303 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT32)))
1306 Stream_Write_UINT32(s, RTS_CMD_RECEIVE_WINDOW_SIZE);
1307 Stream_Write_UINT32(s, ReceiveWindowSize);
1313static int rts_flow_control_ack_command_read(rdpRpc* rpc,
wStream* buffer, UINT32* BytesReceived,
1314 UINT32* AvailableWindow, BYTE* ChannelCookie)
1320 WINPR_ASSERT(buffer);
1322 int rc = rts_destination_command_read(rpc, buffer, &Command);
1326 if (Command != RTS_CMD_FLOW_CONTROL_ACK)
1328 char buffer1[64] = WINPR_C_ARRAY_INIT;
1329 char buffer2[64] = WINPR_C_ARRAY_INIT;
1330 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
1331 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
1332 rts_command_to_string(RTS_CMD_FLOW_CONTROL_ACK, buffer2,
sizeof(buffer2)));
1337 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 24))
1340 Stream_Read_UINT32(buffer, val);
1342 *BytesReceived = val;
1344 Stream_Read_UINT32(buffer, val);
1345 if (AvailableWindow)
1346 *AvailableWindow = val;
1349 Stream_Read(buffer, ChannelCookie, 16);
1351 Stream_Seek(buffer, 16);
1356static BOOL rts_flow_control_ack_command_write(
wStream* s, UINT32 BytesReceived,
1357 UINT32 AvailableWindow, BYTE* ChannelCookie)
1361 if (!Stream_EnsureRemainingCapacity(s, 28))
1364 Stream_Write_UINT32(s, RTS_CMD_FLOW_CONTROL_ACK);
1365 Stream_Write_UINT32(s, BytesReceived);
1366 Stream_Write_UINT32(s, AvailableWindow);
1367 Stream_Write(s, ChannelCookie, 16);
1373static BOOL rts_connection_timeout_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc,
wStream* buffer,
1374 UINT32* ConnectionTimeout)
1377 WINPR_ASSERT(buffer);
1379 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1382 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1383 if (CommandType != RTS_CMD_CONNECTION_TIMEOUT)
1385 WLog_Print(rpc->log, WLOG_ERROR,
1386 "[MS-RPCH] 2.2.3.5.3 ConnectionTimeout::CommandType must be 0x%08" PRIx32
1389 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_CONNECTION_TIMEOUT), CommandType);
1392 const UINT32 val = Stream_Get_UINT32(buffer);
1393 if (ConnectionTimeout)
1394 *ConnectionTimeout = val;
1399static BOOL rts_cookie_command_write(
wStream* s,
const BYTE* Cookie)
1403 if (!Stream_EnsureRemainingCapacity(s, 20))
1406 Stream_Write_UINT32(s, RTS_CMD_COOKIE);
1407 Stream_Write(s, Cookie, 16);
1412static BOOL rts_channel_lifetime_command_write(
wStream* s, UINT32 ChannelLifetime)
1416 if (!Stream_EnsureRemainingCapacity(s, 8))
1418 Stream_Write_UINT32(s, RTS_CMD_CHANNEL_LIFETIME);
1419 Stream_Write_UINT32(s, ChannelLifetime);
1424static BOOL rts_client_keepalive_command_write(
wStream* s, UINT32 ClientKeepalive)
1428 if (!Stream_EnsureRemainingCapacity(s, 8))
1436 Stream_Write_UINT32(s, RTS_CMD_CLIENT_KEEPALIVE);
1437 Stream_Write_UINT32(s, ClientKeepalive);
1443static BOOL rts_version_command_read(rdpRpc* rpc,
wStream* buffer, uint32_t* pversion)
1446 WINPR_ASSERT(buffer);
1448 if (!Stream_EnsureRemainingCapacity(buffer, 8))
1451 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1452 if (CommandType != RTS_CMD_VERSION)
1454 WLog_Print(rpc->log, WLOG_ERROR,
1455 "[MS-RPCH] 2.2.3.5.7 Version::CommandType must be 0x%08" PRIx32
", got "
1457 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_VERSION), CommandType);
1460 const uint32_t version = Stream_Get_UINT32(buffer);
1463 WLog_Print(rpc->log, WLOG_WARN,
1464 "[MS-RPCH] 2.2.3.5.7 Version::Version should be 0x00000001, got 0x%08" PRIx32,
1468 *pversion = version;
1474static BOOL rts_version_command_write(
wStream* buffer)
1476 WINPR_ASSERT(buffer);
1478 if (!Stream_EnsureRemainingCapacity((buffer), 8))
1481 Stream_Write_UINT32(buffer, RTS_CMD_VERSION);
1482 Stream_Write_UINT32(buffer, 1);
1487static BOOL rts_empty_command_write(
wStream* s)
1491 if (!Stream_EnsureRemainingCapacity(s, 8))
1494 Stream_Write_UINT32(s, RTS_CMD_EMPTY);
1499static BOOL rts_padding_command_read(
wStream* s,
size_t* length, BOOL silent)
1501 UINT32 ConformanceCount = 0;
1503 WINPR_ASSERT(length);
1504 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1506 Stream_Read_UINT32(s, ConformanceCount);
1507 *length = ConformanceCount + 4;
1511static BOOL rts_client_address_command_read(
wStream* s,
size_t* length, BOOL silent)
1513 UINT32 AddressType = 0;
1516 WINPR_ASSERT(length);
1518 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1520 Stream_Read_UINT32(s, AddressType);
1522 if (AddressType == 0)
1526 *length = 4 + 4 + 12;
1532 *length = 4 + 16 + 12;
1537static BOOL rts_association_group_id_command_write(
wStream* s,
const BYTE* AssociationGroupId)
1541 if (!Stream_EnsureRemainingCapacity(s, 20))
1544 Stream_Write_UINT32(s, RTS_CMD_ASSOCIATION_GROUP_ID);
1545 Stream_Write(s, AssociationGroupId, 16);
1550static int rts_destination_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc,
wStream* buffer,
1551 UINT32* Destination)
1555 WINPR_ASSERT(buffer);
1557 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 4))
1559 Stream_Read_UINT32(buffer, val);
1566static BOOL rts_destination_command_write(
wStream* s, UINT32 Destination)
1570 if (!Stream_EnsureRemainingCapacity(s, 8))
1573 Stream_Write_UINT32(s, RTS_CMD_DESTINATION);
1574 Stream_Write_UINT32(s, Destination);
1579BOOL rts_generate_cookie(BYTE* cookie)
1581 WINPR_ASSERT(cookie);
1582 return winpr_RAND(cookie, 16) >= 0;
1585#define rts_send_buffer(channel, s, frag_length) \
1586 rts_send_buffer_int((channel), (s), (frag_length), __FILE__, __LINE__, __func__)
1587static BOOL rts_send_buffer_int(
RpcChannel* channel,
wStream* s,
size_t frag_length,
1588 const char* file,
size_t line,
const char* fkt)
1590 BOOL status = FALSE;
1593 WINPR_ASSERT(channel);
1594 WINPR_ASSERT(channel->rpc);
1597 Stream_SealLength(s);
1599 const DWORD level = WLOG_TRACE;
1600 if (WLog_IsLevelActive(channel->rpc->log, level))
1602 WLog_PrintTextMessage(channel->rpc->log, level, line, file, fkt,
1603 "Sending [%s] %" PRIuz
" bytes", fkt, Stream_Length(s));
1607 if (Stream_Length(s) != frag_length)
1610 rc = rpc_channel_write(channel, Stream_Buffer(s), Stream_Length(s));
1613 if ((
size_t)rc != Stream_Length(s))
1622BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc)
1624 BOOL status = FALSE;
1627 UINT32 ReceiveWindowSize = 0;
1628 BYTE* OUTChannelCookie =
nullptr;
1629 BYTE* VirtualConnectionCookie =
nullptr;
1635 connection = rpc->VirtualConnection;
1636 WINPR_ASSERT(connection);
1638 outChannel = connection->DefaultOutChannel;
1639 WINPR_ASSERT(outChannel);
1641 header.header.frag_length = 76;
1642 header.Flags = RTS_FLAG_NONE;
1643 header.NumberOfCommands = 4;
1645 WLog_DBG(TAG,
"Sending CONN/A1 RTS PDU");
1646 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1647 OUTChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1648 ReceiveWindowSize = outChannel->ReceiveWindow;
1650 buffer = Stream_New(
nullptr, header.header.frag_length);
1655 if (!rts_write_pdu_header(buffer, &header))
1657 status = rts_version_command_write(buffer);
1660 status = rts_cookie_command_write(
1661 buffer, VirtualConnectionCookie);
1664 status = rts_cookie_command_write(buffer, OUTChannelCookie);
1667 status = rts_receive_window_size_command_write(
1668 buffer, ReceiveWindowSize);
1671 status = rts_send_buffer(&outChannel->common, buffer, header.header.frag_length);
1673 Stream_Free(buffer, TRUE);
1677BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc,
wStream* buffer)
1680 UINT32 ConnectionTimeout = 0;
1683 if (!rts_read_pdu_header(buffer, &header))
1686 if (header.rts.Flags != RTS_FLAG_NONE)
1688 WLog_Print(rpc->log, WLOG_ERROR,
1689 "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected Flags=0x%08" PRIx32
1690 ", expected 0x%08" PRIx32,
1691 header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
1694 if (header.rts.NumberOfCommands != 1)
1696 WLog_Print(rpc->log, WLOG_ERROR,
1697 "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected NumberOfCommands=%" PRIu32
1699 header.rts.NumberOfCommands);
1703 if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
1706 WLog_Print(rpc->log, WLOG_DEBUG,
"Receiving CONN/A3 RTS PDU: ConnectionTimeout: %" PRIu32
"",
1710 WINPR_ASSERT(rpc->VirtualConnection);
1711 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1713 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
1718 rts_free_pdu_header(&header, FALSE);
1724BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc)
1726 BOOL status = FALSE;
1729 BYTE* INChannelCookie =
nullptr;
1730 BYTE* AssociationGroupId =
nullptr;
1731 BYTE* VirtualConnectionCookie =
nullptr;
1737 connection = rpc->VirtualConnection;
1738 WINPR_ASSERT(connection);
1740 inChannel = connection->DefaultInChannel;
1741 WINPR_ASSERT(inChannel);
1743 header.header.frag_length = 104;
1744 header.Flags = RTS_FLAG_NONE;
1745 header.NumberOfCommands = 6;
1747 WLog_DBG(TAG,
"Sending CONN/B1 RTS PDU");
1749 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1750 INChannelCookie = (BYTE*)&(inChannel->common.Cookie);
1751 AssociationGroupId = (BYTE*)&(connection->AssociationGroupId);
1752 buffer = Stream_New(
nullptr, header.header.frag_length);
1756 if (!rts_write_pdu_header(buffer, &header))
1758 if (!rts_version_command_write(buffer))
1760 if (!rts_cookie_command_write(buffer,
1761 VirtualConnectionCookie))
1763 if (!rts_cookie_command_write(buffer, INChannelCookie))
1765 if (!rts_channel_lifetime_command_write(buffer,
1766 rpc->ChannelLifetime))
1768 if (!rts_client_keepalive_command_write(buffer,
1769 rpc->KeepAliveInterval))
1771 if (!rts_association_group_id_command_write(
1772 buffer, AssociationGroupId))
1774 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1776 Stream_Free(buffer, TRUE);
1782BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc,
wStream* buffer)
1785 UINT32 ReceiveWindowSize = 0;
1786 UINT32 ConnectionTimeout = 0;
1789 WINPR_ASSERT(buffer);
1792 if (!rts_read_pdu_header(buffer, &header))
1795 if (header.rts.Flags != RTS_FLAG_NONE)
1797 WLog_Print(rpc->log, WLOG_ERROR,
1798 "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected Flags=0x%08" PRIx32
1799 ", expected 0x%08" PRIx32,
1800 header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
1803 if (header.rts.NumberOfCommands != 3)
1805 WLog_Print(rpc->log, WLOG_ERROR,
1806 "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected NumberOfCommands=%" PRIu32
1808 header.rts.NumberOfCommands);
1811 if (!rts_version_command_read(rpc, buffer,
nullptr))
1814 if (!rts_receive_window_size_command_read(rpc, buffer, &ReceiveWindowSize))
1817 if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
1820 WLog_Print(rpc->log, WLOG_DEBUG,
1821 "Receiving CONN/C2 RTS PDU: ConnectionTimeout: %" PRIu32
1822 " ReceiveWindowSize: %" PRIu32
"",
1823 ConnectionTimeout, ReceiveWindowSize);
1826 WINPR_ASSERT(rpc->VirtualConnection);
1827 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1829 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
1830 rpc->VirtualConnection->DefaultInChannel->PeerReceiveWindow = ReceiveWindowSize;
1835 rts_free_pdu_header(&header, FALSE);
1841BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc)
1843 BOOL status = FALSE;
1846 UINT32 BytesReceived = 0;
1847 UINT32 AvailableWindow = 0;
1848 BYTE* ChannelCookie =
nullptr;
1855 connection = rpc->VirtualConnection;
1856 WINPR_ASSERT(connection);
1858 inChannel = connection->DefaultInChannel;
1859 WINPR_ASSERT(inChannel);
1861 outChannel = connection->DefaultOutChannel;
1862 WINPR_ASSERT(outChannel);
1864 header.header.frag_length = 56;
1865 header.Flags = RTS_FLAG_OTHER_CMD;
1866 header.NumberOfCommands = 2;
1868 WLog_DBG(TAG,
"Sending FlowControlAck RTS PDU");
1870 BytesReceived = outChannel->BytesReceived;
1871 AvailableWindow = outChannel->AvailableWindowAdvertised;
1872 ChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1873 outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
1874 buffer = Stream_New(
nullptr, header.header.frag_length);
1879 if (!rts_write_pdu_header(buffer, &header))
1881 if (!rts_destination_command_write(buffer, FDOutProxy))
1885 if (!rts_flow_control_ack_command_write(buffer, BytesReceived, AvailableWindow, ChannelCookie))
1888 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1890 Stream_Free(buffer, TRUE);
1894static int rts_recv_flow_control_ack_pdu(rdpRpc* rpc,
wStream* buffer)
1897 UINT32 BytesReceived = 0;
1898 UINT32 AvailableWindow = 0;
1899 BYTE ChannelCookie[16] = WINPR_C_ARRAY_INIT;
1901 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1902 (BYTE*)&ChannelCookie);
1906 "Receiving FlowControlAck RTS PDU: BytesReceived: %" PRIu32
1907 " AvailableWindow: %" PRIu32
"",
1908 BytesReceived, AvailableWindow);
1910 WINPR_ASSERT(rpc->VirtualConnection);
1911 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1913 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1914 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1918static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc,
wStream* buffer)
1921 UINT32 Destination = 0;
1922 UINT32 BytesReceived = 0;
1923 UINT32 AvailableWindow = 0;
1924 BYTE ChannelCookie[16] = WINPR_C_ARRAY_INIT;
1942 int rc = rts_destination_command_read(rpc, buffer, &Command);
1946 if (Command != RTS_CMD_DESTINATION)
1948 char buffer1[64] = WINPR_C_ARRAY_INIT;
1949 char buffer2[64] = WINPR_C_ARRAY_INIT;
1950 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
1951 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
1952 rts_command_to_string(RTS_CMD_DESTINATION, buffer2,
sizeof(buffer2)));
1956 rc = rts_destination_command_read(rpc, buffer, &Destination);
1960 switch (Destination)
1971 WLog_Print(rpc->log, WLOG_ERROR,
1972 "got destination %" PRIu32
1973 ", expected one of [FDClient[0]|FDInProxy[1]|FDServer[2]|FDOutProxy[3]",
1978 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1984 "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %" PRIu32
1985 " AvailableWindow: %" PRIu32
"",
1986 BytesReceived, AvailableWindow);
1988 WINPR_ASSERT(rpc->VirtualConnection);
1989 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1990 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1991 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1995BOOL rts_recv_ping_pdu(rdpRpc* rpc,
wStream* s)
2001 WINPR_ASSERT(rpc->auth);
2004 if (!rts_read_pdu_header(s, &header))
2008 if (header.common.ptype != PTYPE_RTS)
2010 WLog_Print(rpc->log, WLOG_ERROR,
"received invalid ping PDU, type is 0x%" PRIx32,
2011 header.common.ptype);
2014 if (header.rts.Flags != RTS_FLAG_PING)
2016 WLog_Print(rpc->log, WLOG_ERROR,
"received unexpected ping PDU::Flags 0x%" PRIx32,
2021 rts_free_pdu_header(&header, FALSE);
2025static int rts_send_ping_pdu(rdpRpc* rpc)
2027 BOOL status = FALSE;
2033 WINPR_ASSERT(rpc->VirtualConnection);
2035 inChannel = rpc->VirtualConnection->DefaultInChannel;
2036 WINPR_ASSERT(inChannel);
2038 header.header.frag_length = 20;
2039 header.Flags = RTS_FLAG_PING;
2040 header.NumberOfCommands = 0;
2042 WLog_DBG(TAG,
"Sending Ping RTS PDU");
2043 buffer = Stream_New(
nullptr, header.header.frag_length);
2048 if (!rts_write_pdu_header(buffer, &header))
2050 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2052 Stream_Free(buffer, TRUE);
2053 return (status) ? 1 : -1;
2056BOOL rts_command_length(UINT32 CommandType,
wStream* s,
size_t* length, BOOL silent)
2059 size_t CommandLength = 0;
2063 switch (CommandType)
2065 case RTS_CMD_RECEIVE_WINDOW_SIZE:
2066 CommandLength = RTS_CMD_RECEIVE_WINDOW_SIZE_LENGTH;
2069 case RTS_CMD_FLOW_CONTROL_ACK:
2070 CommandLength = RTS_CMD_FLOW_CONTROL_ACK_LENGTH;
2073 case RTS_CMD_CONNECTION_TIMEOUT:
2074 CommandLength = RTS_CMD_CONNECTION_TIMEOUT_LENGTH;
2077 case RTS_CMD_COOKIE:
2078 CommandLength = RTS_CMD_COOKIE_LENGTH;
2081 case RTS_CMD_CHANNEL_LIFETIME:
2082 CommandLength = RTS_CMD_CHANNEL_LIFETIME_LENGTH;
2085 case RTS_CMD_CLIENT_KEEPALIVE:
2086 CommandLength = RTS_CMD_CLIENT_KEEPALIVE_LENGTH;
2089 case RTS_CMD_VERSION:
2090 CommandLength = RTS_CMD_VERSION_LENGTH;
2094 CommandLength = RTS_CMD_EMPTY_LENGTH;
2097 case RTS_CMD_PADDING:
2098 if (!rts_padding_command_read(s, &padding, silent))
2102 case RTS_CMD_NEGATIVE_ANCE:
2103 CommandLength = RTS_CMD_NEGATIVE_ANCE_LENGTH;
2107 CommandLength = RTS_CMD_ANCE_LENGTH;
2110 case RTS_CMD_CLIENT_ADDRESS:
2111 if (!rts_client_address_command_read(s, &CommandLength, silent))
2115 case RTS_CMD_ASSOCIATION_GROUP_ID:
2116 CommandLength = RTS_CMD_ASSOCIATION_GROUP_ID_LENGTH;
2119 case RTS_CMD_DESTINATION:
2120 CommandLength = RTS_CMD_DESTINATION_LENGTH;
2123 case RTS_CMD_PING_TRAFFIC_SENT_NOTIFY:
2124 CommandLength = RTS_CMD_PING_TRAFFIC_SENT_NOTIFY_LENGTH;
2128 WLog_ERR(TAG,
"Error: Unknown RTS Command Type: 0x%" PRIx32
"", CommandType);
2132 CommandLength += padding;
2133 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, CommandLength, silent))
2137 *length = CommandLength;
2141static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
2143 BOOL status = FALSE;
2146 BYTE* SuccessorChannelCookie =
nullptr;
2151 WINPR_ASSERT(rpc->VirtualConnection);
2153 inChannel = rpc->VirtualConnection->DefaultInChannel;
2154 WINPR_ASSERT(inChannel);
2156 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2157 WINPR_ASSERT(nextOutChannel);
2159 header.header.frag_length = 56;
2160 header.Flags = RTS_FLAG_OUT_CHANNEL;
2161 header.NumberOfCommands = 3;
2163 WLog_DBG(TAG,
"Sending OUT_R2/A7 RTS PDU");
2165 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2166 buffer = Stream_New(
nullptr, header.header.frag_length);
2171 if (!rts_write_pdu_header(buffer, &header))
2173 if (!rts_destination_command_write(buffer, FDServer))
2175 if (!rts_cookie_command_write(buffer,
2176 SuccessorChannelCookie))
2178 if (!rts_version_command_write(buffer))
2180 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2182 Stream_Free(buffer, TRUE);
2183 return (status) ? 1 : -1;
2186static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc)
2188 BOOL status = FALSE;
2194 WINPR_ASSERT(rpc->VirtualConnection);
2196 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2197 WINPR_ASSERT(nextOutChannel);
2199 header.header.frag_length = 24;
2200 header.Flags = RTS_FLAG_PING;
2201 header.NumberOfCommands = 1;
2203 WLog_DBG(TAG,
"Sending OUT_R2/C1 RTS PDU");
2204 buffer = Stream_New(
nullptr, header.header.frag_length);
2209 if (!rts_write_pdu_header(buffer, &header))
2212 if (!rts_empty_command_write(buffer))
2214 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2216 Stream_Free(buffer, TRUE);
2217 return (status) ? 1 : -1;
2220BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
2222 BOOL status = FALSE;
2225 UINT32 ReceiveWindowSize = 0;
2226 BYTE* VirtualConnectionCookie =
nullptr;
2227 BYTE* PredecessorChannelCookie =
nullptr;
2228 BYTE* SuccessorChannelCookie =
nullptr;
2235 connection = rpc->VirtualConnection;
2236 WINPR_ASSERT(connection);
2238 outChannel = connection->DefaultOutChannel;
2239 WINPR_ASSERT(outChannel);
2241 nextOutChannel = connection->NonDefaultOutChannel;
2242 WINPR_ASSERT(nextOutChannel);
2244 header.header.frag_length = 96;
2245 header.Flags = RTS_FLAG_RECYCLE_CHANNEL;
2246 header.NumberOfCommands = 5;
2248 WLog_DBG(TAG,
"Sending OUT_R1/A3 RTS PDU");
2250 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
2251 PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie);
2252 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2253 ReceiveWindowSize = outChannel->ReceiveWindow;
2254 buffer = Stream_New(
nullptr, header.header.frag_length);
2259 if (!rts_write_pdu_header(buffer, &header))
2261 if (!rts_version_command_write(buffer))
2263 if (!rts_cookie_command_write(buffer,
2264 VirtualConnectionCookie))
2266 if (!rts_cookie_command_write(
2267 buffer, PredecessorChannelCookie))
2269 if (!rts_cookie_command_write(buffer,
2270 SuccessorChannelCookie))
2272 if (!rts_receive_window_size_command_write(buffer,
2276 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2278 Stream_Free(buffer, TRUE);
2282static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc,
wStream* buffer)
2285 UINT32 Destination = 0;
2288 WINPR_ASSERT(buffer);
2290 connection = rpc->VirtualConnection;
2291 WINPR_ASSERT(connection);
2293 WLog_DBG(TAG,
"Receiving OUT R1/A2 RTS PDU");
2295 status = rts_destination_command_read(rpc, buffer, &Destination);
2299 connection->NonDefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
2301 if (!connection->NonDefaultOutChannel)
2304 status = rpc_out_channel_replacement_connect(connection->NonDefaultOutChannel, 5000);
2308 WLog_ERR(TAG,
"rpc_out_channel_replacement_connect failure");
2312 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2313 CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
2317static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED
wStream* buffer)
2323 WINPR_ASSERT(buffer);
2325 connection = rpc->VirtualConnection;
2326 WINPR_ASSERT(connection);
2328 WLog_DBG(TAG,
"Receiving OUT R2/A6 RTS PDU");
2329 status = rts_send_OUT_R2_C1_pdu(rpc);
2333 WLog_ERR(TAG,
"rts_send_OUT_R2_C1_pdu failure");
2337 status = rts_send_OUT_R2_A7_pdu(rpc);
2341 WLog_ERR(TAG,
"rts_send_OUT_R2_A7_pdu failure");
2345 rpc_out_channel_transition_to_state(connection->NonDefaultOutChannel,
2346 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2347 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2348 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2352static int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED
wStream* buffer)
2357 WINPR_ASSERT(buffer);
2359 connection = rpc->VirtualConnection;
2360 WINPR_ASSERT(connection);
2362 WLog_DBG(TAG,
"Receiving OUT R2/B3 RTS PDU");
2363 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2364 CLIENT_OUT_CHANNEL_STATE_RECYCLED);
2370 BOOL status = FALSE;
2376 WINPR_ASSERT(buffer);
2377 WINPR_ASSERT(header);
2379 wLog* log = WLog_Get(TAG);
2381 const size_t total = Stream_Length(buffer);
2382 length = header->common.frag_length;
2385 WLog_Print(log, WLOG_ERROR,
"PDU length %" PRIuz
" does not match available data %" PRIuz,
2390 connection = rpc->VirtualConnection;
2394 WLog_Print(log, WLOG_ERROR,
"not connected, aborting");
2398 if (!rts_extract_pdu_signature(&signature, buffer, header))
2401 rts_print_pdu_signature(log, WLOG_TRACE, &signature);
2403 if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE,
sizeof(signature)) == 0)
2405 status = rts_recv_flow_control_ack_pdu(rpc, buffer);
2407 else if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE,
2408 sizeof(signature)) == 0)
2410 status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer);
2412 else if (memcmp(&signature, &RTS_PDU_PING_SIGNATURE,
sizeof(signature)) == 0)
2414 status = rts_send_ping_pdu(rpc);
2418 if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
2420 if (memcmp(&signature, &RTS_PDU_OUT_R1_A2_SIGNATURE,
sizeof(signature)) == 0)
2422 status = rts_recv_OUT_R1_A2_pdu(rpc, buffer);
2425 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_A6W)
2427 if (memcmp(&signature, &RTS_PDU_OUT_R2_A6_SIGNATURE,
sizeof(signature)) == 0)
2429 status = rts_recv_OUT_R2_A6_pdu(rpc, buffer);
2432 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_B3W)
2434 if (memcmp(&signature, &RTS_PDU_OUT_R2_B3_SIGNATURE,
sizeof(signature)) == 0)
2436 status = rts_recv_OUT_R2_B3_pdu(rpc, buffer);
2443 const UINT32 SignatureId = rts_identify_pdu_signature(&signature,
nullptr);
2444 WLog_Print(log, WLOG_ERROR,
"error parsing RTS PDU with signature id: 0x%08" PRIX32
"",
2446 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2449 const size_t rem = Stream_GetRemainingLength(buffer);
2452 WLog_Print(log, WLOG_ERROR,
"%" PRIuz
" bytes or %" PRIuz
" total not parsed, aborting",
2454 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2466 if (!rts_write_common_pdu_header(s, &auth->header))
2469 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT16)))
2472 Stream_Write_UINT16(s, auth->max_xmit_frag);
2473 Stream_Write_UINT16(s, auth->max_recv_frag);
2475 return rts_write_auth_verifier(s, &auth->auth_verifier, &auth->header);
2484 if (!rts_write_common_pdu_header(s, &bind->header))
2487 if (!Stream_EnsureRemainingCapacity(s, 8))
2490 Stream_Write_UINT16(s, bind->max_xmit_frag);
2491 Stream_Write_UINT16(s, bind->max_recv_frag);
2492 Stream_Write_UINT32(s, bind->assoc_group_id);
2494 if (!rts_write_context_list(s, &bind->p_context_elem))
2497 return rts_write_auth_verifier(s, &bind->auth_verifier, &bind->header);
2500BOOL rts_conditional_check_and_log(
const char* tag,
wStream* s,
size_t size, BOOL silent,
2501 const char* fkt,
const char* file,
size_t line)
2505 const size_t rem = Stream_GetRemainingLength(s);
2506 return (rem >= size);
2509 return Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, size, 1,
"%s(%s:%" PRIuz
")", fkt,
2513BOOL rts_conditional_safe_seek(
wStream* s,
size_t size, BOOL silent,
const char* fkt,
2514 const char* file,
size_t line)
2518 const size_t rem = Stream_GetRemainingLength(s);
2522 return Stream_SafeSeekEx(s, size, file, line, fkt);