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,
258 if (header->auth_length > header->frag_length - 8ull)
262 "Invalid header->auth_length(%" PRIu16
") > header->frag_length(%" PRIu16
264 header->frag_length, header->auth_length);
270 if (!Stream_CheckAndLogRequiredLength(TAG, s,
272 return RTS_PDU_INCOMPLETE;
276 const size_t sz2 = Stream_GetRemainingLength(s);
278 return RTS_PDU_INCOMPLETE;
280 return RTS_PDU_VALID;
283static BOOL rts_read_auth_verifier_no_checks(
wStream* s, auth_verifier_co_t* auth,
289 WINPR_ASSERT(header);
291 WINPR_ASSERT(header->frag_length > header->auth_length + 8);
294 *startPos = Stream_GetPosition(s);
298 const size_t expected = header->frag_length - header->auth_length - 8;
300 if (!Stream_SetPosition(s, expected))
302 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 8, silent))
305 Stream_Read_UINT8(s, auth->auth_type);
306 Stream_Read_UINT8(s, auth->auth_level);
307 Stream_Read_UINT8(s, auth->auth_pad_length);
308 Stream_Read_UINT8(s, auth->auth_reserved);
309 Stream_Read_UINT32(s, auth->auth_context_id);
312 if (header->auth_length != 0)
314 const void* ptr = Stream_Pointer(s);
315 if (!Stream_ConditionalSafeSeek(s, header->auth_length, silent))
317 auth->auth_value = (BYTE*)sdup(ptr, header->auth_length);
318 if (auth->auth_value ==
nullptr)
325static BOOL rts_read_auth_verifier(
wStream* s, auth_verifier_co_t* auth,
331 WINPR_ASSERT(header);
333 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
336 const size_t expected = header->frag_length - header->auth_length - 8;
337 WINPR_ASSERT(pos + auth->auth_pad_length == expected);
338 return pos + auth->auth_pad_length == expected;
341static BOOL rts_read_auth_verifier_with_stub(
wStream* s, auth_verifier_co_t* auth,
345 size_t alloc_hint = 0;
346 BYTE** ptr =
nullptr;
348 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
351 switch (header->ptype)
356 alloc_hint = hdr->alloc_hint;
357 ptr = &hdr->stub_data;
363 alloc_hint = hdr->alloc_hint;
364 ptr = &hdr->stub_data;
370 alloc_hint = hdr->alloc_hint;
371 ptr = &hdr->stub_data;
380 const size_t off = header->auth_length + 8 + auth->auth_pad_length + pos;
381 const size_t size = header->frag_length - MIN(header->frag_length, off);
382 const void* src = Stream_Buffer(s) + pos;
384 if (off > header->frag_length)
386 "Unexpected alloc_hint(%" PRIuz
") for PDU %s: size %" PRIuz
387 ", frag_length %" PRIu16
", offset %" PRIuz,
388 alloc_hint, rts_pdu_ptype_to_string(header->ptype), size, header->frag_length,
394 *ptr = (BYTE*)sdup(src, size);
403static void rts_free_auth_verifier(auth_verifier_co_t* auth)
407 free(auth->auth_value);
410static BOOL rts_write_auth_verifier(
wStream* s,
const auth_verifier_co_t* auth,
414 UINT8 auth_pad_length = 0;
418 WINPR_ASSERT(header);
421 pos = Stream_GetPosition(s);
424 auth_pad_length = 4 - (pos % 4);
425 if (!Stream_EnsureRemainingCapacity(s, auth_pad_length))
427 Stream_Zero(s, auth_pad_length);
430#if defined(WITH_VERBOSE_WINPR_ASSERT) && (WITH_VERBOSE_WINPR_ASSERT != 0)
431 WINPR_ASSERT(header->frag_length + 8ull > header->auth_length);
433 size_t apos = Stream_GetPosition(s);
434 size_t expected = header->frag_length - header->auth_length - 8;
436 WINPR_ASSERT(apos == expected);
440 if (!Stream_EnsureRemainingCapacity(s,
sizeof(auth_verifier_co_t)))
443 Stream_Write_UINT8(s, auth->auth_type);
444 Stream_Write_UINT8(s, auth->auth_level);
445 Stream_Write_UINT8(s, auth_pad_length);
446 Stream_Write_UINT8(s, 0);
447 Stream_Write_UINT32(s, auth->auth_context_id);
449 if (!Stream_EnsureRemainingCapacity(s, header->auth_length))
451 Stream_Write(s, auth->auth_value, header->auth_length);
458 WINPR_ASSERT(version);
460 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2 *
sizeof(UINT8), silent))
462 Stream_Read_UINT8(s, version->major);
463 Stream_Read_UINT8(s, version->minor);
471 free(versions->p_protocols);
472 versions->p_protocols =
nullptr;
479 WINPR_ASSERT(versions);
481 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT8), silent))
484 Stream_Read_UINT8(s, versions->n_protocols);
486 if (versions->n_protocols > 0)
488 versions->p_protocols = calloc(versions->n_protocols,
sizeof(
p_rt_version_t));
489 if (!versions->p_protocols)
492 for (BYTE x = 0; x < versions->n_protocols; x++)
495 if (!rts_read_version(s, version, silent))
497 rts_free_supported_versions(versions);
510 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT16), silent))
513 Stream_Read_UINT16(s, port->length);
514 if (port->length == 0)
517 const void* ptr = Stream_ConstPointer(s);
518 if (!Stream_ConditionalSafeSeek(s, port->length, silent))
520 port->port_spec = sdup(ptr, port->length);
521 return port->port_spec !=
nullptr;
524static void rts_free_port_any(
port_any_t* port)
528 free(port->port_spec);
536 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(
p_uuid_t), silent))
539 Stream_Read_UINT32(s, uuid->time_low);
540 Stream_Read_UINT16(s, uuid->time_mid);
541 Stream_Read_UINT16(s, uuid->time_hi_and_version);
542 Stream_Read_UINT8(s, uuid->clock_seq_hi_and_reserved);
543 Stream_Read_UINT8(s, uuid->clock_seq_low);
544 Stream_Read(s, uuid->node, ARRAYSIZE(uuid->node));
553 if (!Stream_EnsureRemainingCapacity(s,
sizeof(
p_uuid_t)))
556 Stream_Write_UINT32(s, uuid->time_low);
557 Stream_Write_UINT16(s, uuid->time_mid);
558 Stream_Write_UINT16(s, uuid->time_hi_and_version);
559 Stream_Write_UINT8(s, uuid->clock_seq_hi_and_reserved);
560 Stream_Write_UINT8(s, uuid->clock_seq_low);
561 Stream_Write(s, uuid->node, ARRAYSIZE(uuid->node));
578 WINPR_ASSERT(syntax_id);
580 if (!rts_read_uuid(s, &syntax_id->if_uuid, silent))
583 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
586 Stream_Read_UINT32(s, syntax_id->if_version);
593 WINPR_ASSERT(syntax_id);
595 if (!rts_write_uuid(s, &syntax_id->if_uuid))
598 if (!Stream_EnsureRemainingCapacity(s, 4))
601 Stream_Write_UINT32(s, syntax_id->if_version);
609 rts_syntax_id_free(ptr->transfer_syntaxes);
613WINPR_ATTR_MALLOC(rts_context_elem_free, 1)
624 WINPR_ASSERT(element);
626 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
629 Stream_Read_UINT16(s, element->p_cont_id);
630 Stream_Read_UINT8(s, element->n_transfer_syn);
631 Stream_Read_UINT8(s, element->reserved);
633 if (!rts_read_syntax_id(s, &element->abstract_syntax, silent))
636 if (element->n_transfer_syn > 0)
638 element->transfer_syntaxes = rts_syntax_id_new(element->n_transfer_syn);
639 if (!element->transfer_syntaxes)
641 for (BYTE x = 0; x < element->n_transfer_syn; x++)
644 if (!rts_read_syntax_id(s, syn, silent))
655 WINPR_ASSERT(element);
657 if (!Stream_EnsureRemainingCapacity(s, 4))
659 Stream_Write_UINT16(s, element->p_cont_id);
660 Stream_Write_UINT8(s, element->n_transfer_syn);
661 Stream_Write_UINT8(s, element->reserved);
662 if (!rts_write_syntax_id(s, &element->abstract_syntax))
665 for (BYTE x = 0; x < element->n_transfer_syn; x++)
668 if (!rts_write_syntax_id(s, syn))
680 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
682 Stream_Read_UINT8(s, list->n_context_elem);
683 Stream_Read_UINT8(s, list->reserved);
684 Stream_Read_UINT16(s, list->reserved2);
686 if (list->n_context_elem > 0)
688 list->p_cont_elem = rts_context_elem_new(list->n_context_elem);
689 if (!list->p_cont_elem)
691 for (BYTE x = 0; x < list->n_context_elem; x++)
694 if (!rts_read_context_elem(s, element, silent))
705 rts_context_elem_free(list->p_cont_elem);
713 if (!Stream_EnsureRemainingCapacity(s, 4))
715 Stream_Write_UINT8(s, list->n_context_elem);
716 Stream_Write_UINT8(s, 0);
717 Stream_Write_UINT16(s, 0);
719 for (BYTE x = 0; x < list->n_context_elem; x++)
722 if (!rts_write_context_elem(s, element))
728static p_result_t* rts_result_new(
size_t count)
733static void rts_result_free(
p_result_t* results)
743 WINPR_ASSERT(result);
745 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2, silent))
748 const UINT16 res = Stream_Get_UINT16(s);
753 case provider_rejection:
757 WLog_ERR(TAG,
"Invalid p_cont_def_result_t %" PRIu16, res);
760 result->result = (p_cont_def_result_t)res;
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)
789 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
791 Stream_Read_UINT8(s, list->n_results);
792 Stream_Read_UINT8(s, list->reserved);
793 Stream_Read_UINT16(s, list->reserved2);
795 if (list->n_results > 0)
797 list->p_results = rts_result_new(list->n_results);
798 if (!list->p_results)
801 for (BYTE x = 0; x < list->n_results; x++)
804 if (!rts_read_result(s, result, silent))
816 for (BYTE x = 0; x < list->n_results; x++)
819 rts_free_result(result);
821 rts_result_free(list->p_results);
829 rts_free_context_list(&ctx->p_context_elem);
830 rts_free_auth_verifier(&ctx->auth_verifier);
838 if (!Stream_ConditionalCheckAndLogRequiredLength(
842 Stream_Read_UINT16(s, ctx->max_xmit_frag);
843 Stream_Read_UINT16(s, ctx->max_recv_frag);
844 Stream_Read_UINT32(s, ctx->assoc_group_id);
846 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
849 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
855static BOOL rts_read_pdu_alter_context_response(
wStream* s,
862 if (!Stream_ConditionalCheckAndLogRequiredLength(
866 Stream_Read_UINT16(s, ctx->max_xmit_frag);
867 Stream_Read_UINT16(s, ctx->max_recv_frag);
868 Stream_Read_UINT32(s, ctx->assoc_group_id);
870 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
873 if (!rts_align_stream(s, 4, silent))
876 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
879 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
890 rts_free_port_any(&ctx->sec_addr);
891 rts_free_result_list(&ctx->p_result_list);
892 rts_free_auth_verifier(&ctx->auth_verifier);
900 if (!Stream_ConditionalCheckAndLogRequiredLength(
903 Stream_Read_UINT16(s, ctx->max_xmit_frag);
904 Stream_Read_UINT16(s, ctx->max_recv_frag);
905 Stream_Read_UINT32(s, ctx->assoc_group_id);
907 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
910 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
920 rts_free_context_list(&ctx->p_context_elem);
921 rts_free_auth_verifier(&ctx->auth_verifier);
929 if (!Stream_CheckAndLogRequiredLength(
932 Stream_Read_UINT16(s, ctx->max_xmit_frag);
933 Stream_Read_UINT16(s, ctx->max_recv_frag);
934 Stream_Read_UINT32(s, ctx->assoc_group_id);
936 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
939 if (!rts_align_stream(s, 4, silent))
942 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
945 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
952 rts_free_port_any(&ctx->sec_addr);
953 rts_free_result_list(&ctx->p_result_list);
954 rts_free_auth_verifier(&ctx->auth_verifier);
962 if (!Stream_ConditionalCheckAndLogRequiredLength(
965 Stream_Read_UINT16(s, ctx->provider_reject_reason);
966 return rts_read_supported_versions(s, &ctx->versions, silent);
974 rts_free_supported_versions(&ctx->versions);
982 if (!Stream_ConditionalCheckAndLogRequiredLength(
985 Stream_Read_UINT16(s, ctx->max_xmit_frag);
986 Stream_Read_UINT16(s, ctx->max_recv_frag);
988 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
995 rts_free_auth_verifier(&ctx->auth_verifier);
1003 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 12, silent))
1005 Stream_Read_UINT32(s, ctx->alloc_hint);
1006 Stream_Read_UINT16(s, ctx->p_cont_id);
1007 Stream_Read_UINT8(s, ctx->cancel_count);
1008 Stream_Read_UINT8(s, ctx->reserved);
1009 Stream_Read_UINT32(s, ctx->status);
1011 WLog_WARN(TAG,
"status=%s", Win32ErrorCode2Tag(ctx->status & 0xFFFF));
1012 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1019 rts_free_auth_verifier(&ctx->auth_verifier);
1027 if (!Stream_ConditionalCheckAndLogRequiredLength(
1030 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1037 rts_free_auth_verifier(&ctx->auth_verifier);
1045 if (!Stream_ConditionalCheckAndLogRequiredLength(
1048 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1055 rts_free_auth_verifier(&ctx->auth_verifier);
1063 if (!Stream_ConditionalCheckAndLogRequiredLength(
1066 Stream_Read_UINT32(s, ctx->alloc_hint);
1067 Stream_Read_UINT16(s, ctx->p_cont_id);
1068 Stream_Read_UINT16(s, ctx->opnum);
1069 if (!rts_read_uuid(s, &ctx->object, silent))
1072 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1079 rts_free_auth_verifier(&ctx->auth_verifier);
1087 if (!Stream_ConditionalCheckAndLogRequiredLength(
1090 Stream_Read_UINT32(s, ctx->alloc_hint);
1091 Stream_Read_UINT16(s, ctx->p_cont_id);
1092 Stream_Read_UINT8(s, ctx->cancel_count);
1093 Stream_Read_UINT8(s, ctx->reserved);
1095 if (!rts_align_stream(s, 8, silent))
1098 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1105 free(ctx->stub_data);
1106 rts_free_auth_verifier(&ctx->auth_verifier);
1114 if (!Stream_ConditionalCheckAndLogRequiredLength(
1118 Stream_Read_UINT16(s, ctx->Flags);
1119 Stream_Read_UINT16(s, ctx->NumberOfCommands);
1128void rts_free_pdu_header(
rpcconn_hdr_t* header, BOOL allocated)
1133 switch (header->common.ptype)
1135 case PTYPE_ALTER_CONTEXT:
1136 rts_free_pdu_alter_context(&header->alter_context);
1138 case PTYPE_ALTER_CONTEXT_RESP:
1139 rts_free_pdu_alter_context_response(&header->alter_context_response);
1142 rts_free_pdu_bind(&header->bind);
1144 case PTYPE_BIND_ACK:
1145 rts_free_pdu_bind_ack(&header->bind_ack);
1147 case PTYPE_BIND_NAK:
1148 rts_free_pdu_bind_nak(&header->bind_nak);
1150 case PTYPE_RPC_AUTH_3:
1151 rts_free_pdu_auth3(&header->rpc_auth_3);
1153 case PTYPE_CANCEL_ACK:
1154 rts_free_pdu_cancel_ack(&header->cancel);
1157 rts_free_pdu_fault(&header->fault);
1159 case PTYPE_ORPHANED:
1160 rts_free_pdu_orphaned(&header->orphaned);
1163 rts_free_pdu_request(&header->request);
1165 case PTYPE_RESPONSE:
1166 rts_free_pdu_response(&header->response);
1169 rts_free_pdu_rts(&header->rts);
1172 case PTYPE_SHUTDOWN:
1181 case PTYPE_CL_CANCEL:
1183 case PTYPE_CO_CANCEL:
1194 return rts_read_pdu_header_ex(s, header, FALSE);
1201 WINPR_ASSERT(header);
1203 const rts_pdu_status_t status = rts_read_common_pdu_header(s, &header->common, silent);
1204 if (status != RTS_PDU_VALID)
1207 WLog_DBG(TAG,
"Reading PDU type %s", rts_pdu_ptype_to_string(header->common.ptype));
1209 switch (header->common.ptype)
1211 case PTYPE_ALTER_CONTEXT:
1212 rc = rts_read_pdu_alter_context(s, &header->alter_context, silent);
1214 case PTYPE_ALTER_CONTEXT_RESP:
1215 rc = rts_read_pdu_alter_context_response(s, &header->alter_context_response, silent);
1218 rc = rts_read_pdu_bind(s, &header->bind, silent);
1220 case PTYPE_BIND_ACK:
1221 rc = rts_read_pdu_bind_ack(s, &header->bind_ack, silent);
1223 case PTYPE_BIND_NAK:
1224 rc = rts_read_pdu_bind_nak(s, &header->bind_nak, silent);
1226 case PTYPE_RPC_AUTH_3:
1227 rc = rts_read_pdu_auth3(s, &header->rpc_auth_3, silent);
1229 case PTYPE_CANCEL_ACK:
1230 rc = rts_read_pdu_cancel_ack(s, &header->cancel, silent);
1233 rc = rts_read_pdu_fault(s, &header->fault, silent);
1235 case PTYPE_ORPHANED:
1236 rc = rts_read_pdu_orphaned(s, &header->orphaned, silent);
1239 rc = rts_read_pdu_request(s, &header->request, silent);
1241 case PTYPE_RESPONSE:
1242 rc = rts_read_pdu_response(s, &header->response, silent);
1245 rc = rts_read_pdu_rts(s, &header->rts, silent);
1247 case PTYPE_SHUTDOWN:
1257 case PTYPE_CL_CANCEL:
1259 case PTYPE_CO_CANCEL:
1270 WINPR_ASSERT(header);
1274 if (!rts_write_common_pdu_header(s, &header->header))
1277 Stream_Write_UINT16(s, header->Flags);
1278 Stream_Write_UINT16(s, header->NumberOfCommands);
1283static BOOL rts_receive_window_size_command_read(rdpRpc* rpc,
wStream* buffer,
1284 UINT32* ReceiveWindowSize)
1287 WINPR_ASSERT(buffer);
1289 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1291 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1292 if (CommandType != RTS_CMD_RECEIVE_WINDOW_SIZE)
1294 WLog_Print(rpc->log, WLOG_ERROR,
1295 "[MS-RPCH] 2.2.3.5.1 ReceiveWindowSize::CommandType must be 0x%08" PRIx32
1298 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_RECEIVE_WINDOW_SIZE), CommandType);
1301 const UINT32 val = Stream_Get_UINT32(buffer);
1302 if (ReceiveWindowSize)
1303 *ReceiveWindowSize = val;
1309static BOOL rts_receive_window_size_command_write(
wStream* s, UINT32 ReceiveWindowSize)
1313 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT32)))
1316 Stream_Write_UINT32(s, RTS_CMD_RECEIVE_WINDOW_SIZE);
1317 Stream_Write_UINT32(s, ReceiveWindowSize);
1323static int rts_flow_control_ack_command_read(rdpRpc* rpc,
wStream* buffer, UINT32* BytesReceived,
1324 UINT32* AvailableWindow, BYTE* ChannelCookie)
1330 WINPR_ASSERT(buffer);
1332 int rc = rts_destination_command_read(rpc, buffer, &Command);
1336 if (Command != RTS_CMD_FLOW_CONTROL_ACK)
1338 char buffer1[64] = WINPR_C_ARRAY_INIT;
1339 char buffer2[64] = WINPR_C_ARRAY_INIT;
1340 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
1341 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
1342 rts_command_to_string(RTS_CMD_FLOW_CONTROL_ACK, buffer2,
sizeof(buffer2)));
1347 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 24))
1350 Stream_Read_UINT32(buffer, val);
1352 *BytesReceived = val;
1354 Stream_Read_UINT32(buffer, val);
1355 if (AvailableWindow)
1356 *AvailableWindow = val;
1359 Stream_Read(buffer, ChannelCookie, 16);
1361 Stream_Seek(buffer, 16);
1366static BOOL rts_flow_control_ack_command_write(
wStream* s, UINT32 BytesReceived,
1367 UINT32 AvailableWindow, BYTE* ChannelCookie)
1371 if (!Stream_EnsureRemainingCapacity(s, 28))
1374 Stream_Write_UINT32(s, RTS_CMD_FLOW_CONTROL_ACK);
1375 Stream_Write_UINT32(s, BytesReceived);
1376 Stream_Write_UINT32(s, AvailableWindow);
1377 Stream_Write(s, ChannelCookie, 16);
1383static BOOL rts_connection_timeout_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc,
wStream* buffer,
1384 UINT32* ConnectionTimeout)
1387 WINPR_ASSERT(buffer);
1389 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1392 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1393 if (CommandType != RTS_CMD_CONNECTION_TIMEOUT)
1395 WLog_Print(rpc->log, WLOG_ERROR,
1396 "[MS-RPCH] 2.2.3.5.3 ConnectionTimeout::CommandType must be 0x%08" PRIx32
1399 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_CONNECTION_TIMEOUT), CommandType);
1402 const UINT32 val = Stream_Get_UINT32(buffer);
1403 if (ConnectionTimeout)
1404 *ConnectionTimeout = val;
1409static BOOL rts_cookie_command_write(
wStream* s,
const BYTE* Cookie)
1413 if (!Stream_EnsureRemainingCapacity(s, 20))
1416 Stream_Write_UINT32(s, RTS_CMD_COOKIE);
1417 Stream_Write(s, Cookie, 16);
1422static BOOL rts_channel_lifetime_command_write(
wStream* s, UINT32 ChannelLifetime)
1426 if (!Stream_EnsureRemainingCapacity(s, 8))
1428 Stream_Write_UINT32(s, RTS_CMD_CHANNEL_LIFETIME);
1429 Stream_Write_UINT32(s, ChannelLifetime);
1434static BOOL rts_client_keepalive_command_write(
wStream* s, UINT32 ClientKeepalive)
1438 if (!Stream_EnsureRemainingCapacity(s, 8))
1446 Stream_Write_UINT32(s, RTS_CMD_CLIENT_KEEPALIVE);
1447 Stream_Write_UINT32(s, ClientKeepalive);
1453static BOOL rts_version_command_read(rdpRpc* rpc,
wStream* buffer, uint32_t* pversion)
1456 WINPR_ASSERT(buffer);
1458 if (!Stream_EnsureRemainingCapacity(buffer, 8))
1461 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1462 if (CommandType != RTS_CMD_VERSION)
1464 WLog_Print(rpc->log, WLOG_ERROR,
1465 "[MS-RPCH] 2.2.3.5.7 Version::CommandType must be 0x%08" PRIx32
", got "
1467 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_VERSION), CommandType);
1470 const uint32_t version = Stream_Get_UINT32(buffer);
1473 WLog_Print(rpc->log, WLOG_WARN,
1474 "[MS-RPCH] 2.2.3.5.7 Version::Version should be 0x00000001, got 0x%08" PRIx32,
1478 *pversion = version;
1484static BOOL rts_version_command_write(
wStream* buffer)
1486 WINPR_ASSERT(buffer);
1488 if (!Stream_EnsureRemainingCapacity((buffer), 8))
1491 Stream_Write_UINT32(buffer, RTS_CMD_VERSION);
1492 Stream_Write_UINT32(buffer, 1);
1497static BOOL rts_empty_command_write(
wStream* s)
1501 if (!Stream_EnsureRemainingCapacity(s, 8))
1504 Stream_Write_UINT32(s, RTS_CMD_EMPTY);
1509static BOOL rts_padding_command_read(
wStream* s,
size_t* length, BOOL silent)
1511 UINT32 ConformanceCount = 0;
1513 WINPR_ASSERT(length);
1514 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1516 Stream_Read_UINT32(s, ConformanceCount);
1517 *length = ConformanceCount + 4;
1521static BOOL rts_client_address_command_read(
wStream* s,
size_t* length, BOOL silent)
1523 UINT32 AddressType = 0;
1526 WINPR_ASSERT(length);
1528 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1530 Stream_Read_UINT32(s, AddressType);
1532 if (AddressType == 0)
1536 *length = 4 + 4 + 12;
1542 *length = 4 + 16 + 12;
1547static BOOL rts_association_group_id_command_write(
wStream* s,
const BYTE* AssociationGroupId)
1551 if (!Stream_EnsureRemainingCapacity(s, 20))
1554 Stream_Write_UINT32(s, RTS_CMD_ASSOCIATION_GROUP_ID);
1555 Stream_Write(s, AssociationGroupId, 16);
1560static int rts_destination_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc,
wStream* buffer,
1561 UINT32* Destination)
1565 WINPR_ASSERT(buffer);
1567 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 4))
1569 Stream_Read_UINT32(buffer, val);
1576static BOOL rts_destination_command_write(
wStream* s, UINT32 Destination)
1580 if (!Stream_EnsureRemainingCapacity(s, 8))
1583 Stream_Write_UINT32(s, RTS_CMD_DESTINATION);
1584 Stream_Write_UINT32(s, Destination);
1589BOOL rts_generate_cookie(BYTE* cookie)
1591 WINPR_ASSERT(cookie);
1592 return winpr_RAND(cookie, 16) >= 0;
1595#define rts_send_buffer(channel, s, frag_length) \
1596 rts_send_buffer_int((channel), (s), (frag_length), __FILE__, __LINE__, __func__)
1597static BOOL rts_send_buffer_int(
RpcChannel* channel,
wStream* s,
size_t frag_length,
1598 const char* file,
size_t line,
const char* fkt)
1600 BOOL status = FALSE;
1603 WINPR_ASSERT(channel);
1604 WINPR_ASSERT(channel->rpc);
1607 Stream_SealLength(s);
1609 const DWORD level = WLOG_TRACE;
1610 if (WLog_IsLevelActive(channel->rpc->log, level))
1612 WLog_PrintTextMessage(channel->rpc->log, level, line, file, fkt,
1613 "Sending [%s] %" PRIuz
" bytes", fkt, Stream_Length(s));
1617 if (Stream_Length(s) != frag_length)
1620 rc = rpc_channel_write(channel, Stream_Buffer(s), Stream_Length(s));
1623 if ((
size_t)rc != Stream_Length(s))
1632BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc)
1634 BOOL status = FALSE;
1637 UINT32 ReceiveWindowSize = 0;
1638 BYTE* OUTChannelCookie =
nullptr;
1639 BYTE* VirtualConnectionCookie =
nullptr;
1645 connection = rpc->VirtualConnection;
1646 WINPR_ASSERT(connection);
1648 outChannel = connection->DefaultOutChannel;
1649 WINPR_ASSERT(outChannel);
1651 header.header.frag_length = 76;
1652 header.Flags = RTS_FLAG_NONE;
1653 header.NumberOfCommands = 4;
1655 WLog_DBG(TAG,
"Sending CONN/A1 RTS PDU");
1656 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1657 OUTChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1658 ReceiveWindowSize = outChannel->ReceiveWindow;
1660 buffer = Stream_New(
nullptr, header.header.frag_length);
1665 if (!rts_write_pdu_header(buffer, &header))
1667 status = rts_version_command_write(buffer);
1670 status = rts_cookie_command_write(
1671 buffer, VirtualConnectionCookie);
1674 status = rts_cookie_command_write(buffer, OUTChannelCookie);
1677 status = rts_receive_window_size_command_write(
1678 buffer, ReceiveWindowSize);
1681 status = rts_send_buffer(&outChannel->common, buffer, header.header.frag_length);
1683 Stream_Free(buffer, TRUE);
1687BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc,
wStream* buffer)
1690 UINT32 ConnectionTimeout = 0;
1693 if (!rts_read_pdu_header(buffer, &header))
1696 if (header.rts.Flags != RTS_FLAG_NONE)
1698 WLog_Print(rpc->log, WLOG_ERROR,
1699 "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected Flags=0x%08" PRIx32
1700 ", expected 0x%08" PRIx32,
1701 header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
1704 if (header.rts.NumberOfCommands != 1)
1706 WLog_Print(rpc->log, WLOG_ERROR,
1707 "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected NumberOfCommands=%" PRIu32
1709 header.rts.NumberOfCommands);
1713 if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
1716 WLog_Print(rpc->log, WLOG_DEBUG,
"Receiving CONN/A3 RTS PDU: ConnectionTimeout: %" PRIu32
"",
1720 WINPR_ASSERT(rpc->VirtualConnection);
1721 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1723 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
1728 rts_free_pdu_header(&header, FALSE);
1734BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc)
1736 BOOL status = FALSE;
1739 BYTE* INChannelCookie =
nullptr;
1740 BYTE* AssociationGroupId =
nullptr;
1741 BYTE* VirtualConnectionCookie =
nullptr;
1747 connection = rpc->VirtualConnection;
1748 WINPR_ASSERT(connection);
1750 inChannel = connection->DefaultInChannel;
1751 WINPR_ASSERT(inChannel);
1753 header.header.frag_length = 104;
1754 header.Flags = RTS_FLAG_NONE;
1755 header.NumberOfCommands = 6;
1757 WLog_DBG(TAG,
"Sending CONN/B1 RTS PDU");
1759 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1760 INChannelCookie = (BYTE*)&(inChannel->common.Cookie);
1761 AssociationGroupId = (BYTE*)&(connection->AssociationGroupId);
1762 buffer = Stream_New(
nullptr, header.header.frag_length);
1766 if (!rts_write_pdu_header(buffer, &header))
1768 if (!rts_version_command_write(buffer))
1770 if (!rts_cookie_command_write(buffer,
1771 VirtualConnectionCookie))
1773 if (!rts_cookie_command_write(buffer, INChannelCookie))
1775 if (!rts_channel_lifetime_command_write(buffer,
1776 rpc->ChannelLifetime))
1778 if (!rts_client_keepalive_command_write(buffer,
1779 rpc->KeepAliveInterval))
1781 if (!rts_association_group_id_command_write(
1782 buffer, AssociationGroupId))
1784 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1786 Stream_Free(buffer, TRUE);
1792BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc,
wStream* buffer)
1795 UINT32 ReceiveWindowSize = 0;
1796 UINT32 ConnectionTimeout = 0;
1799 WINPR_ASSERT(buffer);
1802 if (!rts_read_pdu_header(buffer, &header))
1805 if (header.rts.Flags != RTS_FLAG_NONE)
1807 WLog_Print(rpc->log, WLOG_ERROR,
1808 "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected Flags=0x%08" PRIx32
1809 ", expected 0x%08" PRIx32,
1810 header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
1813 if (header.rts.NumberOfCommands != 3)
1815 WLog_Print(rpc->log, WLOG_ERROR,
1816 "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected NumberOfCommands=%" PRIu32
1818 header.rts.NumberOfCommands);
1821 if (!rts_version_command_read(rpc, buffer,
nullptr))
1824 if (!rts_receive_window_size_command_read(rpc, buffer, &ReceiveWindowSize))
1827 if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
1830 WLog_Print(rpc->log, WLOG_DEBUG,
1831 "Receiving CONN/C2 RTS PDU: ConnectionTimeout: %" PRIu32
1832 " ReceiveWindowSize: %" PRIu32
"",
1833 ConnectionTimeout, ReceiveWindowSize);
1836 WINPR_ASSERT(rpc->VirtualConnection);
1837 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1839 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
1840 rpc->VirtualConnection->DefaultInChannel->PeerReceiveWindow = ReceiveWindowSize;
1845 rts_free_pdu_header(&header, FALSE);
1851BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc)
1853 BOOL status = FALSE;
1856 UINT32 BytesReceived = 0;
1857 UINT32 AvailableWindow = 0;
1858 BYTE* ChannelCookie =
nullptr;
1865 connection = rpc->VirtualConnection;
1866 WINPR_ASSERT(connection);
1868 inChannel = connection->DefaultInChannel;
1869 WINPR_ASSERT(inChannel);
1871 outChannel = connection->DefaultOutChannel;
1872 WINPR_ASSERT(outChannel);
1874 header.header.frag_length = 56;
1875 header.Flags = RTS_FLAG_OTHER_CMD;
1876 header.NumberOfCommands = 2;
1878 WLog_DBG(TAG,
"Sending FlowControlAck RTS PDU");
1880 BytesReceived = outChannel->BytesReceived;
1881 AvailableWindow = outChannel->AvailableWindowAdvertised;
1882 ChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1883 outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
1884 buffer = Stream_New(
nullptr, header.header.frag_length);
1889 if (!rts_write_pdu_header(buffer, &header))
1891 if (!rts_destination_command_write(buffer, FDOutProxy))
1895 if (!rts_flow_control_ack_command_write(buffer, BytesReceived, AvailableWindow, ChannelCookie))
1898 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1900 Stream_Free(buffer, TRUE);
1904static int rts_recv_flow_control_ack_pdu(rdpRpc* rpc,
wStream* buffer)
1907 UINT32 BytesReceived = 0;
1908 UINT32 AvailableWindow = 0;
1909 BYTE ChannelCookie[16] = WINPR_C_ARRAY_INIT;
1911 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1912 (BYTE*)&ChannelCookie);
1916 "Receiving FlowControlAck RTS PDU: BytesReceived: %" PRIu32
1917 " AvailableWindow: %" PRIu32
"",
1918 BytesReceived, AvailableWindow);
1920 WINPR_ASSERT(rpc->VirtualConnection);
1921 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1923 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1924 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1928static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc,
wStream* buffer)
1931 UINT32 Destination = 0;
1932 UINT32 BytesReceived = 0;
1933 UINT32 AvailableWindow = 0;
1934 BYTE ChannelCookie[16] = WINPR_C_ARRAY_INIT;
1952 int rc = rts_destination_command_read(rpc, buffer, &Command);
1956 if (Command != RTS_CMD_DESTINATION)
1958 char buffer1[64] = WINPR_C_ARRAY_INIT;
1959 char buffer2[64] = WINPR_C_ARRAY_INIT;
1960 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
1961 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
1962 rts_command_to_string(RTS_CMD_DESTINATION, buffer2,
sizeof(buffer2)));
1966 rc = rts_destination_command_read(rpc, buffer, &Destination);
1970 switch (Destination)
1981 WLog_Print(rpc->log, WLOG_ERROR,
1982 "got destination %" PRIu32
1983 ", expected one of [FDClient[0]|FDInProxy[1]|FDServer[2]|FDOutProxy[3]",
1988 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1994 "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %" PRIu32
1995 " AvailableWindow: %" PRIu32
"",
1996 BytesReceived, AvailableWindow);
1998 WINPR_ASSERT(rpc->VirtualConnection);
1999 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
2000 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
2001 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
2005BOOL rts_recv_ping_pdu(rdpRpc* rpc,
wStream* s)
2011 WINPR_ASSERT(rpc->auth);
2014 if (!rts_read_pdu_header(s, &header))
2018 if (header.common.ptype != PTYPE_RTS)
2020 WLog_Print(rpc->log, WLOG_ERROR,
"received invalid ping PDU, type is 0x%" PRIx32,
2021 header.common.ptype);
2024 if (header.rts.Flags != RTS_FLAG_PING)
2026 WLog_Print(rpc->log, WLOG_ERROR,
"received unexpected ping PDU::Flags 0x%" PRIx32,
2031 rts_free_pdu_header(&header, FALSE);
2035static int rts_send_ping_pdu(rdpRpc* rpc)
2037 BOOL status = FALSE;
2043 WINPR_ASSERT(rpc->VirtualConnection);
2045 inChannel = rpc->VirtualConnection->DefaultInChannel;
2046 WINPR_ASSERT(inChannel);
2048 header.header.frag_length = 20;
2049 header.Flags = RTS_FLAG_PING;
2050 header.NumberOfCommands = 0;
2052 WLog_DBG(TAG,
"Sending Ping RTS PDU");
2053 buffer = Stream_New(
nullptr, header.header.frag_length);
2058 if (!rts_write_pdu_header(buffer, &header))
2060 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2062 Stream_Free(buffer, TRUE);
2063 return (status) ? 1 : -1;
2066BOOL rts_command_length(UINT32 CommandType,
wStream* s,
size_t* length, BOOL silent)
2069 size_t CommandLength = 0;
2073 switch (CommandType)
2075 case RTS_CMD_RECEIVE_WINDOW_SIZE:
2076 CommandLength = RTS_CMD_RECEIVE_WINDOW_SIZE_LENGTH;
2079 case RTS_CMD_FLOW_CONTROL_ACK:
2080 CommandLength = RTS_CMD_FLOW_CONTROL_ACK_LENGTH;
2083 case RTS_CMD_CONNECTION_TIMEOUT:
2084 CommandLength = RTS_CMD_CONNECTION_TIMEOUT_LENGTH;
2087 case RTS_CMD_COOKIE:
2088 CommandLength = RTS_CMD_COOKIE_LENGTH;
2091 case RTS_CMD_CHANNEL_LIFETIME:
2092 CommandLength = RTS_CMD_CHANNEL_LIFETIME_LENGTH;
2095 case RTS_CMD_CLIENT_KEEPALIVE:
2096 CommandLength = RTS_CMD_CLIENT_KEEPALIVE_LENGTH;
2099 case RTS_CMD_VERSION:
2100 CommandLength = RTS_CMD_VERSION_LENGTH;
2104 CommandLength = RTS_CMD_EMPTY_LENGTH;
2107 case RTS_CMD_PADDING:
2108 if (!rts_padding_command_read(s, &padding, silent))
2112 case RTS_CMD_NEGATIVE_ANCE:
2113 CommandLength = RTS_CMD_NEGATIVE_ANCE_LENGTH;
2117 CommandLength = RTS_CMD_ANCE_LENGTH;
2120 case RTS_CMD_CLIENT_ADDRESS:
2121 if (!rts_client_address_command_read(s, &CommandLength, silent))
2125 case RTS_CMD_ASSOCIATION_GROUP_ID:
2126 CommandLength = RTS_CMD_ASSOCIATION_GROUP_ID_LENGTH;
2129 case RTS_CMD_DESTINATION:
2130 CommandLength = RTS_CMD_DESTINATION_LENGTH;
2133 case RTS_CMD_PING_TRAFFIC_SENT_NOTIFY:
2134 CommandLength = RTS_CMD_PING_TRAFFIC_SENT_NOTIFY_LENGTH;
2138 WLog_ERR(TAG,
"Error: Unknown RTS Command Type: 0x%" PRIx32
"", CommandType);
2142 CommandLength += padding;
2143 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, CommandLength, silent))
2147 *length = CommandLength;
2151static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
2153 BOOL status = FALSE;
2156 BYTE* SuccessorChannelCookie =
nullptr;
2161 WINPR_ASSERT(rpc->VirtualConnection);
2163 inChannel = rpc->VirtualConnection->DefaultInChannel;
2164 WINPR_ASSERT(inChannel);
2166 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2167 WINPR_ASSERT(nextOutChannel);
2169 header.header.frag_length = 56;
2170 header.Flags = RTS_FLAG_OUT_CHANNEL;
2171 header.NumberOfCommands = 3;
2173 WLog_DBG(TAG,
"Sending OUT_R2/A7 RTS PDU");
2175 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2176 buffer = Stream_New(
nullptr, header.header.frag_length);
2181 if (!rts_write_pdu_header(buffer, &header))
2183 if (!rts_destination_command_write(buffer, FDServer))
2185 if (!rts_cookie_command_write(buffer,
2186 SuccessorChannelCookie))
2188 if (!rts_version_command_write(buffer))
2190 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2192 Stream_Free(buffer, TRUE);
2193 return (status) ? 1 : -1;
2196static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc)
2198 BOOL status = FALSE;
2204 WINPR_ASSERT(rpc->VirtualConnection);
2206 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2207 WINPR_ASSERT(nextOutChannel);
2209 header.header.frag_length = 24;
2210 header.Flags = RTS_FLAG_PING;
2211 header.NumberOfCommands = 1;
2213 WLog_DBG(TAG,
"Sending OUT_R2/C1 RTS PDU");
2214 buffer = Stream_New(
nullptr, header.header.frag_length);
2219 if (!rts_write_pdu_header(buffer, &header))
2222 if (!rts_empty_command_write(buffer))
2224 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2226 Stream_Free(buffer, TRUE);
2227 return (status) ? 1 : -1;
2230BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
2232 BOOL status = FALSE;
2235 UINT32 ReceiveWindowSize = 0;
2236 BYTE* VirtualConnectionCookie =
nullptr;
2237 BYTE* PredecessorChannelCookie =
nullptr;
2238 BYTE* SuccessorChannelCookie =
nullptr;
2245 connection = rpc->VirtualConnection;
2246 WINPR_ASSERT(connection);
2248 outChannel = connection->DefaultOutChannel;
2249 WINPR_ASSERT(outChannel);
2251 nextOutChannel = connection->NonDefaultOutChannel;
2252 WINPR_ASSERT(nextOutChannel);
2254 header.header.frag_length = 96;
2255 header.Flags = RTS_FLAG_RECYCLE_CHANNEL;
2256 header.NumberOfCommands = 5;
2258 WLog_DBG(TAG,
"Sending OUT_R1/A3 RTS PDU");
2260 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
2261 PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie);
2262 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2263 ReceiveWindowSize = outChannel->ReceiveWindow;
2264 buffer = Stream_New(
nullptr, header.header.frag_length);
2269 if (!rts_write_pdu_header(buffer, &header))
2271 if (!rts_version_command_write(buffer))
2273 if (!rts_cookie_command_write(buffer,
2274 VirtualConnectionCookie))
2276 if (!rts_cookie_command_write(
2277 buffer, PredecessorChannelCookie))
2279 if (!rts_cookie_command_write(buffer,
2280 SuccessorChannelCookie))
2282 if (!rts_receive_window_size_command_write(buffer,
2286 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2288 Stream_Free(buffer, TRUE);
2292static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc,
wStream* buffer)
2295 UINT32 Destination = 0;
2298 WINPR_ASSERT(buffer);
2300 connection = rpc->VirtualConnection;
2301 WINPR_ASSERT(connection);
2303 WLog_DBG(TAG,
"Receiving OUT R1/A2 RTS PDU");
2305 status = rts_destination_command_read(rpc, buffer, &Destination);
2309 connection->NonDefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
2311 if (!connection->NonDefaultOutChannel)
2314 status = rpc_out_channel_replacement_connect(connection->NonDefaultOutChannel, 5000);
2318 WLog_ERR(TAG,
"rpc_out_channel_replacement_connect failure");
2322 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2323 CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
2327static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED
wStream* buffer)
2333 WINPR_ASSERT(buffer);
2335 connection = rpc->VirtualConnection;
2336 WINPR_ASSERT(connection);
2338 WLog_DBG(TAG,
"Receiving OUT R2/A6 RTS PDU");
2339 status = rts_send_OUT_R2_C1_pdu(rpc);
2343 WLog_ERR(TAG,
"rts_send_OUT_R2_C1_pdu failure");
2347 status = rts_send_OUT_R2_A7_pdu(rpc);
2351 WLog_ERR(TAG,
"rts_send_OUT_R2_A7_pdu failure");
2355 rpc_out_channel_transition_to_state(connection->NonDefaultOutChannel,
2356 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2357 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2358 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2362static int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED
wStream* buffer)
2367 WINPR_ASSERT(buffer);
2369 connection = rpc->VirtualConnection;
2370 WINPR_ASSERT(connection);
2372 WLog_DBG(TAG,
"Receiving OUT R2/B3 RTS PDU");
2373 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2374 CLIENT_OUT_CHANNEL_STATE_RECYCLED);
2380 BOOL status = FALSE;
2386 WINPR_ASSERT(buffer);
2387 WINPR_ASSERT(header);
2389 wLog* log = WLog_Get(TAG);
2391 const size_t total = Stream_Length(buffer);
2392 length = header->common.frag_length;
2395 WLog_Print(log, WLOG_ERROR,
"PDU length %" PRIuz
" does not match available data %" PRIuz,
2400 connection = rpc->VirtualConnection;
2404 WLog_Print(log, WLOG_ERROR,
"not connected, aborting");
2408 if (!rts_extract_pdu_signature(&signature, buffer, header))
2411 rts_print_pdu_signature(log, WLOG_TRACE, &signature);
2413 if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE,
sizeof(signature)) == 0)
2415 status = rts_recv_flow_control_ack_pdu(rpc, buffer);
2417 else if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE,
2418 sizeof(signature)) == 0)
2420 status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer);
2422 else if (memcmp(&signature, &RTS_PDU_PING_SIGNATURE,
sizeof(signature)) == 0)
2424 status = rts_send_ping_pdu(rpc);
2428 if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
2430 if (memcmp(&signature, &RTS_PDU_OUT_R1_A2_SIGNATURE,
sizeof(signature)) == 0)
2432 status = rts_recv_OUT_R1_A2_pdu(rpc, buffer);
2435 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_A6W)
2437 if (memcmp(&signature, &RTS_PDU_OUT_R2_A6_SIGNATURE,
sizeof(signature)) == 0)
2439 status = rts_recv_OUT_R2_A6_pdu(rpc, buffer);
2442 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_B3W)
2444 if (memcmp(&signature, &RTS_PDU_OUT_R2_B3_SIGNATURE,
sizeof(signature)) == 0)
2446 status = rts_recv_OUT_R2_B3_pdu(rpc, buffer);
2453 const UINT32 SignatureId = rts_identify_pdu_signature(&signature,
nullptr);
2454 WLog_Print(log, WLOG_ERROR,
"error parsing RTS PDU with signature id: 0x%08" PRIX32
"",
2456 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2459 const size_t rem = Stream_GetRemainingLength(buffer);
2462 WLog_Print(log, WLOG_ERROR,
"%" PRIuz
" bytes or %" PRIuz
" total not parsed, aborting",
2464 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2476 if (!rts_write_common_pdu_header(s, &auth->header))
2479 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT16)))
2482 Stream_Write_UINT16(s, auth->max_xmit_frag);
2483 Stream_Write_UINT16(s, auth->max_recv_frag);
2485 return rts_write_auth_verifier(s, &auth->auth_verifier, &auth->header);
2494 if (!rts_write_common_pdu_header(s, &bind->header))
2497 if (!Stream_EnsureRemainingCapacity(s, 8))
2500 Stream_Write_UINT16(s, bind->max_xmit_frag);
2501 Stream_Write_UINT16(s, bind->max_recv_frag);
2502 Stream_Write_UINT32(s, bind->assoc_group_id);
2504 if (!rts_write_context_list(s, &bind->p_context_elem))
2507 return rts_write_auth_verifier(s, &bind->auth_verifier, &bind->header);
2510BOOL rts_conditional_check_and_log(
const char* tag,
wStream* s,
size_t size, BOOL silent,
2511 const char* fkt,
const char* file,
size_t line)
2515 const size_t rem = Stream_GetRemainingLength(s);
2516 return (rem >= size);
2519 return Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, size, 1,
"%s(%s:%" PRIuz
")", fkt,
2523BOOL rts_conditional_safe_seek(
wStream* s,
size_t size, BOOL silent,
const char* fkt,
2524 const char* file,
size_t line)
2528 const size_t rem = Stream_GetRemainingLength(s);
2532 return Stream_SafeSeekEx(s, size, file, line, fkt);