20 #include <freerdp/config.h>
22 #include <winpr/assert.h>
23 #include <winpr/crt.h>
24 #include <winpr/crypto.h>
26 #include <freerdp/log.h>
28 #include "ncacn_http.h"
29 #include "rpc_client.h"
30 #include "rts_signature.h"
34 #define TAG FREERDP_TAG("core.gateway.rts")
69 static int rts_destination_command_read(rdpRpc* rpc,
wStream* buffer, UINT32* Destination);
71 static const char* rts_command_to_string(UINT32 cmd,
char* buffer,
size_t len)
73 const char* str = NULL;
83 ENTRY(RTS_CMD_RECEIVE_WINDOW_SIZE);
84 ENTRY(RTS_CMD_FLOW_CONTROL_ACK);
85 ENTRY(RTS_CMD_CONNECTION_TIMEOUT);
86 ENTRY(RTS_CMD_COOKIE);
87 ENTRY(RTS_CMD_CHANNEL_LIFETIME);
88 ENTRY(RTS_CMD_CLIENT_KEEPALIVE);
89 ENTRY(RTS_CMD_VERSION);
91 ENTRY(RTS_CMD_PADDING);
92 ENTRY(RTS_CMD_NEGATIVE_ANCE);
94 ENTRY(RTS_CMD_CLIENT_ADDRESS);
95 ENTRY(RTS_CMD_ASSOCIATION_GROUP_ID);
96 ENTRY(RTS_CMD_DESTINATION);
97 ENTRY(RTS_CMD_PING_TRAFFIC_SENT_NOTIFY);
98 ENTRY(RTS_CMD_LAST_ID);
100 str =
"RTS_CMD_UNKNOWN";
106 (void)_snprintf(buffer, len,
"%s [0x%08" PRIx32
"]", str, cmd);
110 static const char* rts_pdu_ptype_to_string(UINT32 ptype)
115 return "PTYPE_REQUEST";
119 return "PTYPE_RESPONSE";
121 return "PTYPE_FAULT";
123 return "PTYPE_WORKING";
125 return "PTYPE_NOCALL";
127 return "PTYPE_REJECT";
130 case PTYPE_CL_CANCEL:
131 return "PTYPE_CL_CANCEL";
134 case PTYPE_CANCEL_ACK:
135 return "PTYPE_CANCEL_ACK";
139 return "PTYPE_BIND_ACK";
141 return "PTYPE_BIND_NAK";
142 case PTYPE_ALTER_CONTEXT:
143 return "PTYPE_ALTER_CONTEXT";
144 case PTYPE_ALTER_CONTEXT_RESP:
145 return "PTYPE_ALTER_CONTEXT_RESP";
146 case PTYPE_RPC_AUTH_3:
147 return "PTYPE_RPC_AUTH_3";
149 return "PTYPE_SHUTDOWN";
150 case PTYPE_CO_CANCEL:
151 return "PTYPE_CO_CANCEL";
153 return "PTYPE_ORPHANED";
164 header.header.rpc_vers = 5;
165 header.header.rpc_vers_minor = 0;
166 header.header.ptype = PTYPE_RTS;
167 header.header.packed_drep[0] = 0x10;
168 header.header.packed_drep[1] = 0x00;
169 header.header.packed_drep[2] = 0x00;
170 header.header.packed_drep[3] = 0x00;
171 header.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
172 header.header.auth_length = 0;
173 header.header.call_id = 0;
178 static BOOL rts_align_stream(
wStream* s,
size_t alignment, BOOL silent)
184 WINPR_ASSERT(alignment > 0);
186 pos = Stream_GetPosition(s);
187 pad = rpc_offset_align(&pos, alignment);
188 return Stream_ConditionalSafeSeek(s, pad, silent);
191 static char* sdup(
const void* src,
size_t length)
194 WINPR_ASSERT(src || (length == 0));
198 dst = calloc(length + 1,
sizeof(
char));
201 memcpy(dst, src, length);
208 WINPR_ASSERT(header);
212 Stream_Write_UINT8(s, header->rpc_vers);
213 Stream_Write_UINT8(s, header->rpc_vers_minor);
214 Stream_Write_UINT8(s, header->ptype);
215 Stream_Write_UINT8(s, header->pfc_flags);
216 Stream_Write(s, header->packed_drep, ARRAYSIZE(header->packed_drep));
217 Stream_Write_UINT16(s, header->frag_length);
218 Stream_Write_UINT16(s, header->auth_length);
219 Stream_Write_UINT32(s, header->call_id);
226 WINPR_ASSERT(header);
235 const size_t sz = Stream_GetRemainingLength(s);
240 Stream_Read_UINT8(s, header->rpc_vers);
241 Stream_Read_UINT8(s, header->rpc_vers_minor);
242 Stream_Read_UINT8(s, header->ptype);
243 Stream_Read_UINT8(s, header->pfc_flags);
244 Stream_Read(s, header->packed_drep, ARRAYSIZE(header->packed_drep));
245 Stream_Read_UINT16(s, header->frag_length);
246 Stream_Read_UINT16(s, header->auth_length);
247 Stream_Read_UINT32(s, header->call_id);
252 WLog_WARN(TAG,
"Invalid header->frag_length of %" PRIu16
", expected %" PRIuz,
259 if (!Stream_CheckAndLogRequiredLength(TAG, s,
265 const size_t sz2 = Stream_GetRemainingLength(s);
272 static BOOL rts_read_auth_verifier_no_checks(
wStream* s, auth_verifier_co_t* auth,
278 WINPR_ASSERT(header);
280 WINPR_ASSERT(header->frag_length > header->auth_length + 8);
283 *startPos = Stream_GetPosition(s);
287 const size_t expected = header->frag_length - header->auth_length - 8;
289 Stream_SetPosition(s, expected);
290 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 8, silent))
293 Stream_Read_UINT8(s, auth->auth_type);
294 Stream_Read_UINT8(s, auth->auth_level);
295 Stream_Read_UINT8(s, auth->auth_pad_length);
296 Stream_Read_UINT8(s, auth->auth_reserved);
297 Stream_Read_UINT32(s, auth->auth_context_id);
300 if (header->auth_length != 0)
302 const void* ptr = Stream_Pointer(s);
303 if (!Stream_ConditionalSafeSeek(s, header->auth_length, silent))
305 auth->auth_value = (BYTE*)sdup(ptr, header->auth_length);
306 if (auth->auth_value == NULL)
313 static BOOL rts_read_auth_verifier(
wStream* s, auth_verifier_co_t* auth,
319 WINPR_ASSERT(header);
321 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
324 const size_t expected = header->frag_length - header->auth_length - 8;
325 WINPR_ASSERT(pos + auth->auth_pad_length == expected);
326 return pos + auth->auth_pad_length == expected;
329 static BOOL rts_read_auth_verifier_with_stub(
wStream* s, auth_verifier_co_t* auth,
333 size_t alloc_hint = 0;
336 if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos, silent))
339 switch (header->ptype)
344 alloc_hint = hdr->alloc_hint;
345 ptr = &hdr->stub_data;
351 alloc_hint = hdr->alloc_hint;
352 ptr = &hdr->stub_data;
358 alloc_hint = hdr->alloc_hint;
359 ptr = &hdr->stub_data;
368 const size_t off = header->auth_length + 8 + auth->auth_pad_length + pos;
369 const size_t size = header->frag_length - MIN(header->frag_length, off);
370 const void* src = Stream_Buffer(s) + pos;
372 if (off > header->frag_length)
374 "Unexpected alloc_hint(%" PRIuz
") for PDU %s: size %" PRIuz
376 alloc_hint, rts_pdu_ptype_to_string(header->ptype), header->frag_length, off);
377 *ptr = (BYTE*)sdup(src, size);
385 static void rts_free_auth_verifier(auth_verifier_co_t* auth)
389 free(auth->auth_value);
392 static BOOL rts_write_auth_verifier(
wStream* s,
const auth_verifier_co_t* auth,
396 UINT8 auth_pad_length = 0;
400 WINPR_ASSERT(header);
403 pos = Stream_GetPosition(s);
406 auth_pad_length = 4 - (pos % 4);
407 if (!Stream_EnsureRemainingCapacity(s, auth_pad_length))
409 Stream_Zero(s, auth_pad_length);
412 #if defined(WITH_VERBOSE_WINPR_ASSERT) && (WITH_VERBOSE_WINPR_ASSERT != 0)
413 WINPR_ASSERT(header->frag_length + 8ull > header->auth_length);
415 size_t apos = Stream_GetPosition(s);
416 size_t expected = header->frag_length - header->auth_length - 8;
418 WINPR_ASSERT(apos == expected);
422 if (!Stream_EnsureRemainingCapacity(s,
sizeof(auth_verifier_co_t)))
425 Stream_Write_UINT8(s, auth->auth_type);
426 Stream_Write_UINT8(s, auth->auth_level);
427 Stream_Write_UINT8(s, auth_pad_length);
428 Stream_Write_UINT8(s, 0);
429 Stream_Write_UINT32(s, auth->auth_context_id);
431 if (!Stream_EnsureRemainingCapacity(s, header->auth_length))
433 Stream_Write(s, auth->auth_value, header->auth_length);
440 WINPR_ASSERT(version);
442 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2 *
sizeof(UINT8), silent))
444 Stream_Read_UINT8(s, version->major);
445 Stream_Read_UINT8(s, version->minor);
453 free(versions->p_protocols);
454 versions->p_protocols = NULL;
461 WINPR_ASSERT(versions);
463 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT8), silent))
466 Stream_Read_UINT8(s, versions->n_protocols);
468 if (versions->n_protocols > 0)
470 versions->p_protocols = calloc(versions->n_protocols,
sizeof(
p_rt_version_t));
471 if (!versions->p_protocols)
474 for (BYTE x = 0; x < versions->n_protocols; x++)
477 if (!rts_read_version(s, version, silent))
479 rts_free_supported_versions(versions);
492 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(UINT16), silent))
495 Stream_Read_UINT16(s, port->length);
496 if (port->length == 0)
499 const void* ptr = Stream_ConstPointer(s);
500 if (!Stream_ConditionalSafeSeek(s, port->length, silent))
502 port->port_spec = sdup(ptr, port->length);
503 return port->port_spec != NULL;
506 static void rts_free_port_any(
port_any_t* port)
510 free(port->port_spec);
518 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s,
sizeof(
p_uuid_t), silent))
521 Stream_Read_UINT32(s, uuid->time_low);
522 Stream_Read_UINT16(s, uuid->time_mid);
523 Stream_Read_UINT16(s, uuid->time_hi_and_version);
524 Stream_Read_UINT8(s, uuid->clock_seq_hi_and_reserved);
525 Stream_Read_UINT8(s, uuid->clock_seq_low);
526 Stream_Read(s, uuid->node, ARRAYSIZE(uuid->node));
535 if (!Stream_EnsureRemainingCapacity(s,
sizeof(
p_uuid_t)))
538 Stream_Write_UINT32(s, uuid->time_low);
539 Stream_Write_UINT16(s, uuid->time_mid);
540 Stream_Write_UINT16(s, uuid->time_hi_and_version);
541 Stream_Write_UINT8(s, uuid->clock_seq_hi_and_reserved);
542 Stream_Write_UINT8(s, uuid->clock_seq_low);
543 Stream_Write(s, uuid->node, ARRAYSIZE(uuid->node));
560 WINPR_ASSERT(syntax_id);
562 if (!rts_read_uuid(s, &syntax_id->if_uuid, silent))
565 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
568 Stream_Read_UINT32(s, syntax_id->if_version);
575 WINPR_ASSERT(syntax_id);
577 if (!rts_write_uuid(s, &syntax_id->if_uuid))
580 if (!Stream_EnsureRemainingCapacity(s, 4))
583 Stream_Write_UINT32(s, syntax_id->if_version);
597 rts_syntax_id_free(ptr->transfer_syntaxes);
604 WINPR_ASSERT(element);
606 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
609 Stream_Read_UINT16(s, element->p_cont_id);
610 Stream_Read_UINT8(s, element->n_transfer_syn);
611 Stream_Read_UINT8(s, element->reserved);
613 if (!rts_read_syntax_id(s, &element->abstract_syntax, silent))
616 if (element->n_transfer_syn > 0)
618 element->transfer_syntaxes = rts_syntax_id_new(element->n_transfer_syn);
619 if (!element->transfer_syntaxes)
621 for (BYTE x = 0; x < element->n_transfer_syn; x++)
624 if (!rts_read_syntax_id(s, syn, silent))
635 WINPR_ASSERT(element);
637 if (!Stream_EnsureRemainingCapacity(s, 4))
639 Stream_Write_UINT16(s, element->p_cont_id);
640 Stream_Write_UINT8(s, element->n_transfer_syn);
641 Stream_Write_UINT8(s, element->reserved);
642 if (!rts_write_syntax_id(s, &element->abstract_syntax))
645 for (BYTE x = 0; x < element->n_transfer_syn; x++)
648 if (!rts_write_syntax_id(s, syn))
660 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
662 Stream_Read_UINT8(s, list->n_context_elem);
663 Stream_Read_UINT8(s, list->reserved);
664 Stream_Read_UINT16(s, list->reserved2);
666 if (list->n_context_elem > 0)
668 list->p_cont_elem = rts_context_elem_new(list->n_context_elem);
669 if (!list->p_cont_elem)
671 for (BYTE x = 0; x < list->n_context_elem; x++)
674 if (!rts_read_context_elem(s, element, silent))
685 rts_context_elem_free(list->p_cont_elem);
693 if (!Stream_EnsureRemainingCapacity(s, 4))
695 Stream_Write_UINT8(s, list->n_context_elem);
696 Stream_Write_UINT8(s, 0);
697 Stream_Write_UINT16(s, 0);
699 for (BYTE x = 0; x < list->n_context_elem; x++)
702 if (!rts_write_context_elem(s, element))
708 static p_result_t* rts_result_new(
size_t count)
713 static void rts_result_free(
p_result_t* results)
723 WINPR_ASSERT(result);
725 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 2, silent))
727 Stream_Read_UINT16(s, result->result);
728 Stream_Read_UINT16(s, result->reason);
730 return rts_read_syntax_id(s, &result->transfer_syntax, silent);
733 static void rts_free_result(
p_result_t* result)
744 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
746 Stream_Read_UINT8(s, list->n_results);
747 Stream_Read_UINT8(s, list->reserved);
748 Stream_Read_UINT16(s, list->reserved2);
750 if (list->n_results > 0)
752 list->p_results = rts_result_new(list->n_results);
753 if (!list->p_results)
756 for (BYTE x = 0; x < list->n_results; x++)
759 if (!rts_read_result(s, result, silent))
771 for (BYTE x = 0; x < list->n_results; x++)
774 rts_free_result(result);
776 rts_result_free(list->p_results);
784 rts_free_context_list(&ctx->p_context_elem);
785 rts_free_auth_verifier(&ctx->auth_verifier);
793 if (!Stream_ConditionalCheckAndLogRequiredLength(
797 Stream_Read_UINT16(s, ctx->max_xmit_frag);
798 Stream_Read_UINT16(s, ctx->max_recv_frag);
799 Stream_Read_UINT32(s, ctx->assoc_group_id);
801 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
804 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
810 static BOOL rts_read_pdu_alter_context_response(
wStream* s,
817 if (!Stream_ConditionalCheckAndLogRequiredLength(
821 Stream_Read_UINT16(s, ctx->max_xmit_frag);
822 Stream_Read_UINT16(s, ctx->max_recv_frag);
823 Stream_Read_UINT32(s, ctx->assoc_group_id);
825 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
828 if (!rts_align_stream(s, 4, silent))
831 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
834 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
845 rts_free_port_any(&ctx->sec_addr);
846 rts_free_result_list(&ctx->p_result_list);
847 rts_free_auth_verifier(&ctx->auth_verifier);
855 if (!Stream_ConditionalCheckAndLogRequiredLength(
858 Stream_Read_UINT16(s, ctx->max_xmit_frag);
859 Stream_Read_UINT16(s, ctx->max_recv_frag);
860 Stream_Read_UINT32(s, ctx->assoc_group_id);
862 if (!rts_read_context_list(s, &ctx->p_context_elem, silent))
865 if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent))
875 rts_free_context_list(&ctx->p_context_elem);
876 rts_free_auth_verifier(&ctx->auth_verifier);
884 if (!Stream_CheckAndLogRequiredLength(
887 Stream_Read_UINT16(s, ctx->max_xmit_frag);
888 Stream_Read_UINT16(s, ctx->max_recv_frag);
889 Stream_Read_UINT32(s, ctx->assoc_group_id);
891 if (!rts_read_port_any(s, &ctx->sec_addr, silent))
894 if (!rts_align_stream(s, 4, silent))
897 if (!rts_read_result_list(s, &ctx->p_result_list, silent))
900 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
907 rts_free_port_any(&ctx->sec_addr);
908 rts_free_result_list(&ctx->p_result_list);
909 rts_free_auth_verifier(&ctx->auth_verifier);
917 if (!Stream_ConditionalCheckAndLogRequiredLength(
920 Stream_Read_UINT16(s, ctx->provider_reject_reason);
921 return rts_read_supported_versions(s, &ctx->versions, silent);
929 rts_free_supported_versions(&ctx->versions);
937 if (!Stream_ConditionalCheckAndLogRequiredLength(
940 Stream_Read_UINT16(s, ctx->max_xmit_frag);
941 Stream_Read_UINT16(s, ctx->max_recv_frag);
943 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
950 rts_free_auth_verifier(&ctx->auth_verifier);
958 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 12, silent))
960 Stream_Read_UINT32(s, ctx->alloc_hint);
961 Stream_Read_UINT16(s, ctx->p_cont_id);
962 Stream_Read_UINT8(s, ctx->cancel_count);
963 Stream_Read_UINT8(s, ctx->reserved);
964 Stream_Read_UINT32(s, ctx->status);
966 WLog_WARN(TAG,
"status=%s", Win32ErrorCode2Tag(ctx->status));
967 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
974 rts_free_auth_verifier(&ctx->auth_verifier);
982 if (!Stream_ConditionalCheckAndLogRequiredLength(
985 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
992 rts_free_auth_verifier(&ctx->auth_verifier);
1000 if (!Stream_ConditionalCheckAndLogRequiredLength(
1003 return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header, silent);
1010 rts_free_auth_verifier(&ctx->auth_verifier);
1018 if (!Stream_ConditionalCheckAndLogRequiredLength(
1021 Stream_Read_UINT32(s, ctx->alloc_hint);
1022 Stream_Read_UINT16(s, ctx->p_cont_id);
1023 Stream_Read_UINT16(s, ctx->opnum);
1024 if (!rts_read_uuid(s, &ctx->object, silent))
1027 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1034 rts_free_auth_verifier(&ctx->auth_verifier);
1042 if (!Stream_ConditionalCheckAndLogRequiredLength(
1045 Stream_Read_UINT32(s, ctx->alloc_hint);
1046 Stream_Read_UINT16(s, ctx->p_cont_id);
1047 Stream_Read_UINT8(s, ctx->cancel_count);
1048 Stream_Read_UINT8(s, ctx->reserved);
1050 if (!rts_align_stream(s, 8, silent))
1053 return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header, silent);
1060 free(ctx->stub_data);
1061 rts_free_auth_verifier(&ctx->auth_verifier);
1069 if (!Stream_ConditionalCheckAndLogRequiredLength(
1073 Stream_Read_UINT16(s, ctx->Flags);
1074 Stream_Read_UINT16(s, ctx->NumberOfCommands);
1083 void rts_free_pdu_header(
rpcconn_hdr_t* header, BOOL allocated)
1088 switch (header->common.ptype)
1090 case PTYPE_ALTER_CONTEXT:
1091 rts_free_pdu_alter_context(&header->alter_context);
1093 case PTYPE_ALTER_CONTEXT_RESP:
1094 rts_free_pdu_alter_context_response(&header->alter_context_response);
1097 rts_free_pdu_bind(&header->bind);
1099 case PTYPE_BIND_ACK:
1100 rts_free_pdu_bind_ack(&header->bind_ack);
1102 case PTYPE_BIND_NAK:
1103 rts_free_pdu_bind_nak(&header->bind_nak);
1105 case PTYPE_RPC_AUTH_3:
1106 rts_free_pdu_auth3(&header->rpc_auth_3);
1108 case PTYPE_CANCEL_ACK:
1109 rts_free_pdu_cancel_ack(&header->cancel);
1112 rts_free_pdu_fault(&header->fault);
1114 case PTYPE_ORPHANED:
1115 rts_free_pdu_orphaned(&header->orphaned);
1118 rts_free_pdu_request(&header->request);
1120 case PTYPE_RESPONSE:
1121 rts_free_pdu_response(&header->response);
1124 rts_free_pdu_rts(&header->rts);
1127 case PTYPE_SHUTDOWN:
1136 case PTYPE_CL_CANCEL:
1138 case PTYPE_CO_CANCEL:
1149 return rts_read_pdu_header_ex(s, header, FALSE);
1156 WINPR_ASSERT(header);
1158 if (!rts_read_common_pdu_header(s, &header->common, silent))
1161 WLog_DBG(TAG,
"Reading PDU type %s", rts_pdu_ptype_to_string(header->common.ptype));
1163 switch (header->common.ptype)
1165 case PTYPE_ALTER_CONTEXT:
1166 rc = rts_read_pdu_alter_context(s, &header->alter_context, silent);
1168 case PTYPE_ALTER_CONTEXT_RESP:
1169 rc = rts_read_pdu_alter_context_response(s, &header->alter_context_response, silent);
1172 rc = rts_read_pdu_bind(s, &header->bind, silent);
1174 case PTYPE_BIND_ACK:
1175 rc = rts_read_pdu_bind_ack(s, &header->bind_ack, silent);
1177 case PTYPE_BIND_NAK:
1178 rc = rts_read_pdu_bind_nak(s, &header->bind_nak, silent);
1180 case PTYPE_RPC_AUTH_3:
1181 rc = rts_read_pdu_auth3(s, &header->rpc_auth_3, silent);
1183 case PTYPE_CANCEL_ACK:
1184 rc = rts_read_pdu_cancel_ack(s, &header->cancel, silent);
1187 rc = rts_read_pdu_fault(s, &header->fault, silent);
1189 case PTYPE_ORPHANED:
1190 rc = rts_read_pdu_orphaned(s, &header->orphaned, silent);
1193 rc = rts_read_pdu_request(s, &header->request, silent);
1195 case PTYPE_RESPONSE:
1196 rc = rts_read_pdu_response(s, &header->response, silent);
1199 rc = rts_read_pdu_rts(s, &header->rts, silent);
1201 case PTYPE_SHUTDOWN:
1211 case PTYPE_CL_CANCEL:
1213 case PTYPE_CO_CANCEL:
1224 WINPR_ASSERT(header);
1228 if (!rts_write_common_pdu_header(s, &header->header))
1231 Stream_Write_UINT16(s, header->Flags);
1232 Stream_Write_UINT16(s, header->NumberOfCommands);
1236 static BOOL rts_receive_window_size_command_read(rdpRpc* rpc,
wStream* buffer,
1237 UINT64* ReceiveWindowSize)
1240 WINPR_ASSERT(buffer);
1242 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1244 const UINT64 val = Stream_Get_UINT64(buffer);
1245 if (ReceiveWindowSize)
1246 *ReceiveWindowSize = val;
1251 static BOOL rts_receive_window_size_command_write(
wStream* s, UINT32 ReceiveWindowSize)
1255 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT32)))
1258 Stream_Write_UINT32(s, RTS_CMD_RECEIVE_WINDOW_SIZE);
1259 Stream_Write_UINT32(s, ReceiveWindowSize);
1264 static int rts_flow_control_ack_command_read(rdpRpc* rpc,
wStream* buffer, UINT32* BytesReceived,
1265 UINT32* AvailableWindow, BYTE* ChannelCookie)
1271 WINPR_ASSERT(buffer);
1273 int rc = rts_destination_command_read(rpc, buffer, &Command);
1277 if (Command != RTS_CMD_FLOW_CONTROL_ACK)
1279 char buffer1[64] = { 0 };
1280 char buffer2[64] = { 0 };
1281 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
1282 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
1283 rts_command_to_string(RTS_CMD_FLOW_CONTROL_ACK, buffer2,
sizeof(buffer2)));
1288 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 24))
1291 Stream_Read_UINT32(buffer, val);
1293 *BytesReceived = val;
1295 Stream_Read_UINT32(buffer, val);
1296 if (AvailableWindow)
1297 *AvailableWindow = val;
1300 Stream_Read(buffer, ChannelCookie, 16);
1302 Stream_Seek(buffer, 16);
1306 static BOOL rts_flow_control_ack_command_write(
wStream* s, UINT32 BytesReceived,
1307 UINT32 AvailableWindow, BYTE* ChannelCookie)
1311 if (!Stream_EnsureRemainingCapacity(s, 28))
1314 Stream_Write_UINT32(s, RTS_CMD_FLOW_CONTROL_ACK);
1315 Stream_Write_UINT32(s, BytesReceived);
1316 Stream_Write_UINT32(s, AvailableWindow);
1317 Stream_Write(s, ChannelCookie, 16);
1322 static BOOL rts_connection_timeout_command_read(rdpRpc* rpc,
wStream* buffer,
1323 UINT64* ConnectionTimeout)
1326 WINPR_ASSERT(buffer);
1328 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 8))
1331 UINT64 val = Stream_Get_UINT64(buffer);
1332 if (ConnectionTimeout)
1333 *ConnectionTimeout = val;
1338 static BOOL rts_cookie_command_write(
wStream* s,
const BYTE* Cookie)
1342 if (!Stream_EnsureRemainingCapacity(s, 20))
1345 Stream_Write_UINT32(s, RTS_CMD_COOKIE);
1346 Stream_Write(s, Cookie, 16);
1351 static BOOL rts_channel_lifetime_command_write(
wStream* s, UINT32 ChannelLifetime)
1355 if (!Stream_EnsureRemainingCapacity(s, 8))
1357 Stream_Write_UINT32(s, RTS_CMD_CHANNEL_LIFETIME);
1358 Stream_Write_UINT32(s, ChannelLifetime);
1363 static BOOL rts_client_keepalive_command_write(
wStream* s, UINT32 ClientKeepalive)
1367 if (!Stream_EnsureRemainingCapacity(s, 8))
1375 Stream_Write_UINT32(s, RTS_CMD_CLIENT_KEEPALIVE);
1376 Stream_Write_UINT32(s, ClientKeepalive);
1381 static BOOL rts_version_command_read(rdpRpc* rpc,
wStream* buffer)
1384 WINPR_ASSERT(buffer);
1386 if (!Stream_SafeSeek(buffer, 8))
1394 static BOOL rts_version_command_write(
wStream* buffer)
1396 WINPR_ASSERT(buffer);
1398 if (!Stream_EnsureRemainingCapacity((buffer), 8))
1401 Stream_Write_UINT32(buffer, RTS_CMD_VERSION);
1402 Stream_Write_UINT32(buffer, 1);
1407 static BOOL rts_empty_command_write(
wStream* s)
1411 if (!Stream_EnsureRemainingCapacity(s, 8))
1414 Stream_Write_UINT32(s, RTS_CMD_EMPTY);
1419 static BOOL rts_padding_command_read(
wStream* s,
size_t* length, BOOL silent)
1421 UINT32 ConformanceCount = 0;
1423 WINPR_ASSERT(length);
1424 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1426 Stream_Read_UINT32(s, ConformanceCount);
1427 *length = ConformanceCount + 4;
1431 static BOOL rts_client_address_command_read(
wStream* s,
size_t* length, BOOL silent)
1433 UINT32 AddressType = 0;
1436 WINPR_ASSERT(length);
1438 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
1440 Stream_Read_UINT32(s, AddressType);
1442 if (AddressType == 0)
1446 *length = 4 + 4 + 12;
1452 *length = 4 + 16 + 12;
1457 static BOOL rts_association_group_id_command_write(
wStream* s,
const BYTE* AssociationGroupId)
1461 if (!Stream_EnsureRemainingCapacity(s, 20))
1464 Stream_Write_UINT32(s, RTS_CMD_ASSOCIATION_GROUP_ID);
1465 Stream_Write(s, AssociationGroupId, 16);
1470 static int rts_destination_command_read(rdpRpc* rpc,
wStream* buffer, UINT32* Destination)
1474 WINPR_ASSERT(buffer);
1476 if (!Stream_CheckAndLogRequiredLength(TAG, buffer, 4))
1478 Stream_Read_UINT32(buffer, val);
1485 static BOOL rts_destination_command_write(
wStream* s, UINT32 Destination)
1489 if (!Stream_EnsureRemainingCapacity(s, 8))
1492 Stream_Write_UINT32(s, RTS_CMD_DESTINATION);
1493 Stream_Write_UINT32(s, Destination);
1498 void rts_generate_cookie(BYTE* cookie)
1500 WINPR_ASSERT(cookie);
1501 winpr_RAND(cookie, 16);
1504 static BOOL rts_send_buffer(
RpcChannel* channel,
wStream* s,
size_t frag_length)
1506 BOOL status = FALSE;
1509 WINPR_ASSERT(channel);
1512 Stream_SealLength(s);
1515 if (Stream_Length(s) != frag_length)
1518 rc = rpc_channel_write(channel, Stream_Buffer(s), Stream_Length(s));
1521 if ((
size_t)rc != Stream_Length(s))
1530 BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc)
1532 BOOL status = FALSE;
1535 UINT32 ReceiveWindowSize = 0;
1536 BYTE* OUTChannelCookie = NULL;
1537 BYTE* VirtualConnectionCookie = NULL;
1543 connection = rpc->VirtualConnection;
1544 WINPR_ASSERT(connection);
1546 outChannel = connection->DefaultOutChannel;
1547 WINPR_ASSERT(outChannel);
1549 header.header.frag_length = 76;
1550 header.Flags = RTS_FLAG_NONE;
1551 header.NumberOfCommands = 4;
1553 WLog_DBG(TAG,
"Sending CONN/A1 RTS PDU");
1554 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1555 OUTChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1556 ReceiveWindowSize = outChannel->ReceiveWindow;
1558 buffer = Stream_New(NULL, header.header.frag_length);
1563 if (!rts_write_pdu_header(buffer, &header))
1565 status = rts_version_command_write(buffer);
1568 status = rts_cookie_command_write(
1569 buffer, VirtualConnectionCookie);
1572 status = rts_cookie_command_write(buffer, OUTChannelCookie);
1575 status = rts_receive_window_size_command_write(
1576 buffer, ReceiveWindowSize);
1579 status = rts_send_buffer(&outChannel->common, buffer, header.header.frag_length);
1581 Stream_Free(buffer, TRUE);
1585 BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc,
wStream* buffer)
1588 UINT64 ConnectionTimeout = 0;
1590 if (!Stream_SafeSeek(buffer, 20))
1593 rc = rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout);
1594 if (!rc || (ConnectionTimeout > UINT32_MAX))
1597 WLog_DBG(TAG,
"Receiving CONN/A3 RTS PDU: ConnectionTimeout: %" PRIu64
"", ConnectionTimeout);
1600 WINPR_ASSERT(rpc->VirtualConnection);
1601 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1603 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout =
1604 (UINT32)ConnectionTimeout;
1610 BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc)
1612 BOOL status = FALSE;
1615 BYTE* INChannelCookie = NULL;
1616 BYTE* AssociationGroupId = NULL;
1617 BYTE* VirtualConnectionCookie = NULL;
1623 connection = rpc->VirtualConnection;
1624 WINPR_ASSERT(connection);
1626 inChannel = connection->DefaultInChannel;
1627 WINPR_ASSERT(inChannel);
1629 header.header.frag_length = 104;
1630 header.Flags = RTS_FLAG_NONE;
1631 header.NumberOfCommands = 6;
1633 WLog_DBG(TAG,
"Sending CONN/B1 RTS PDU");
1635 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
1636 INChannelCookie = (BYTE*)&(inChannel->common.Cookie);
1637 AssociationGroupId = (BYTE*)&(connection->AssociationGroupId);
1638 buffer = Stream_New(NULL, header.header.frag_length);
1642 if (!rts_write_pdu_header(buffer, &header))
1644 if (!rts_version_command_write(buffer))
1646 if (!rts_cookie_command_write(buffer,
1647 VirtualConnectionCookie))
1649 if (!rts_cookie_command_write(buffer, INChannelCookie))
1651 if (!rts_channel_lifetime_command_write(buffer,
1652 rpc->ChannelLifetime))
1654 if (!rts_client_keepalive_command_write(buffer,
1655 rpc->KeepAliveInterval))
1657 if (!rts_association_group_id_command_write(
1658 buffer, AssociationGroupId))
1660 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1662 Stream_Free(buffer, TRUE);
1668 BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc,
wStream* buffer)
1671 UINT64 ReceiveWindowSize = 0;
1672 UINT64 ConnectionTimeout = 0;
1675 WINPR_ASSERT(buffer);
1677 if (!Stream_SafeSeek(buffer, 20))
1680 rc = rts_version_command_read(rpc, buffer);
1683 rc = rts_receive_window_size_command_read(rpc, buffer, &ReceiveWindowSize);
1684 if (!rc || (ReceiveWindowSize > UINT32_MAX))
1686 rc = rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout);
1687 if (!rc || (ConnectionTimeout > UINT32_MAX))
1691 "Receiving CONN/C2 RTS PDU: ConnectionTimeout: %" PRIu64
" ReceiveWindowSize: %" PRIu64
1693 ConnectionTimeout, ReceiveWindowSize);
1696 WINPR_ASSERT(rpc->VirtualConnection);
1697 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1699 rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout =
1700 (UINT32)ConnectionTimeout;
1701 rpc->VirtualConnection->DefaultInChannel->PeerReceiveWindow = (UINT32)ReceiveWindowSize;
1707 BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc)
1709 BOOL status = FALSE;
1712 UINT32 BytesReceived = 0;
1713 UINT32 AvailableWindow = 0;
1714 BYTE* ChannelCookie = NULL;
1721 connection = rpc->VirtualConnection;
1722 WINPR_ASSERT(connection);
1724 inChannel = connection->DefaultInChannel;
1725 WINPR_ASSERT(inChannel);
1727 outChannel = connection->DefaultOutChannel;
1728 WINPR_ASSERT(outChannel);
1730 header.header.frag_length = 56;
1731 header.Flags = RTS_FLAG_OTHER_CMD;
1732 header.NumberOfCommands = 2;
1734 WLog_DBG(TAG,
"Sending FlowControlAck RTS PDU");
1736 BytesReceived = outChannel->BytesReceived;
1737 AvailableWindow = outChannel->AvailableWindowAdvertised;
1738 ChannelCookie = (BYTE*)&(outChannel->common.Cookie);
1739 outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
1740 buffer = Stream_New(NULL, header.header.frag_length);
1745 if (!rts_write_pdu_header(buffer, &header))
1747 if (!rts_destination_command_write(buffer, FDOutProxy))
1751 if (!rts_flow_control_ack_command_write(buffer, BytesReceived, AvailableWindow, ChannelCookie))
1754 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1756 Stream_Free(buffer, TRUE);
1760 static int rts_recv_flow_control_ack_pdu(rdpRpc* rpc,
wStream* buffer)
1763 UINT32 BytesReceived = 0;
1764 UINT32 AvailableWindow = 0;
1765 BYTE ChannelCookie[16] = { 0 };
1767 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1768 (BYTE*)&ChannelCookie);
1772 "Receiving FlowControlAck RTS PDU: BytesReceived: %" PRIu32
1773 " AvailableWindow: %" PRIu32
"",
1774 BytesReceived, AvailableWindow);
1776 WINPR_ASSERT(rpc->VirtualConnection);
1777 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1779 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1780 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1784 static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc,
wStream* buffer)
1787 UINT32 Destination = 0;
1788 UINT32 BytesReceived = 0;
1789 UINT32 AvailableWindow = 0;
1790 BYTE ChannelCookie[16] = { 0 };
1808 int rc = rts_destination_command_read(rpc, buffer, &Command);
1812 if (Command != RTS_CMD_DESTINATION)
1814 char buffer1[64] = { 0 };
1815 char buffer2[64] = { 0 };
1816 WLog_Print(rpc->log, WLOG_ERROR,
"got command %s, expected %s",
1817 rts_command_to_string(Command, buffer1,
sizeof(buffer1)),
1818 rts_command_to_string(RTS_CMD_DESTINATION, buffer2,
sizeof(buffer2)));
1822 rc = rts_destination_command_read(rpc, buffer, &Destination);
1826 switch (Destination)
1837 WLog_Print(rpc->log, WLOG_ERROR,
1838 "got destination %" PRIu32
1839 ", expected one of [FDClient[0]|FDInProxy[1]|FDServer[2]|FDOutProxy[3]",
1844 rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow,
1850 "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %" PRIu32
1851 " AvailableWindow: %" PRIu32
"",
1852 BytesReceived, AvailableWindow);
1854 WINPR_ASSERT(rpc->VirtualConnection);
1855 WINPR_ASSERT(rpc->VirtualConnection->DefaultInChannel);
1856 rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
1857 AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
1861 BOOL rts_recv_ping_pdu(rdpRpc* rpc,
wStream* s)
1867 WINPR_ASSERT(rpc->auth);
1870 if (!rts_read_pdu_header(s, &header))
1874 if (header.common.ptype != PTYPE_RTS)
1876 WLog_Print(rpc->log, WLOG_ERROR,
"received invalid ping PDU, type is 0x%" PRIx32,
1877 header.common.ptype);
1880 if (header.rts.Flags != RTS_FLAG_PING)
1882 WLog_Print(rpc->log, WLOG_ERROR,
"received unexpected ping PDU::Flags 0x%" PRIx32,
1887 rts_free_pdu_header(&header, FALSE);
1891 static int rts_send_ping_pdu(rdpRpc* rpc)
1893 BOOL status = FALSE;
1899 WINPR_ASSERT(rpc->VirtualConnection);
1901 inChannel = rpc->VirtualConnection->DefaultInChannel;
1902 WINPR_ASSERT(inChannel);
1904 header.header.frag_length = 20;
1905 header.Flags = RTS_FLAG_PING;
1906 header.NumberOfCommands = 0;
1908 WLog_DBG(TAG,
"Sending Ping RTS PDU");
1909 buffer = Stream_New(NULL, header.header.frag_length);
1914 if (!rts_write_pdu_header(buffer, &header))
1916 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
1918 Stream_Free(buffer, TRUE);
1919 return (status) ? 1 : -1;
1922 BOOL rts_command_length(UINT32 CommandType,
wStream* s,
size_t* length, BOOL silent)
1925 size_t CommandLength = 0;
1929 switch (CommandType)
1931 case RTS_CMD_RECEIVE_WINDOW_SIZE:
1932 CommandLength = RTS_CMD_RECEIVE_WINDOW_SIZE_LENGTH;
1935 case RTS_CMD_FLOW_CONTROL_ACK:
1936 CommandLength = RTS_CMD_FLOW_CONTROL_ACK_LENGTH;
1939 case RTS_CMD_CONNECTION_TIMEOUT:
1940 CommandLength = RTS_CMD_CONNECTION_TIMEOUT_LENGTH;
1943 case RTS_CMD_COOKIE:
1944 CommandLength = RTS_CMD_COOKIE_LENGTH;
1947 case RTS_CMD_CHANNEL_LIFETIME:
1948 CommandLength = RTS_CMD_CHANNEL_LIFETIME_LENGTH;
1951 case RTS_CMD_CLIENT_KEEPALIVE:
1952 CommandLength = RTS_CMD_CLIENT_KEEPALIVE_LENGTH;
1955 case RTS_CMD_VERSION:
1956 CommandLength = RTS_CMD_VERSION_LENGTH;
1960 CommandLength = RTS_CMD_EMPTY_LENGTH;
1963 case RTS_CMD_PADDING:
1964 if (!rts_padding_command_read(s, &padding, silent))
1968 case RTS_CMD_NEGATIVE_ANCE:
1969 CommandLength = RTS_CMD_NEGATIVE_ANCE_LENGTH;
1973 CommandLength = RTS_CMD_ANCE_LENGTH;
1976 case RTS_CMD_CLIENT_ADDRESS:
1977 if (!rts_client_address_command_read(s, &CommandLength, silent))
1981 case RTS_CMD_ASSOCIATION_GROUP_ID:
1982 CommandLength = RTS_CMD_ASSOCIATION_GROUP_ID_LENGTH;
1985 case RTS_CMD_DESTINATION:
1986 CommandLength = RTS_CMD_DESTINATION_LENGTH;
1989 case RTS_CMD_PING_TRAFFIC_SENT_NOTIFY:
1990 CommandLength = RTS_CMD_PING_TRAFFIC_SENT_NOTIFY_LENGTH;
1994 WLog_ERR(TAG,
"Error: Unknown RTS Command Type: 0x%" PRIx32
"", CommandType);
1998 CommandLength += padding;
1999 if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, CommandLength, silent))
2003 *length = CommandLength;
2007 static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
2009 BOOL status = FALSE;
2012 BYTE* SuccessorChannelCookie = NULL;
2017 WINPR_ASSERT(rpc->VirtualConnection);
2019 inChannel = rpc->VirtualConnection->DefaultInChannel;
2020 WINPR_ASSERT(inChannel);
2022 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2023 WINPR_ASSERT(nextOutChannel);
2025 header.header.frag_length = 56;
2026 header.Flags = RTS_FLAG_OUT_CHANNEL;
2027 header.NumberOfCommands = 3;
2029 WLog_DBG(TAG,
"Sending OUT_R2/A7 RTS PDU");
2031 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2032 buffer = Stream_New(NULL, header.header.frag_length);
2037 if (!rts_write_pdu_header(buffer, &header))
2039 if (!rts_destination_command_write(buffer, FDServer))
2041 if (!rts_cookie_command_write(buffer,
2042 SuccessorChannelCookie))
2044 if (!rts_version_command_write(buffer))
2046 status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length);
2048 Stream_Free(buffer, TRUE);
2049 return (status) ? 1 : -1;
2052 static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc)
2054 BOOL status = FALSE;
2060 WINPR_ASSERT(rpc->VirtualConnection);
2062 nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
2063 WINPR_ASSERT(nextOutChannel);
2065 header.header.frag_length = 24;
2066 header.Flags = RTS_FLAG_PING;
2067 header.NumberOfCommands = 1;
2069 WLog_DBG(TAG,
"Sending OUT_R2/C1 RTS PDU");
2070 buffer = Stream_New(NULL, header.header.frag_length);
2075 if (!rts_write_pdu_header(buffer, &header))
2078 if (!rts_empty_command_write(buffer))
2080 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2082 Stream_Free(buffer, TRUE);
2083 return (status) ? 1 : -1;
2086 BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
2088 BOOL status = FALSE;
2091 UINT32 ReceiveWindowSize = 0;
2092 BYTE* VirtualConnectionCookie = NULL;
2093 BYTE* PredecessorChannelCookie = NULL;
2094 BYTE* SuccessorChannelCookie = NULL;
2101 connection = rpc->VirtualConnection;
2102 WINPR_ASSERT(connection);
2104 outChannel = connection->DefaultOutChannel;
2105 WINPR_ASSERT(outChannel);
2107 nextOutChannel = connection->NonDefaultOutChannel;
2108 WINPR_ASSERT(nextOutChannel);
2110 header.header.frag_length = 96;
2111 header.Flags = RTS_FLAG_RECYCLE_CHANNEL;
2112 header.NumberOfCommands = 5;
2114 WLog_DBG(TAG,
"Sending OUT_R1/A3 RTS PDU");
2116 VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
2117 PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie);
2118 SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
2119 ReceiveWindowSize = outChannel->ReceiveWindow;
2120 buffer = Stream_New(NULL, header.header.frag_length);
2125 if (!rts_write_pdu_header(buffer, &header))
2127 if (!rts_version_command_write(buffer))
2129 if (!rts_cookie_command_write(buffer,
2130 VirtualConnectionCookie))
2132 if (!rts_cookie_command_write(
2133 buffer, PredecessorChannelCookie))
2135 if (!rts_cookie_command_write(buffer,
2136 SuccessorChannelCookie))
2138 if (!rts_receive_window_size_command_write(buffer,
2142 status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length);
2144 Stream_Free(buffer, TRUE);
2148 static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc,
wStream* buffer)
2151 UINT32 Destination = 0;
2154 WINPR_ASSERT(buffer);
2156 connection = rpc->VirtualConnection;
2157 WINPR_ASSERT(connection);
2159 WLog_DBG(TAG,
"Receiving OUT R1/A2 RTS PDU");
2161 status = rts_destination_command_read(rpc, buffer, &Destination);
2165 connection->NonDefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
2167 if (!connection->NonDefaultOutChannel)
2170 status = rpc_out_channel_replacement_connect(connection->NonDefaultOutChannel, 5000);
2174 WLog_ERR(TAG,
"rpc_out_channel_replacement_connect failure");
2178 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2179 CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
2183 static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc,
wStream* buffer)
2189 WINPR_ASSERT(buffer);
2191 connection = rpc->VirtualConnection;
2192 WINPR_ASSERT(connection);
2194 WLog_DBG(TAG,
"Receiving OUT R2/A6 RTS PDU");
2195 status = rts_send_OUT_R2_C1_pdu(rpc);
2199 WLog_ERR(TAG,
"rts_send_OUT_R2_C1_pdu failure");
2203 status = rts_send_OUT_R2_A7_pdu(rpc);
2207 WLog_ERR(TAG,
"rts_send_OUT_R2_A7_pdu failure");
2211 rpc_out_channel_transition_to_state(connection->NonDefaultOutChannel,
2212 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2213 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2214 CLIENT_OUT_CHANNEL_STATE_OPENED_B3W);
2218 static int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc,
wStream* buffer)
2223 WINPR_ASSERT(buffer);
2225 connection = rpc->VirtualConnection;
2226 WINPR_ASSERT(connection);
2228 WLog_DBG(TAG,
"Receiving OUT R2/B3 RTS PDU");
2229 rpc_out_channel_transition_to_state(connection->DefaultOutChannel,
2230 CLIENT_OUT_CHANNEL_STATE_RECYCLED);
2236 BOOL status = FALSE;
2242 WINPR_ASSERT(buffer);
2243 WINPR_ASSERT(header);
2245 wLog* log = WLog_Get(TAG);
2247 const size_t total = Stream_Length(buffer);
2248 length = header->common.frag_length;
2251 WLog_Print(log, WLOG_ERROR,
"PDU length %" PRIuz
" does not match available data %" PRIuz,
2256 connection = rpc->VirtualConnection;
2260 WLog_Print(log, WLOG_ERROR,
"not connected, aborting");
2264 if (!rts_extract_pdu_signature(&signature, buffer, header))
2267 rts_print_pdu_signature(log, WLOG_TRACE, &signature);
2269 if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE,
sizeof(signature)) == 0)
2271 status = rts_recv_flow_control_ack_pdu(rpc, buffer);
2273 else if (memcmp(&signature, &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE,
2274 sizeof(signature)) == 0)
2276 status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer);
2278 else if (memcmp(&signature, &RTS_PDU_PING_SIGNATURE,
sizeof(signature)) == 0)
2280 status = rts_send_ping_pdu(rpc);
2284 if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
2286 if (memcmp(&signature, &RTS_PDU_OUT_R1_A2_SIGNATURE,
sizeof(signature)) == 0)
2288 status = rts_recv_OUT_R1_A2_pdu(rpc, buffer);
2291 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_A6W)
2293 if (memcmp(&signature, &RTS_PDU_OUT_R2_A6_SIGNATURE,
sizeof(signature)) == 0)
2295 status = rts_recv_OUT_R2_A6_pdu(rpc, buffer);
2298 else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_B3W)
2300 if (memcmp(&signature, &RTS_PDU_OUT_R2_B3_SIGNATURE,
sizeof(signature)) == 0)
2302 status = rts_recv_OUT_R2_B3_pdu(rpc, buffer);
2309 const UINT32 SignatureId = rts_identify_pdu_signature(&signature, NULL);
2310 WLog_Print(log, WLOG_ERROR,
"error parsing RTS PDU with signature id: 0x%08" PRIX32
"",
2312 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2315 const size_t rem = Stream_GetRemainingLength(buffer);
2318 WLog_Print(log, WLOG_ERROR,
"%" PRIuz
" bytes or %" PRIuz
" total not parsed, aborting",
2320 rts_print_pdu_signature(log, WLOG_ERROR, &signature);
2332 if (!rts_write_common_pdu_header(s, &auth->header))
2335 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT16)))
2338 Stream_Write_UINT16(s, auth->max_xmit_frag);
2339 Stream_Write_UINT16(s, auth->max_recv_frag);
2341 return rts_write_auth_verifier(s, &auth->auth_verifier, &auth->header);
2350 if (!rts_write_common_pdu_header(s, &bind->header))
2353 if (!Stream_EnsureRemainingCapacity(s, 8))
2356 Stream_Write_UINT16(s, bind->max_xmit_frag);
2357 Stream_Write_UINT16(s, bind->max_recv_frag);
2358 Stream_Write_UINT32(s, bind->assoc_group_id);
2360 if (!rts_write_context_list(s, &bind->p_context_elem))
2363 return rts_write_auth_verifier(s, &bind->auth_verifier, &bind->header);
2366 BOOL rts_conditional_check_and_log(
const char* tag,
wStream* s,
size_t size, BOOL silent,
2367 const char* fkt,
const char* file,
size_t line)
2371 const size_t rem = Stream_GetRemainingLength(s);
2377 return Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, size, 1,
"%s(%s:%" PRIuz
")", fkt,
2381 BOOL rts_conditional_safe_seek(
wStream* s,
size_t size, BOOL silent,
const char* fkt,
2382 const char* file,
size_t line)
2386 const size_t rem = Stream_GetRemainingLength(s);
2390 return Stream_SafeSeekEx(s, size, file, line, fkt);