22#include <freerdp/config.h>
24#include "../settings.h"
27#include <winpr/assert.h>
28#include <winpr/cast.h>
29#include <winpr/tchar.h>
30#include <winpr/synch.h>
31#include <winpr/dsparse.h>
32#include <winpr/crypto.h>
34#include <freerdp/log.h>
36#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
37#include <valgrind/memcheck.h>
42#include "../credssp_auth.h"
43#include "ncacn_http.h"
46#include "rpc_client.h"
51#define TAG FREERDP_TAG("core.gateway.rpc")
53static const char* PTYPE_STRINGS[] = {
"PTYPE_REQUEST",
"PTYPE_PING",
54 "PTYPE_RESPONSE",
"PTYPE_FAULT",
55 "PTYPE_WORKING",
"PTYPE_NOCALL",
56 "PTYPE_REJECT",
"PTYPE_ACK",
57 "PTYPE_CL_CANCEL",
"PTYPE_FACK",
58 "PTYPE_CANCEL_ACK",
"PTYPE_BIND",
59 "PTYPE_BIND_ACK",
"PTYPE_BIND_NAK",
60 "PTYPE_ALTER_CONTEXT",
"PTYPE_ALTER_CONTEXT_RESP",
61 "PTYPE_RPC_AUTH_3",
"PTYPE_SHUTDOWN",
62 "PTYPE_CO_CANCEL",
"PTYPE_ORPHANED",
65static const char* client_in_state_str(CLIENT_IN_CHANNEL_STATE state)
68 const char* str =
"CLIENT_IN_CHANNEL_STATE_UNKNOWN";
72 case CLIENT_IN_CHANNEL_STATE_INITIAL:
73 str =
"CLIENT_IN_CHANNEL_STATE_INITIAL";
76 case CLIENT_IN_CHANNEL_STATE_CONNECTED:
77 str =
"CLIENT_IN_CHANNEL_STATE_CONNECTED";
80 case CLIENT_IN_CHANNEL_STATE_SECURITY:
81 str =
"CLIENT_IN_CHANNEL_STATE_SECURITY";
84 case CLIENT_IN_CHANNEL_STATE_NEGOTIATED:
85 str =
"CLIENT_IN_CHANNEL_STATE_NEGOTIATED";
88 case CLIENT_IN_CHANNEL_STATE_OPENED:
89 str =
"CLIENT_IN_CHANNEL_STATE_OPENED";
92 case CLIENT_IN_CHANNEL_STATE_OPENED_A4W:
93 str =
"CLIENT_IN_CHANNEL_STATE_OPENED_A4W";
96 case CLIENT_IN_CHANNEL_STATE_FINAL:
97 str =
"CLIENT_IN_CHANNEL_STATE_FINAL";
105static const char* client_out_state_str(CLIENT_OUT_CHANNEL_STATE state)
108 const char* str =
"CLIENT_OUT_CHANNEL_STATE_UNKNOWN";
112 case CLIENT_OUT_CHANNEL_STATE_INITIAL:
113 str =
"CLIENT_OUT_CHANNEL_STATE_INITIAL";
116 case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
117 str =
"CLIENT_OUT_CHANNEL_STATE_CONNECTED";
120 case CLIENT_OUT_CHANNEL_STATE_SECURITY:
121 str =
"CLIENT_OUT_CHANNEL_STATE_SECURITY";
124 case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
125 str =
"CLIENT_OUT_CHANNEL_STATE_NEGOTIATED";
128 case CLIENT_OUT_CHANNEL_STATE_OPENED:
129 str =
"CLIENT_OUT_CHANNEL_STATE_OPENED";
132 case CLIENT_OUT_CHANNEL_STATE_OPENED_A6W:
133 str =
"CLIENT_OUT_CHANNEL_STATE_OPENED_A6W";
136 case CLIENT_OUT_CHANNEL_STATE_OPENED_A10W:
137 str =
"CLIENT_OUT_CHANNEL_STATE_OPENED_A10W";
140 case CLIENT_OUT_CHANNEL_STATE_OPENED_B3W:
141 str =
"CLIENT_OUT_CHANNEL_STATE_OPENED_B3W";
144 case CLIENT_OUT_CHANNEL_STATE_RECYCLED:
145 str =
"CLIENT_OUT_CHANNEL_STATE_RECYCLED";
148 case CLIENT_OUT_CHANNEL_STATE_FINAL:
149 str =
"CLIENT_OUT_CHANNEL_STATE_FINAL";
157const char* rpc_vc_state_str(VIRTUAL_CONNECTION_STATE state)
160 const char* str =
"VIRTUAL_CONNECTION_STATE_UNKNOWN";
164 case VIRTUAL_CONNECTION_STATE_INITIAL:
165 str =
"VIRTUAL_CONNECTION_STATE_INITIAL";
168 case VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT:
169 str =
"VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT";
172 case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
173 str =
"VIRTUAL_CONNECTION_STATE_WAIT_A3W";
176 case VIRTUAL_CONNECTION_STATE_WAIT_C2:
177 str =
"VIRTUAL_CONNECTION_STATE_WAIT_C2";
180 case VIRTUAL_CONNECTION_STATE_OPENED:
181 str =
"VIRTUAL_CONNECTION_STATE_OPENED";
184 case VIRTUAL_CONNECTION_STATE_FINAL:
185 str =
"VIRTUAL_CONNECTION_STATE_FINAL";
220void rpc_pdu_header_print(wLog* log,
const rpcconn_hdr_t* header)
222 WINPR_ASSERT(header);
224 WLog_Print(log, WLOG_INFO,
"rpc_vers: %" PRIu8
"", header->common.rpc_vers);
225 WLog_Print(log, WLOG_INFO,
"rpc_vers_minor: %" PRIu8
"", header->common.rpc_vers_minor);
227 if (header->common.ptype > PTYPE_RTS)
228 WLog_Print(log, WLOG_INFO,
"ptype: %s (%" PRIu8
")",
"PTYPE_UNKNOWN", header->common.ptype);
230 WLog_Print(log, WLOG_INFO,
"ptype: %s (%" PRIu8
")", PTYPE_STRINGS[header->common.ptype],
231 header->common.ptype);
233 WLog_Print(log, WLOG_INFO,
"pfc_flags (0x%02" PRIX8
") = {", header->common.pfc_flags);
235 if (header->common.pfc_flags & PFC_FIRST_FRAG)
236 WLog_Print(log, WLOG_INFO,
" PFC_FIRST_FRAG");
238 if (header->common.pfc_flags & PFC_LAST_FRAG)
239 WLog_Print(log, WLOG_INFO,
" PFC_LAST_FRAG");
241 if (header->common.pfc_flags & PFC_PENDING_CANCEL)
242 WLog_Print(log, WLOG_INFO,
" PFC_PENDING_CANCEL");
244 if (header->common.pfc_flags & PFC_RESERVED_1)
245 WLog_Print(log, WLOG_INFO,
" PFC_RESERVED_1");
247 if (header->common.pfc_flags & PFC_CONC_MPX)
248 WLog_Print(log, WLOG_INFO,
" PFC_CONC_MPX");
250 if (header->common.pfc_flags & PFC_DID_NOT_EXECUTE)
251 WLog_Print(log, WLOG_INFO,
" PFC_DID_NOT_EXECUTE");
253 if (header->common.pfc_flags & PFC_OBJECT_UUID)
254 WLog_Print(log, WLOG_INFO,
" PFC_OBJECT_UUID");
256 WLog_Print(log, WLOG_INFO,
" }");
257 WLog_Print(log, WLOG_INFO,
258 "packed_drep[4]: %02" PRIX8
" %02" PRIX8
" %02" PRIX8
" %02" PRIX8
"",
259 header->common.packed_drep[0], header->common.packed_drep[1],
260 header->common.packed_drep[2], header->common.packed_drep[3]);
261 WLog_Print(log, WLOG_INFO,
"frag_length: %" PRIu16
"", header->common.frag_length);
262 WLog_Print(log, WLOG_INFO,
"auth_length: %" PRIu16
"", header->common.auth_length);
263 WLog_Print(log, WLOG_INFO,
"call_id: %" PRIu32
"", header->common.call_id);
265 if (header->common.ptype == PTYPE_RESPONSE)
267 WLog_Print(log, WLOG_INFO,
"alloc_hint: %" PRIu32
"", header->response.alloc_hint);
268 WLog_Print(log, WLOG_INFO,
"p_cont_id: %" PRIu16
"", header->response.p_cont_id);
269 WLog_Print(log, WLOG_INFO,
"cancel_count: %" PRIu8
"", header->response.cancel_count);
270 WLog_Print(log, WLOG_INFO,
"reserved: %" PRIu8
"", header->response.reserved);
279 header.rpc_vers = rpc->rpc_vers;
280 header.rpc_vers_minor = rpc->rpc_vers_minor;
281 header.packed_drep[0] = rpc->packed_drep[0];
282 header.packed_drep[1] = rpc->packed_drep[1];
283 header.packed_drep[2] = rpc->packed_drep[2];
284 header.packed_drep[3] = rpc->packed_drep[3];
288size_t rpc_offset_align(
size_t* offset,
size_t alignment)
292 *offset = (*offset + alignment - 1) & ~(alignment - 1);
297size_t rpc_offset_pad(
size_t* offset,
size_t pad)
378BOOL rpc_get_stub_data_info(rdpRpc* rpc,
const rpcconn_hdr_t* header,
size_t* poffset,
384 UINT32 frag_length = 0;
385 UINT32 auth_length = 0;
386 UINT32 auth_pad_length = 0;
387 UINT32 sec_trailer_offset = 0;
388 const rpc_sec_trailer* sec_trailer = NULL;
391 WINPR_ASSERT(header);
392 WINPR_ASSERT(poffset);
393 WINPR_ASSERT(length);
395 offset = RPC_COMMON_FIELDS_LENGTH;
397 switch (header->common.ptype)
401 rpc_offset_align(&offset, 8);
402 sec_trailer = &header->response.auth_verifier;
407 rpc_offset_align(&offset, 8);
408 sec_trailer = &header->request.auth_verifier;
416 WLog_Print(rpc->log, WLOG_ERROR,
"Unknown PTYPE: 0x%02" PRIX8
"", header->common.ptype);
420 frag_length = header->common.frag_length;
421 auth_length = header->common.auth_length;
427 used = offset + auth_length + 8ull;
430 auth_pad_length = sec_trailer->auth_pad_length;
431 used += sec_trailer->auth_pad_length;
434 if (frag_length < used)
440 sec_trailer_offset = frag_length - auth_length - 8;
448 if ((frag_length - (sec_trailer_offset + 8)) != auth_length)
450 WLog_Print(rpc->log, WLOG_ERROR,
451 "invalid auth_length: actual: %" PRIu32
", expected: %" PRIu32
"", auth_length,
452 (frag_length - (sec_trailer_offset + 8)));
455 *length = sec_trailer_offset - auth_pad_length - offset;
466 if (!channel || (length > INT32_MAX))
470 status = BIO_read(channel->tls->bio, Stream_Pointer(s), (INT32)length);
474 Stream_Seek(s, (
size_t)status);
478 if (BIO_should_retry(channel->tls->bio))
481 WLog_Print(channel->rpc->log, WLOG_ERROR,
"rpc_channel_read: Out of retries");
485SSIZE_T rpc_channel_write_int(
RpcChannel* channel,
const BYTE* data,
size_t length,
486 const char* file,
size_t line,
const char* fkt)
488 WINPR_ASSERT(channel);
489 WINPR_ASSERT(channel->rpc);
491 const DWORD level = WLOG_TRACE;
492 if (WLog_IsLevelActive(channel->rpc->log, level))
494 WLog_PrintMessage(channel->rpc->log, WLOG_MESSAGE_TEXT, level, line, file, fkt,
495 "Sending [%s] %" PRIuz
" bytes", fkt, length);
498 return freerdp_tls_write_all(channel->tls, data, length);
501BOOL rpc_in_channel_transition_to_state(
RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
506 inChannel->State = state;
507 WLog_Print(inChannel->common.rpc->log, WLOG_DEBUG,
"%s", client_in_state_str(state));
514 HttpContext* http = NULL;
515 rdpSettings* settings = NULL;
518 if (!client || !channel || !inout || !client->context || !client->context->settings)
521 settings = client->context->settings;
522 channel->auth = credssp_auth_new(client->context);
523 rts_generate_cookie((BYTE*)&channel->Cookie);
524 channel->client = client;
529 channel->http = http_context_new();
534 http = channel->http;
537 if (!http_context_set_pragma(http,
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"))
542 char* strguid = NULL;
543 RPC_STATUS rpcStatus = UuidToStringA(guid, &strguid);
545 if (rpcStatus != RPC_S_OK)
548 const BOOL rc = http_context_append_pragma(http,
"SessionId=%s", strguid);
549 RpcStringFreeA(&strguid);
555 if (!http_context_append_pragma(http,
"MinConnTimeout=%" PRIu32, timeout))
559 if (!http_context_set_rdg_correlation_id(http, guid) ||
560 !http_context_set_rdg_connection_id(http, guid))
565 if (!http_context_set_method(http, inout) ||
566 !http_context_set_uri(http,
"/rpc/rpcproxy.dll?localhost:3388") ||
567 !http_context_set_accept(http,
"application/rpc") ||
568 !http_context_set_cache_control(http,
"no-cache") ||
569 !http_context_set_connection(http,
"Keep-Alive") ||
570 !http_context_set_user_agent(http,
"MSRPC") ||
571 !http_context_set_host(http, settings->GatewayHostname))
577static int rpc_in_channel_init(rdpRpc* rpc,
RpcInChannel* inChannel,
const GUID* guid)
580 WINPR_ASSERT(inChannel);
582 inChannel->common.rpc = rpc;
583 inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL;
584 inChannel->BytesSent = 0;
585 inChannel->SenderAvailableWindow = rpc->ReceiveWindow;
586 inChannel->PingOriginator.ConnectionTimeout = 30;
587 inChannel->PingOriginator.KeepAliveInterval = 0;
589 if (rpc_channel_rpch_init(rpc->client, &inChannel->common,
"RPC_IN_DATA", guid) < 0)
595static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc,
const GUID* guid)
601 rpc_in_channel_init(rpc, inChannel, guid);
612 credssp_auth_free(channel->auth);
613 http_context_free(channel->http);
614 freerdp_tls_free(channel->tls);
618BOOL rpc_out_channel_transition_to_state(
RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
623 outChannel->State = state;
624 WLog_Print(outChannel->common.rpc->log, WLOG_DEBUG,
"%s", client_out_state_str(state));
628static int rpc_out_channel_init(rdpRpc* rpc,
RpcOutChannel* outChannel,
const GUID* guid)
631 WINPR_ASSERT(outChannel);
633 outChannel->common.rpc = rpc;
634 outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
635 outChannel->BytesReceived = 0;
636 outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
637 outChannel->ReceiveWindow = rpc->ReceiveWindow;
638 outChannel->ReceiveWindowSize = rpc->ReceiveWindow;
639 outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
641 if (rpc_channel_rpch_init(rpc->client, &outChannel->common,
"RPC_OUT_DATA", guid) < 0)
647RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc,
const GUID* guid)
653 rpc_out_channel_init(rpc, outChannel, guid);
660 VIRTUAL_CONNECTION_STATE state)
666 connection->State = state;
667 WLog_Print(rpc->log, WLOG_DEBUG,
"%s", rpc_vc_state_str(state));
676 if (connection->DefaultInChannel)
677 rpc_channel_free(&connection->DefaultInChannel->common);
678 if (connection->NonDefaultInChannel)
679 rpc_channel_free(&connection->NonDefaultInChannel->common);
680 if (connection->DefaultOutChannel)
681 rpc_channel_free(&connection->DefaultOutChannel->common);
682 if (connection->NonDefaultOutChannel)
683 rpc_channel_free(&connection->NonDefaultOutChannel->common);
697 rts_generate_cookie((BYTE*)&(connection->Cookie));
698 rts_generate_cookie((BYTE*)&(connection->AssociationGroupId));
699 connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
701 connection->DefaultInChannel = rpc_in_channel_new(rpc, &connection->Cookie);
703 if (!connection->DefaultInChannel)
706 connection->DefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
708 if (!connection->DefaultOutChannel)
713 rpc_virtual_connection_free(connection);
717static BOOL rpc_channel_tls_connect(
RpcChannel* channel, UINT32 timeout)
719 if (!channel || !channel->client || !channel->client->context ||
720 !channel->client->context->settings)
723 rdpContext* context = channel->client->context;
724 WINPR_ASSERT(context);
726 rdpSettings* settings = context->settings;
727 WINPR_ASSERT(settings);
732 rdpTransport* transport = freerdp_get_transport(context);
734 transport_connect_layer(transport, channel->client->host, channel->client->port, timeout);
739 BIO* layerBio = BIO_new(BIO_s_transport_layer());
742 transport_layer_free(layer);
745 BIO_set_data(layerBio, layer);
747 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
750 BIO_free_all(layerBio);
754 bufferedBio = BIO_push(bufferedBio, layerBio);
756 if (!BIO_set_nonblock(bufferedBio, TRUE))
758 BIO_free_all(bufferedBio);
762 if (channel->client->isProxy)
764 WINPR_ASSERT(settings->GatewayPort <= UINT16_MAX);
765 if (!proxy_connect(context, bufferedBio, proxyUsername, proxyPassword,
766 settings->GatewayHostname, (UINT16)settings->GatewayPort))
768 BIO_free_all(bufferedBio);
773 channel->bio = bufferedBio;
774 rdpTls* tls = channel->tls = freerdp_tls_new(context);
779 tls->hostname = settings->GatewayHostname;
780 tls->port = WINPR_ASSERTING_INT_CAST(int32_t, MIN(UINT16_MAX, settings->GatewayPort));
781 tls->isGatewayTransport = TRUE;
782 int tlsStatus = freerdp_tls_connect(tls, bufferedBio);
788 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
792 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
801static int rpc_in_channel_connect(
RpcInChannel* inChannel, UINT32 timeout)
803 rdpContext* context = NULL;
805 if (!inChannel || !inChannel->common.client || !inChannel->common.client->context)
808 context = inChannel->common.client->context;
812 if (!rpc_channel_tls_connect(&inChannel->common, timeout))
815 rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);
817 if (!rpc_ncacn_http_auth_init(context, &inChannel->common))
822 if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
824 WLog_Print(inChannel->common.rpc->log, WLOG_ERROR,
825 "rpc_ncacn_http_send_in_channel_request failure");
829 if (!rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY))
835static int rpc_out_channel_connect(
RpcOutChannel* outChannel, UINT32 timeout)
837 rdpContext* context = NULL;
839 if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
842 context = outChannel->common.client->context;
846 if (!rpc_channel_tls_connect(&outChannel->common, timeout))
849 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
851 if (!rpc_ncacn_http_auth_init(context, &outChannel->common))
856 if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
858 WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
859 "rpc_ncacn_http_send_out_channel_request failure");
863 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
867int rpc_out_channel_replacement_connect(
RpcOutChannel* outChannel, uint32_t timeout)
869 rdpContext* context = NULL;
871 if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
874 context = outChannel->common.client->context;
878 if (!rpc_channel_tls_connect(&outChannel->common, timeout))
881 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
883 if (!rpc_ncacn_http_auth_init(context, (
RpcChannel*)outChannel))
888 if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, TRUE))
890 WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
891 "rpc_ncacn_http_send_out_channel_request failure");
895 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
899BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout)
904 rpc->VirtualConnection = rpc_virtual_connection_new(rpc);
906 if (!rpc->VirtualConnection)
909 connection = rpc->VirtualConnection;
910 inChannel = connection->DefaultInChannel;
911 outChannel = connection->DefaultOutChannel;
912 rpc_virtual_connection_transition_to_state(rpc, connection, VIRTUAL_CONNECTION_STATE_INITIAL);
914 if (rpc_in_channel_connect(inChannel, timeout) < 0)
917 if (rpc_out_channel_connect(outChannel, timeout) < 0)
923rdpRpc* rpc_new(rdpTransport* transport)
925 rdpContext* context = transport_get_context(transport);
928 WINPR_ASSERT(context);
930 rpc = (rdpRpc*)calloc(1,
sizeof(rdpRpc));
935 rpc->log = WLog_Get(TAG);
936 rpc->State = RPC_CLIENT_STATE_INITIAL;
937 rpc->transport = transport;
939 rpc->auth = credssp_auth_new(context);
946 rpc->StubFragCount = 0;
948 rpc->rpc_vers_minor = 0;
950 rpc->packed_drep[0] = 0x10;
951 rpc->packed_drep[1] = 0x00;
952 rpc->packed_drep[2] = 0x00;
953 rpc->packed_drep[3] = 0x00;
954 rpc->max_xmit_frag = 0x0FF8;
955 rpc->max_recv_frag = 0x0FF8;
956 rpc->ReceiveWindow = 0x00010000;
957 rpc->ChannelLifetime = 0x40000000;
958 rpc->KeepAliveInterval = 300000;
959 rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
960 rpc->CurrentKeepAliveTime = 0;
962 rpc->client = rpc_client_new(context, rpc->max_recv_frag);
969 WINPR_PRAGMA_DIAG_PUSH
970 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
972 WINPR_PRAGMA_DIAG_POP
976void rpc_free(rdpRpc* rpc)
980 rpc_client_free(rpc->client);
981 credssp_auth_free(rpc->auth);
982 rpc_virtual_connection_free(rpc->VirtualConnection);
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.