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 = NULL;
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);
227 WINPR_ASSERT(header);
236 const size_t sz = Stream_GetRemainingLength(s);
241 Stream_Read_UINT8(s, header->rpc_vers);
242 Stream_Read_UINT8(s, header->rpc_vers_minor);
243 Stream_Read_UINT8(s, header->ptype);
244 Stream_Read_UINT8(s, header->pfc_flags);
245 Stream_Read(s, header->packed_drep, ARRAYSIZE(header->packed_drep));
246 Stream_Read_UINT16(s, header->frag_length);
247 Stream_Read_UINT16(s, header->auth_length);
248 Stream_Read_UINT32(s, header->call_id);
253 WLog_WARN(TAG,
"Invalid header->frag_length of %" PRIu16
", expected %" PRIuz,
260 if (!Stream_CheckAndLogRequiredLength(TAG, s,
266 const size_t sz2 = Stream_GetRemainingLength(s);
273static BOOL rts_read_auth_verifier_no_checks(
wStream* s, auth_verifier_co_t* auth,
279 WINPR_ASSERT(header);
281 WINPR_ASSERT(header->frag_length > header->auth_length + 8);
284 *startPos = Stream_GetPosition(s);
288 const size_t expected = header->frag_length - header->auth_length - 8;
290 Stream_SetPosition(s, expected);
291 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 8, silent))
294 Stream_Read_UINT8(s, auth->auth_type);
295 Stream_Read_UINT8(s, auth->auth_level);
296 Stream_Read_UINT8(s, auth->auth_pad_length);
297 Stream_Read_UINT8(s, auth->auth_reserved);
298 Stream_Read_UINT32(s, auth->auth_context_id);
301 if (header->auth_length != 0)
303 const void* ptr = Stream_Pointer(s);
304 if (!Stream_ConditionalSafeSeek(s, header->auth_length, silent))
306 auth->auth_value = (BYTE*)sdup(ptr, header->auth_length);
307 if (auth->auth_value == NULL)
314static BOOL rts_read_auth_verifier(
wStream* s, auth_verifier_co_t* auth,
320 WINPR_ASSERT(header);
322 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
325 const size_t expected = header->frag_length - header->auth_length - 8;
326 WINPR_ASSERT(pos + auth->auth_pad_length == expected);
327 return pos + auth->auth_pad_length == expected;
330static BOOL rts_read_auth_verifier_with_stub(
wStream* s, auth_verifier_co_t* auth,
334 size_t alloc_hint = 0;
337 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
340 switch (header->ptype)
345 alloc_hint = hdr->alloc_hint;
346 ptr = &hdr->stub_data;
352 alloc_hint = hdr->alloc_hint;
353 ptr = &hdr->stub_data;
359 alloc_hint = hdr->alloc_hint;
360 ptr = &hdr->stub_data;
369 const size_t off = header->auth_length + 8 + auth->auth_pad_length + pos;
370 const size_t size = header->frag_length - MIN(header->frag_length, off);
371 const void* src = Stream_Buffer(s) + pos;
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,
383 *ptr = (BYTE*)sdup(src, size);
392static void rts_free_auth_verifier(auth_verifier_co_t* auth)
396 free(auth->auth_value);
399static BOOL rts_write_auth_verifier(
wStream* s,
const auth_verifier_co_t* auth,
403 UINT8 auth_pad_length = 0;
407 WINPR_ASSERT(header);
410 pos = Stream_GetPosition(s);
413 auth_pad_length = 4 - (pos % 4);
414 if (!Stream_EnsureRemainingCapacity(s, auth_pad_length))
416 Stream_Zero(s, auth_pad_length);
419#if defined(WITH_VERBOSE_WINPR_ASSERT) && (WITH_VERBOSE_WINPR_ASSERT != 0)
420 WINPR_ASSERT(header->frag_length + 8ull > header->auth_length);
422 size_t apos = Stream_GetPosition(s);
423 size_t expected = header->frag_length - header->auth_length - 8;
425 WINPR_ASSERT(apos == expected);
429 if (!Stream_EnsureRemainingCapacity(s,
sizeof(auth_verifier_co_t)))
432 Stream_Write_UINT8(s, auth->auth_type);
433 Stream_Write_UINT8(s, auth->auth_level);
434 Stream_Write_UINT8(s, auth_pad_length);
435 Stream_Write_UINT8(s, 0);
436 Stream_Write_UINT32(s, auth->auth_context_id);
438 if (!Stream_EnsureRemainingCapacity(s, header->auth_length))
440 Stream_Write(s, auth->auth_value, header->auth_length);
447 WINPR_ASSERT(version);
449 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2 *
sizeof(UINT8), silent))
451 Stream_Read_UINT8(s, version->major);
452 Stream_Read_UINT8(s, version->minor);
460 free(versions->p_protocols);
461 versions->p_protocols = NULL;
468 WINPR_ASSERT(versions);
470 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT8), silent))
473 Stream_Read_UINT8(s, versions->n_protocols);
475 if (versions->n_protocols > 0)
477 versions->p_protocols = calloc(versions->n_protocols,
sizeof(
p_rt_version_t));
478 if (!versions->p_protocols)
481 for (BYTE x = 0; x < versions->n_protocols; x++)
484 if (!rts_read_version(s, version, silent))
486 rts_free_supported_versions(versions);
499 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT16), silent))
502 Stream_Read_UINT16(s, port->length);
503 if (port->length == 0)
506 const void* ptr = Stream_ConstPointer(s);
507 if (!Stream_ConditionalSafeSeek(s, port->length, silent))
509 port->port_spec = sdup(ptr, port->length);
510 return port->port_spec != NULL;
513static void rts_free_port_any(
port_any_t* port)
517 free(port->port_spec);
525 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(
p_uuid_t), silent))
528 Stream_Read_UINT32(s, uuid->time_low);
529 Stream_Read_UINT16(s, uuid->time_mid);
530 Stream_Read_UINT16(s, uuid->time_hi_and_version);
531 Stream_Read_UINT8(s, uuid->clock_seq_hi_and_reserved);
532 Stream_Read_UINT8(s, uuid->clock_seq_low);
533 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));
567 WINPR_ASSERT(syntax_id);
569 if (!rts_read_uuid(s, &syntax_id->if_uuid, silent))
572 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
575 Stream_Read_UINT32(s, syntax_id->if_version);
582 WINPR_ASSERT(syntax_id);
584 if (!rts_write_uuid(s, &syntax_id->if_uuid))
587 if (!Stream_EnsureRemainingCapacity(s, 4))
590 Stream_Write_UINT32(s, syntax_id->if_version);
598 rts_syntax_id_free(ptr->transfer_syntaxes);
602WINPR_ATTR_MALLOC(rts_context_elem_free, 1)
613 WINPR_ASSERT(element);
615 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
618 Stream_Read_UINT16(s, element->p_cont_id);
619 Stream_Read_UINT8(s, element->n_transfer_syn);
620 Stream_Read_UINT8(s, element->reserved);
622 if (!rts_read_syntax_id(s, &element->abstract_syntax, silent))
625 if (element->n_transfer_syn > 0)
627 element->transfer_syntaxes = rts_syntax_id_new(element->n_transfer_syn);
628 if (!element->transfer_syntaxes)
630 for (BYTE x = 0; x < element->n_transfer_syn; x++)
633 if (!rts_read_syntax_id(s, syn, silent))
644 WINPR_ASSERT(element);
646 if (!Stream_EnsureRemainingCapacity(s, 4))
648 Stream_Write_UINT16(s, element->p_cont_id);
649 Stream_Write_UINT8(s, element->n_transfer_syn);
650 Stream_Write_UINT8(s, element->reserved);
651 if (!rts_write_syntax_id(s, &element->abstract_syntax))
654 for (BYTE x = 0; x < element->n_transfer_syn; x++)
657 if (!rts_write_syntax_id(s, syn))
669 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
671 Stream_Read_UINT8(s, list->n_context_elem);
672 Stream_Read_UINT8(s, list->reserved);
673 Stream_Read_UINT16(s, list->reserved2);
675 if (list->n_context_elem > 0)
677 list->p_cont_elem = rts_context_elem_new(list->n_context_elem);
678 if (!list->p_cont_elem)
680 for (BYTE x = 0; x < list->n_context_elem; x++)
683 if (!rts_read_context_elem(s, element, silent))
694 rts_context_elem_free(list->p_cont_elem);
702 if (!Stream_EnsureRemainingCapacity(s, 4))
704 Stream_Write_UINT8(s, list->n_context_elem);
705 Stream_Write_UINT8(s, 0);
706 Stream_Write_UINT16(s, 0);
708 for (BYTE x = 0; x < list->n_context_elem; x++)
711 if (!rts_write_context_elem(s, element))
717static p_result_t* rts_result_new(
size_t count)
722static void rts_result_free(
p_result_t* results)
732 WINPR_ASSERT(result);
734 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2, silent))
737 const UINT16 res = Stream_Get_UINT16(s);
742 case provider_rejection:
746 WLog_ERR(TAG,
"Invalid p_cont_def_result_t %" PRIu16, res);
749 result->result = (p_cont_def_result_t)res;
751 const UINT16 reason = Stream_Get_UINT16(s);
754 case reason_not_specified:
755 case abstract_syntax_not_supported:
756 case proposed_transfer_syntaxes_not_supported:
757 case local_limit_exceeded:
760 WLog_ERR(TAG,
"Invalid p_provider_reason_t %" PRIu16, reason);
763 result->reason = (p_provider_reason_t)reason;
764 return rts_read_syntax_id(s, &result->transfer_syntax, silent);
767static void rts_free_result(
p_result_t* result)
778 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
780 Stream_Read_UINT8(s, list->n_results);
781 Stream_Read_UINT8(s, list->reserved);
782 Stream_Read_UINT16(s, list->reserved2);
784 if (list->n_results > 0)
786 list->p_results = rts_result_new(list->n_results);
787 if (!list->p_results)
790 for (BYTE x = 0; x < list->n_results; x++)
793 if (!rts_read_result(s, result, silent))
805 for (BYTE x = 0; x < list->n_results; x++)
808 rts_free_result(result);
810 rts_result_free(list->p_results);
818 rts_free_context_list(&ctx->p_context_elem);
819 rts_free_auth_verifier(&ctx->auth_verifier);
827 if (!Stream_ConditionalCheckAndLogRequiredLength(
831 Stream_Read_UINT16(s, ctx->max_xmit_frag);
832 Stream_Read_UINT16(s, ctx->max_recv_frag);
833 Stream_Read_UINT32(s, ctx->assoc_group_id);
835 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
838 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
844static BOOL rts_read_pdu_alter_context_response(
wStream* s,
851 if (!Stream_ConditionalCheckAndLogRequiredLength(
855 Stream_Read_UINT16(s, ctx->max_xmit_frag);
856 Stream_Read_UINT16(s, ctx->max_recv_frag);
857 Stream_Read_UINT32(s, ctx->assoc_group_id);
859 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
862 if (!rts_align_stream(s, 4, silent))
865 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
868 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
879 rts_free_port_any(&ctx->sec_addr);
880 rts_free_result_list(&ctx->p_result_list);
881 rts_free_auth_verifier(&ctx->auth_verifier);
889 if (!Stream_ConditionalCheckAndLogRequiredLength(
892 Stream_Read_UINT16(s, ctx->max_xmit_frag);
893 Stream_Read_UINT16(s, ctx->max_recv_frag);
894 Stream_Read_UINT32(s, ctx->assoc_group_id);
896 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
899 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
909 rts_free_context_list(&ctx->p_context_elem);
910 rts_free_auth_verifier(&ctx->auth_verifier);
918 if (!Stream_CheckAndLogRequiredLength(
921 Stream_Read_UINT16(s, ctx->max_xmit_frag);
922 Stream_Read_UINT16(s, ctx->max_recv_frag);
923 Stream_Read_UINT32(s, ctx->assoc_group_id);
925 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
928 if (!rts_align_stream(s, 4, silent))
931 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
934 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
941 rts_free_port_any(&ctx->sec_addr);
942 rts_free_result_list(&ctx->p_result_list);
943 rts_free_auth_verifier(&ctx->auth_verifier);
951 if (!Stream_ConditionalCheckAndLogRequiredLength(
954 Stream_Read_UINT16(s, ctx->provider_reject_reason);
955 return rts_read_supported_versions(s, &ctx->versions, silent);
963 rts_free_supported_versions(&ctx->versions);
971 if (!Stream_ConditionalCheckAndLogRequiredLength(
974 Stream_Read_UINT16(s, ctx->max_xmit_frag);
975 Stream_Read_UINT16(s, ctx->max_recv_frag);
977 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
984 rts_free_auth_verifier(&ctx->auth_verifier);
992 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 12, silent))
994 Stream_Read_UINT32(s, ctx->alloc_hint);
995 Stream_Read_UINT16(s, ctx->p_cont_id);
996 Stream_Read_UINT8(s, ctx->cancel_count);
997 Stream_Read_UINT8(s, ctx->reserved);
998 Stream_Read_UINT32(s, ctx->status);
1000 WLog_WARN(TAG,
"status=%s", Win32ErrorCode2Tag(ctx->status & 0xFFFF));
1001 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1008 rts_free_auth_verifier(&ctx->auth_verifier);
1016 if (!Stream_ConditionalCheckAndLogRequiredLength(
1019 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1026 rts_free_auth_verifier(&ctx->auth_verifier);
1034 if (!Stream_ConditionalCheckAndLogRequiredLength(
1037 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1044 rts_free_auth_verifier(&ctx->auth_verifier);
1052 if (!Stream_ConditionalCheckAndLogRequiredLength(
1055 Stream_Read_UINT32(s, ctx->alloc_hint);
1056 Stream_Read_UINT16(s, ctx->p_cont_id);
1057 Stream_Read_UINT16(s, ctx->opnum);
1058 if (!rts_read_uuid(s, &ctx->object, silent))
1061 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1068 rts_free_auth_verifier(&ctx->auth_verifier);
1076 if (!Stream_ConditionalCheckAndLogRequiredLength(
1079 Stream_Read_UINT32(s, ctx->alloc_hint);
1080 Stream_Read_UINT16(s, ctx->p_cont_id);
1081 Stream_Read_UINT8(s, ctx->cancel_count);
1082 Stream_Read_UINT8(s, ctx->reserved);
1084 if (!rts_align_stream(s, 8, silent))
1087 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1094 free(ctx->stub_data);
1095 rts_free_auth_verifier(&ctx->auth_verifier);
1103 if (!Stream_ConditionalCheckAndLogRequiredLength(
1107 Stream_Read_UINT16(s, ctx->Flags);
1108 Stream_Read_UINT16(s, ctx->NumberOfCommands);
1117void rts_free_pdu_header(
rpcconn_hdr_t* header, BOOL allocated)
1122 switch (header->common.ptype)
1124 case PTYPE_ALTER_CONTEXT:
1125 rts_free_pdu_alter_context(&header->alter_context);
1127 case PTYPE_ALTER_CONTEXT_RESP:
1128 rts_free_pdu_alter_context_response(&header->alter_context_response);
1131 rts_free_pdu_bind(&header->bind);
1133 case PTYPE_BIND_ACK:
1134 rts_free_pdu_bind_ack(&header->bind_ack);
1136 case PTYPE_BIND_NAK:
1137 rts_free_pdu_bind_nak(&header->bind_nak);
1139 case PTYPE_RPC_AUTH_3:
1140 rts_free_pdu_auth3(&header->rpc_auth_3);
1142 case PTYPE_CANCEL_ACK:
1143 rts_free_pdu_cancel_ack(&header->cancel);
1146 rts_free_pdu_fault(&header->fault);
1148 case PTYPE_ORPHANED:
1149 rts_free_pdu_orphaned(&header->orphaned);
1152 rts_free_pdu_request(&header->request);
1154 case PTYPE_RESPONSE:
1155 rts_free_pdu_response(&header->response);
1158 rts_free_pdu_rts(&header->rts);
1161 case PTYPE_SHUTDOWN:
1170 case PTYPE_CL_CANCEL:
1172 case PTYPE_CO_CANCEL:
1183 return rts_read_pdu_header_ex(s, header, FALSE);
1190 WINPR_ASSERT(header);
1192 if (!rts_read_common_pdu_header(s, &header->common, silent))
1195 WLog_DBG(TAG,
"Reading PDU type %s", rts_pdu_ptype_to_string(header->common.ptype));
1197 switch (header->common.ptype)
1199 case PTYPE_ALTER_CONTEXT:
1200 rc = rts_read_pdu_alter_context(s, &header->alter_context, silent);
1202 case PTYPE_ALTER_CONTEXT_RESP:
1203 rc = rts_read_pdu_alter_context_response(s, &header->alter_context_response, silent);
1206 rc = rts_read_pdu_bind(s, &header->bind, silent);
1208 case PTYPE_BIND_ACK:
1209 rc = rts_read_pdu_bind_ack(s, &header->bind_ack, silent);
1211 case PTYPE_BIND_NAK:
1212 rc = rts_read_pdu_bind_nak(s, &header->bind_nak, silent);
1214 case PTYPE_RPC_AUTH_3:
1215 rc = rts_read_pdu_auth3(s, &header->rpc_auth_3, silent);
1217 case PTYPE_CANCEL_ACK:
1218 rc = rts_read_pdu_cancel_ack(s, &header->cancel, silent);
1221 rc = rts_read_pdu_fault(s, &header->fault, silent);
1223 case PTYPE_ORPHANED:
1224 rc = rts_read_pdu_orphaned(s, &header->orphaned, silent);
1227 rc = rts_read_pdu_request(s, &header->request, silent);
1229 case PTYPE_RESPONSE:
1230 rc = rts_read_pdu_response(s, &header->response, silent);
1233 rc = rts_read_pdu_rts(s, &header->rts, silent);
1235 case PTYPE_SHUTDOWN:
1245 case PTYPE_CL_CANCEL:
1247 case PTYPE_CO_CANCEL:
1258 WINPR_ASSERT(header);
1262 if (!rts_write_common_pdu_header(s, &header->header))
1265 Stream_Write_UINT16(s, header->Flags);
1266 Stream_Write_UINT16(s, header->NumberOfCommands);
1271static BOOL rts_receive_window_size_command_read(rdpRpc* rpc,
wStream* buffer,
1272 UINT32* ReceiveWindowSize)
1275 WINPR_ASSERT(buffer);
1277 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1279 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1280 if (CommandType != RTS_CMD_RECEIVE_WINDOW_SIZE)
1282 WLog_Print(rpc->log, WLOG_ERROR,
1283 "[MS-RPCH] 2.2.3.5.1 ReceiveWindowSize::CommandType must be 0x%08" PRIx32
1286 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_RECEIVE_WINDOW_SIZE), CommandType);
1289 const UINT32 val = Stream_Get_UINT32(buffer);
1290 if (ReceiveWindowSize)
1291 *ReceiveWindowSize = val;
1297static BOOL rts_receive_window_size_command_write(
wStream* s, UINT32 ReceiveWindowSize)
1301 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT32)))
1304 Stream_Write_UINT32(s, RTS_CMD_RECEIVE_WINDOW_SIZE);
1305 Stream_Write_UINT32(s, ReceiveWindowSize);
1311static int rts_flow_control_ack_command_read(rdpRpc* rpc,
wStream* buffer, UINT32* BytesReceived,
1312 UINT32* AvailableWindow, BYTE* ChannelCookie)
1318 WINPR_ASSERT(buffer);
1320 int rc = rts_destination_command_read(rpc, buffer, &Command);
1324 if (Command != RTS_CMD_FLOW_CONTROL_ACK)
1326 char buffer1[64] = { 0 };
1327 char buffer2[64] = { 0 };
1328 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
1329 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
1330 rts_command_to_string(RTS_CMD_FLOW_CONTROL_ACK, buffer2,
sizeof(buffer2)));
1335 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 24))
1338 Stream_Read_UINT32(buffer, val);
1340 *BytesReceived = val;
1342 Stream_Read_UINT32(buffer, val);
1343 if (AvailableWindow)
1344 *AvailableWindow = val;
1347 Stream_Read(buffer, ChannelCookie, 16);
1349 Stream_Seek(buffer, 16);
1354static BOOL rts_flow_control_ack_command_write(
wStream* s, UINT32 BytesReceived,
1355 UINT32 AvailableWindow, BYTE* ChannelCookie)
1359 if (!Stream_EnsureRemainingCapacity(s, 28))
1362 Stream_Write_UINT32(s, RTS_CMD_FLOW_CONTROL_ACK);
1363 Stream_Write_UINT32(s, BytesReceived);
1364 Stream_Write_UINT32(s, AvailableWindow);
1365 Stream_Write(s, ChannelCookie, 16);
1371static BOOL rts_connection_timeout_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc,
wStream* buffer,
1372 UINT32* ConnectionTimeout)
1375 WINPR_ASSERT(buffer);
1377 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1380 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1381 if (CommandType != RTS_CMD_CONNECTION_TIMEOUT)
1383 WLog_Print(rpc->log, WLOG_ERROR,
1384 "[MS-RPCH] 2.2.3.5.3 ConnectionTimeout::CommandType must be 0x%08" PRIx32
1387 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_CONNECTION_TIMEOUT), CommandType);
1390 const UINT32 val = Stream_Get_UINT32(buffer);
1391 if (ConnectionTimeout)
1392 *ConnectionTimeout = val;
1397static BOOL rts_cookie_command_write(
wStream* s,
const BYTE* Cookie)
1401 if (!Stream_EnsureRemainingCapacity(s, 20))
1404 Stream_Write_UINT32(s, RTS_CMD_COOKIE);
1405 Stream_Write(s, Cookie, 16);
1410static BOOL rts_channel_lifetime_command_write(
wStream* s, UINT32 ChannelLifetime)
1414 if (!Stream_EnsureRemainingCapacity(s, 8))
1416 Stream_Write_UINT32(s, RTS_CMD_CHANNEL_LIFETIME);
1417 Stream_Write_UINT32(s, ChannelLifetime);
1422static BOOL rts_client_keepalive_command_write(
wStream* s, UINT32 ClientKeepalive)
1426 if (!Stream_EnsureRemainingCapacity(s, 8))
1434 Stream_Write_UINT32(s, RTS_CMD_CLIENT_KEEPALIVE);
1435 Stream_Write_UINT32(s, ClientKeepalive);
1441static BOOL rts_version_command_read(rdpRpc* rpc,
wStream* buffer, uint32_t* pversion)
1444 WINPR_ASSERT(buffer);
1446 if (!Stream_EnsureRemainingCapacity(buffer, 8))
1449 const uint32_t CommandType = Stream_Get_UINT32(buffer);
1450 if (CommandType != RTS_CMD_VERSION)
1452 WLog_Print(rpc->log, WLOG_ERROR,
1453 "[MS-RPCH] 2.2.3.5.7 Version::CommandType must be 0x%08" PRIx32
", got "
1455 WINPR_CXX_COMPAT_CAST(UINT32, RTS_CMD_VERSION), CommandType);
1458 const uint32_t version = Stream_Get_UINT32(buffer);
1461 WLog_Print(rpc->log, WLOG_WARN,
1462 "[MS-RPCH] 2.2.3.5.7 Version::Version should be 0x00000001, got 0x%08" PRIx32,
1466 *pversion = version;
1472static BOOL rts_version_command_write(
wStream* buffer)
1474 WINPR_ASSERT(buffer);
1476 if (!Stream_EnsureRemainingCapacity((buffer), 8))
1479 Stream_Write_UINT32(buffer, RTS_CMD_VERSION);
1480 Stream_Write_UINT32(buffer, 1);
1485static BOOL rts_empty_command_write(
wStream* s)
1489 if (!Stream_EnsureRemainingCapacity(s, 8))
1492 Stream_Write_UINT32(s, RTS_CMD_EMPTY);
1497static BOOL rts_padding_command_read(
wStream* s,
size_t* length, BOOL silent)
1499 UINT32 ConformanceCount = 0;
1501 WINPR_ASSERT(length);
1502 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1504 Stream_Read_UINT32(s, ConformanceCount);
1505 *length = ConformanceCount + 4;
1509static BOOL rts_client_address_command_read(
wStream* s,
size_t* length, BOOL silent)
1511 UINT32 AddressType = 0;
1514 WINPR_ASSERT(length);
1516 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1518 Stream_Read_UINT32(s, AddressType);
1520 if (AddressType == 0)
1524 *length = 4 + 4 + 12;
1530 *length = 4 + 16 + 12;
1535static BOOL rts_association_group_id_command_write(
wStream* s,
const BYTE* AssociationGroupId)
1539 if (!Stream_EnsureRemainingCapacity(s, 20))
1542 Stream_Write_UINT32(s, RTS_CMD_ASSOCIATION_GROUP_ID);
1543 Stream_Write(s, AssociationGroupId, 16);
1548static int rts_destination_command_read(WINPR_ATTR_UNUSED rdpRpc* rpc,
wStream* buffer,
1549 UINT32* Destination)
1553 WINPR_ASSERT(buffer);
1555 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 4))
1557 Stream_Read_UINT32(buffer, val);
1564static BOOL rts_destination_command_write(
wStream* s, UINT32 Destination)
1568 if (!Stream_EnsureRemainingCapacity(s, 8))
1571 Stream_Write_UINT32(s, RTS_CMD_DESTINATION);
1572 Stream_Write_UINT32(s, Destination);
1577void rts_generate_cookie(BYTE* cookie)
1579 WINPR_ASSERT(cookie);
1580 winpr_RAND(cookie, 16);
1583#define rts_send_buffer(channel, s, frag_length) \
1584 rts_send_buffer_int((channel), (s), (frag_length), __FILE__, __LINE__, __func__)
1585static BOOL rts_send_buffer_int(
RpcChannel* channel,
wStream* s,
size_t frag_length,
1586 const char* file,
size_t line,
const char* fkt)
1588 BOOL status = FALSE;
1591 WINPR_ASSERT(channel);
1592 WINPR_ASSERT(channel->rpc);
1595 Stream_SealLength(s);
1597 const DWORD level = WLOG_TRACE;
1598 if (WLog_IsLevelActive(channel->rpc->log, level))
1600 WLog_PrintTextMessage(channel->rpc->log, level, line, file, fkt,
1601 "Sending [%s] %" PRIuz
" bytes", fkt, Stream_Length(s));
1605 if (Stream_Length(s) != frag_length)
1608 rc = rpc_channel_write(channel, Stream_Buffer(s), Stream_Length(s));
1611 if ((
size_t)rc != Stream_Length(s))
1620BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc)
1622 BOOL status = FALSE;
1625 UINT32 ReceiveWindowSize = 0;
1626 BYTE* OUTChannelCookie = NULL;
1627 BYTE* VirtualConnectionCookie = NULL;
1633 connection = rpc->VirtualConnection;
1634 WINPR_ASSERT(connection);
1636 outChannel = connection->DefaultOutChannel;
1637 WINPR_ASSERT(outChannel);
1639 header.header.frag_length = 76;
1640 header.Flags = RTS_FLAG_NONE;
1641 header.NumberOfCommands = 4;
1643 WLog_DBG(TAG,
"Sending CONN/A1 RTS PDU");
1644 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1645 OUTChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1646 ReceiveWindowSize = outChannel->ReceiveWindow;
1648 buffer = Stream_New(NULL, header.header.frag_length);
1653 if (!rts_write_pdu_header(buffer, &header))
1655 status = rts_version_command_write(buffer);
1658 status = rts_cookie_command_write(
1659 buffer, VirtualConnectionCookie);
1662 status = rts_cookie_command_write(buffer, OUTChannelCookie);
1665 status = rts_receive_window_size_command_write(
1666 buffer, ReceiveWindowSize);
1669 status = rts_send_buffer(&outChannel->common, buffer, header.header.frag_length);
1671 Stream_Free(buffer, TRUE);
1675BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc,
wStream* buffer)
1678 UINT32 ConnectionTimeout = 0;
1681 if (!rts_read_pdu_header(buffer, &header))
1684 if (header.rts.Flags != RTS_FLAG_NONE)
1686 WLog_Print(rpc->log, WLOG_ERROR,
1687 "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected Flags=0x%08" PRIx32
1688 ", expected 0x%08" PRIx32,
1689 header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
1692 if (header.rts.NumberOfCommands != 1)
1694 WLog_Print(rpc->log, WLOG_ERROR,
1695 "[MS-RPCH] 2.2.4.4 CONN/A3 RTS PDU unexpected NumberOfCommands=%" PRIu32
1697 header.rts.NumberOfCommands);
1701 if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
1704 WLog_Print(rpc->log, WLOG_DEBUG,
"Receiving CONN/A3 RTS PDU: ConnectionTimeout: %" PRIu32
"",
1708 WINPR_ASSERT(rpc->VirtualConnection);
1709 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1711 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
1716 rts_free_pdu_header(&header, FALSE);
1722BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc)
1724 BOOL status = FALSE;
1727 BYTE* INChannelCookie = NULL;
1728 BYTE* AssociationGroupId = NULL;
1729 BYTE* VirtualConnectionCookie = NULL;
1735 connection = rpc->VirtualConnection;
1736 WINPR_ASSERT(connection);
1738 inChannel = connection->DefaultInChannel;
1739 WINPR_ASSERT(inChannel);
1741 header.header.frag_length = 104;
1742 header.Flags = RTS_FLAG_NONE;
1743 header.NumberOfCommands = 6;
1745 WLog_DBG(TAG,
"Sending CONN/B1 RTS PDU");
1747 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1748 INChannelCookie = (BYTE*)&(inChannel->common.Cookie);
1749 AssociationGroupId = (BYTE*)&(connection->AssociationGroupId);
1750 buffer = Stream_New(NULL, header.header.frag_length);
1754 if (!rts_write_pdu_header(buffer, &header))
1756 if (!rts_version_command_write(buffer))
1758 if (!rts_cookie_command_write(buffer,
1759 VirtualConnectionCookie))
1761 if (!rts_cookie_command_write(buffer, INChannelCookie))
1763 if (!rts_channel_lifetime_command_write(buffer,
1764 rpc->ChannelLifetime))
1766 if (!rts_client_keepalive_command_write(buffer,
1767 rpc->KeepAliveInterval))
1769 if (!rts_association_group_id_command_write(
1770 buffer, AssociationGroupId))
1772 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1774 Stream_Free(buffer, TRUE);
1780BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc,
wStream* buffer)
1783 UINT32 ReceiveWindowSize = 0;
1784 UINT32 ConnectionTimeout = 0;
1787 WINPR_ASSERT(buffer);
1790 if (!rts_read_pdu_header(buffer, &header))
1793 if (header.rts.Flags != RTS_FLAG_NONE)
1795 WLog_Print(rpc->log, WLOG_ERROR,
1796 "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected Flags=0x%08" PRIx32
1797 ", expected 0x%08" PRIx32,
1798 header.rts.Flags, WINPR_CXX_COMPAT_CAST(UINT32, RTS_FLAG_NONE));
1801 if (header.rts.NumberOfCommands != 3)
1803 WLog_Print(rpc->log, WLOG_ERROR,
1804 "[MS-RPCH] 2.2.4.9 CONN/C2 RTS PDU unexpected NumberOfCommands=%" PRIu32
1806 header.rts.NumberOfCommands);
1809 if (!rts_version_command_read(rpc, buffer, NULL))
1812 if (!rts_receive_window_size_command_read(rpc, buffer, &ReceiveWindowSize))
1815 if (!rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout))
1818 WLog_Print(rpc->log, WLOG_DEBUG,
1819 "Receiving CONN/C2 RTS PDU: ConnectionTimeout: %" PRIu32
1820 " ReceiveWindowSize: %" PRIu32
"",
1821 ConnectionTimeout, ReceiveWindowSize);
1824 WINPR_ASSERT(rpc->VirtualConnection);
1825 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1827 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
1828 rpc->VirtualConnection->DefaultInChannel->PeerReceiveWindow = ReceiveWindowSize;
1833 rts_free_pdu_header(&header, FALSE);
1839BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc)
1841 BOOL status = FALSE;
1844 UINT32 BytesReceived = 0;
1845 UINT32 AvailableWindow = 0;
1846 BYTE* ChannelCookie = NULL;
1853 connection = rpc->VirtualConnection;
1854 WINPR_ASSERT(connection);
1856 inChannel = connection->DefaultInChannel;
1857 WINPR_ASSERT(inChannel);
1859 outChannel = connection->DefaultOutChannel;
1860 WINPR_ASSERT(outChannel);
1862 header.header.frag_length = 56;
1863 header.Flags = RTS_FLAG_OTHER_CMD;
1864 header.NumberOfCommands = 2;
1866 WLog_DBG(TAG,
"Sending FlowControlAck RTS PDU");
1868 BytesReceived = outChannel->BytesReceived;
1869 AvailableWindow = outChannel->AvailableWindowAdvertised;
1870 ChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1871 outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
1872 buffer = Stream_New(NULL, header.header.frag_length);
1877 if (!rts_write_pdu_header(buffer, &header))
1879 if (!rts_destination_command_write(buffer, FDOutProxy))
1883 if (!rts_flow_control_ack_command_write(buffer, BytesReceived, AvailableWindow, ChannelCookie))
1886 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1888 Stream_Free(buffer, TRUE);
1892static int rts_recv_flow_control_ack_pdu(rdpRpc* rpc,
wStream* buffer)
1895 UINT32 BytesReceived = 0;
1896 UINT32 AvailableWindow = 0;
1897 BYTE ChannelCookie[16] = { 0 };
1899 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1900 (BYTE*)&ChannelCookie);
1904 "Receiving FlowControlAck RTS PDU: BytesReceived: %" PRIu32
1905 " AvailableWindow: %" PRIu32
"",
1906 BytesReceived, AvailableWindow);
1908 WINPR_ASSERT(rpc->VirtualConnection);
1909 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1911 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1912 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1916static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc,
wStream* buffer)
1919 UINT32 Destination = 0;
1920 UINT32 BytesReceived = 0;
1921 UINT32 AvailableWindow = 0;
1922 BYTE ChannelCookie[16] = { 0 };
1940 int rc = rts_destination_command_read(rpc, buffer, &Command);
1944 if (Command != RTS_CMD_DESTINATION)
1946 char buffer1[64] = { 0 };
1947 char buffer2[64] = { 0 };
1948 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
1949 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
1950 rts_command_to_string(RTS_CMD_DESTINATION, buffer2,
sizeof(buffer2)));
1954 rc = rts_destination_command_read(rpc, buffer, &Destination);
1958 switch (Destination)
1969 WLog_Print(rpc->log, WLOG_ERROR,
1970 "got destination %" PRIu32
1971 ", expected one of [FDClient[0]|FDInProxy[1]|FDServer[2]|FDOutProxy[3]",
1976 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1982 "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %" PRIu32
1983 " AvailableWindow: %" PRIu32
"",
1984 BytesReceived, AvailableWindow);
1986 WINPR_ASSERT(rpc->VirtualConnection);
1987 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1988 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1989 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1993BOOL rts_recv_ping_pdu(rdpRpc* rpc,
wStream* s)
1999 WINPR_ASSERT(rpc->auth);
2002 if (!rts_read_pdu_header(s, &header))
2006 if (header.common.ptype != PTYPE_RTS)
2008 WLog_Print(rpc->log, WLOG_ERROR,
"received invalid ping PDU, type is 0x%" PRIx32,
2009 header.common.ptype);
2012 if (header.rts.Flags != RTS_FLAG_PING)
2014 WLog_Print(rpc->log, WLOG_ERROR,
"received unexpected ping PDU::Flags 0x%" PRIx32,
2019 rts_free_pdu_header(&header, FALSE);
2023static int rts_send_ping_pdu(rdpRpc* rpc)
2025 BOOL status = FALSE;
2031 WINPR_ASSERT(rpc->VirtualConnection);
2033 inChannel = rpc->VirtualConnection->DefaultInChannel;
2034 WINPR_ASSERT(inChannel);
2036 header.header.frag_length = 20;
2037 header.Flags = RTS_FLAG_PING;
2038 header.NumberOfCommands = 0;
2040 WLog_DBG(TAG,
"Sending Ping RTS PDU");
2041 buffer = Stream_New(NULL, header.header.frag_length);
2046 if (!rts_write_pdu_header(buffer, &header))
2048 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2050 Stream_Free(buffer, TRUE);
2051 return (status) ? 1 : -1;
2054BOOL rts_command_length(UINT32 CommandType,
wStream* s,
size_t* length, BOOL silent)
2057 size_t CommandLength = 0;
2061 switch (CommandType)
2063 case RTS_CMD_RECEIVE_WINDOW_SIZE:
2064 CommandLength = RTS_CMD_RECEIVE_WINDOW_SIZE_LENGTH;
2067 case RTS_CMD_FLOW_CONTROL_ACK:
2068 CommandLength = RTS_CMD_FLOW_CONTROL_ACK_LENGTH;
2071 case RTS_CMD_CONNECTION_TIMEOUT:
2072 CommandLength = RTS_CMD_CONNECTION_TIMEOUT_LENGTH;
2075 case RTS_CMD_COOKIE:
2076 CommandLength = RTS_CMD_COOKIE_LENGTH;
2079 case RTS_CMD_CHANNEL_LIFETIME:
2080 CommandLength = RTS_CMD_CHANNEL_LIFETIME_LENGTH;
2083 case RTS_CMD_CLIENT_KEEPALIVE:
2084 CommandLength = RTS_CMD_CLIENT_KEEPALIVE_LENGTH;
2087 case RTS_CMD_VERSION:
2088 CommandLength = RTS_CMD_VERSION_LENGTH;
2092 CommandLength = RTS_CMD_EMPTY_LENGTH;
2095 case RTS_CMD_PADDING:
2096 if (!rts_padding_command_read(s, &padding, silent))
2100 case RTS_CMD_NEGATIVE_ANCE:
2101 CommandLength = RTS_CMD_NEGATIVE_ANCE_LENGTH;
2105 CommandLength = RTS_CMD_ANCE_LENGTH;
2108 case RTS_CMD_CLIENT_ADDRESS:
2109 if (!rts_client_address_command_read(s, &CommandLength, silent))
2113 case RTS_CMD_ASSOCIATION_GROUP_ID:
2114 CommandLength = RTS_CMD_ASSOCIATION_GROUP_ID_LENGTH;
2117 case RTS_CMD_DESTINATION:
2118 CommandLength = RTS_CMD_DESTINATION_LENGTH;
2121 case RTS_CMD_PING_TRAFFIC_SENT_NOTIFY:
2122 CommandLength = RTS_CMD_PING_TRAFFIC_SENT_NOTIFY_LENGTH;
2126 WLog_ERR(TAG,
"Error: Unknown RTS Command Type: 0x%" PRIx32
"", CommandType);
2130 CommandLength += padding;
2131 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, CommandLength, silent))
2135 *length = CommandLength;
2139static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
2141 BOOL status = FALSE;
2144 BYTE* SuccessorChannelCookie = NULL;
2149 WINPR_ASSERT(rpc->VirtualConnection);
2151 inChannel = rpc->VirtualConnection->DefaultInChannel;
2152 WINPR_ASSERT(inChannel);
2154 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2155 WINPR_ASSERT(nextOutChannel);
2157 header.header.frag_length = 56;
2158 header.Flags = RTS_FLAG_OUT_CHANNEL;
2159 header.NumberOfCommands = 3;
2161 WLog_DBG(TAG,
"Sending OUT_R2/A7 RTS PDU");
2163 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2164 buffer = Stream_New(NULL, header.header.frag_length);
2169 if (!rts_write_pdu_header(buffer, &header))
2171 if (!rts_destination_command_write(buffer, FDServer))
2173 if (!rts_cookie_command_write(buffer,
2174 SuccessorChannelCookie))
2176 if (!rts_version_command_write(buffer))
2178 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2180 Stream_Free(buffer, TRUE);
2181 return (status) ? 1 : -1;
2184static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc)
2186 BOOL status = FALSE;
2192 WINPR_ASSERT(rpc->VirtualConnection);
2194 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2195 WINPR_ASSERT(nextOutChannel);
2197 header.header.frag_length = 24;
2198 header.Flags = RTS_FLAG_PING;
2199 header.NumberOfCommands = 1;
2201 WLog_DBG(TAG,
"Sending OUT_R2/C1 RTS PDU");
2202 buffer = Stream_New(NULL, header.header.frag_length);
2207 if (!rts_write_pdu_header(buffer, &header))
2210 if (!rts_empty_command_write(buffer))
2212 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2214 Stream_Free(buffer, TRUE);
2215 return (status) ? 1 : -1;
2218BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
2220 BOOL status = FALSE;
2223 UINT32 ReceiveWindowSize = 0;
2224 BYTE* VirtualConnectionCookie = NULL;
2225 BYTE* PredecessorChannelCookie = NULL;
2226 BYTE* SuccessorChannelCookie = NULL;
2233 connection = rpc->VirtualConnection;
2234 WINPR_ASSERT(connection);
2236 outChannel = connection->DefaultOutChannel;
2237 WINPR_ASSERT(outChannel);
2239 nextOutChannel = connection->NonDefaultOutChannel;
2240 WINPR_ASSERT(nextOutChannel);
2242 header.header.frag_length = 96;
2243 header.Flags = RTS_FLAG_RECYCLE_CHANNEL;
2244 header.NumberOfCommands = 5;
2246 WLog_DBG(TAG,
"Sending OUT_R1/A3 RTS PDU");
2248 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
2249 PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie);
2250 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2251 ReceiveWindowSize = outChannel->ReceiveWindow;
2252 buffer = Stream_New(NULL, header.header.frag_length);
2257 if (!rts_write_pdu_header(buffer, &header))
2259 if (!rts_version_command_write(buffer))
2261 if (!rts_cookie_command_write(buffer,
2262 VirtualConnectionCookie))
2264 if (!rts_cookie_command_write(
2265 buffer, PredecessorChannelCookie))
2267 if (!rts_cookie_command_write(buffer,
2268 SuccessorChannelCookie))
2270 if (!rts_receive_window_size_command_write(buffer,
2274 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2276 Stream_Free(buffer, TRUE);
2280static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc,
wStream* buffer)
2283 UINT32 Destination = 0;
2286 WINPR_ASSERT(buffer);
2288 connection = rpc->VirtualConnection;
2289 WINPR_ASSERT(connection);
2291 WLog_DBG(TAG,
"Receiving OUT R1/A2 RTS PDU");
2293 status = rts_destination_command_read(rpc, buffer, &Destination);
2297 connection->NonDefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
2299 if (!connection->NonDefaultOutChannel)
2302 status = rpc_out_channel_replacement_connect(connection->NonDefaultOutChannel, 5000);
2306 WLog_ERR(TAG,
"rpc_out_channel_replacement_connect failure");
2310 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2311 CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
2315static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED
wStream* buffer)
2321 WINPR_ASSERT(buffer);
2323 connection = rpc->VirtualConnection;
2324 WINPR_ASSERT(connection);
2326 WLog_DBG(TAG,
"Receiving OUT R2/A6 RTS PDU");
2327 status = rts_send_OUT_R2_C1_pdu(rpc);
2331 WLog_ERR(TAG,
"rts_send_OUT_R2_C1_pdu failure");
2335 status = rts_send_OUT_R2_A7_pdu(rpc);
2339 WLog_ERR(TAG,
"rts_send_OUT_R2_A7_pdu failure");
2343 rpc_out_channel_transition_to_state(connection->NonDefaultOutChannel,
2344 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2345 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2346 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2350static int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc, WINPR_ATTR_UNUSED
wStream* buffer)
2355 WINPR_ASSERT(buffer);
2357 connection = rpc->VirtualConnection;
2358 WINPR_ASSERT(connection);
2360 WLog_DBG(TAG,
"Receiving OUT R2/B3 RTS PDU");
2361 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2362 CLIENT_OUT_CHANNEL_STATE_RECYCLED);
2368 BOOL status = FALSE;
2374 WINPR_ASSERT(buffer);
2375 WINPR_ASSERT(header);
2377 wLog* log = WLog_Get(TAG);
2379 const size_t total = Stream_Length(buffer);
2380 length = header->common.frag_length;
2383 WLog_Print(log, WLOG_ERROR,
"PDU length %" PRIuz
" does not match available data %" PRIuz,
2388 connection = rpc->VirtualConnection;
2392 WLog_Print(log, WLOG_ERROR,
"not connected, aborting");
2396 if (!rts_extract_pdu_signature(&signature, buffer, header))
2399 rts_print_pdu_signature(log, WLOG_TRACE, &signature);
2401 if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE,
sizeof(signature)) == 0)
2403 status = rts_recv_flow_control_ack_pdu(rpc, buffer);
2405 else if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE,
2406 sizeof(signature)) == 0)
2408 status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer);
2410 else if (memcmp(&signature, &RTS_PDU_PING_SIGNATURE,
sizeof(signature)) == 0)
2412 status = rts_send_ping_pdu(rpc);
2416 if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
2418 if (memcmp(&signature, &RTS_PDU_OUT_R1_A2_SIGNATURE,
sizeof(signature)) == 0)
2420 status = rts_recv_OUT_R1_A2_pdu(rpc, buffer);
2423 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_A6W)
2425 if (memcmp(&signature, &RTS_PDU_OUT_R2_A6_SIGNATURE,
sizeof(signature)) == 0)
2427 status = rts_recv_OUT_R2_A6_pdu(rpc, buffer);
2430 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_B3W)
2432 if (memcmp(&signature, &RTS_PDU_OUT_R2_B3_SIGNATURE,
sizeof(signature)) == 0)
2434 status = rts_recv_OUT_R2_B3_pdu(rpc, buffer);
2441 const UINT32 SignatureId = rts_identify_pdu_signature(&signature, NULL);
2442 WLog_Print(log, WLOG_ERROR,
"error parsing RTS PDU with signature id: 0x%08" PRIX32
"",
2444 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2447 const size_t rem = Stream_GetRemainingLength(buffer);
2450 WLog_Print(log, WLOG_ERROR,
"%" PRIuz
" bytes or %" PRIuz
" total not parsed, aborting",
2452 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2464 if (!rts_write_common_pdu_header(s, &auth->header))
2467 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT16)))
2470 Stream_Write_UINT16(s, auth->max_xmit_frag);
2471 Stream_Write_UINT16(s, auth->max_recv_frag);
2473 return rts_write_auth_verifier(s, &auth->auth_verifier, &auth->header);
2482 if (!rts_write_common_pdu_header(s, &bind->header))
2485 if (!Stream_EnsureRemainingCapacity(s, 8))
2488 Stream_Write_UINT16(s, bind->max_xmit_frag);
2489 Stream_Write_UINT16(s, bind->max_recv_frag);
2490 Stream_Write_UINT32(s, bind->assoc_group_id);
2492 if (!rts_write_context_list(s, &bind->p_context_elem))
2495 return rts_write_auth_verifier(s, &bind->auth_verifier, &bind->header);
2498BOOL rts_conditional_check_and_log(
const char* tag,
wStream* s,
size_t size, BOOL silent,
2499 const char* fkt,
const char* file,
size_t line)
2503 const size_t rem = Stream_GetRemainingLength(s);
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);