22 #include <freerdp/config.h>
24 #include "../settings.h"
26 #include <winpr/crt.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"
45 #include "rpc_fault.h"
46 #include "rpc_client.h"
51 #define TAG FREERDP_TAG("core.gateway.rpc")
53 static 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",
65 static 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";
105 static 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";
157 const 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";
220 void 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];
288 size_t rpc_offset_align(
size_t* offset,
size_t alignment)
292 *offset = (*offset + alignment - 1) & ~(alignment - 1);
297 size_t rpc_offset_pad(
size_t* offset,
size_t pad)
378 BOOL 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");
485 SSIZE_T rpc_channel_write(
RpcChannel* channel,
const BYTE* data,
size_t length)
490 return freerdp_tls_write_all(channel->tls, data, length);
493 BOOL rpc_in_channel_transition_to_state(
RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
498 inChannel->State = state;
499 WLog_Print(inChannel->common.rpc->log, WLOG_DEBUG,
"%s", client_in_state_str(state));
503 static int rpc_channel_rpch_init(
RpcClient* client,
RpcChannel* channel,
const char* inout,
506 HttpContext* http = NULL;
507 rdpSettings* settings = NULL;
510 if (!client || !channel || !inout || !client->context || !client->context->settings)
513 settings = client->context->settings;
514 channel->auth = credssp_auth_new(client->context);
515 rts_generate_cookie((BYTE*)&channel->Cookie);
516 channel->client = client;
521 channel->http = http_context_new();
526 http = channel->http;
529 if (!http_context_set_pragma(http,
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"))
534 char* strguid = NULL;
535 RPC_STATUS rpcStatus = UuidToStringA(guid, &strguid);
537 if (rpcStatus != RPC_S_OK)
540 const BOOL rc = http_context_append_pragma(http,
"SessionId=%s", strguid);
541 RpcStringFreeA(&strguid);
547 if (!http_context_append_pragma(http,
"MinConnTimeout=%" PRIu32, timeout))
551 if (!http_context_set_rdg_correlation_id(http, guid) ||
552 !http_context_set_rdg_connection_id(http, guid))
557 if (!http_context_set_method(http, inout) ||
558 !http_context_set_uri(http,
"/rpc/rpcproxy.dll?localhost:3388") ||
559 !http_context_set_accept(http,
"application/rpc") ||
560 !http_context_set_cache_control(http,
"no-cache") ||
561 !http_context_set_connection(http,
"Keep-Alive") ||
562 !http_context_set_user_agent(http,
"MSRPC") ||
563 !http_context_set_host(http, settings->GatewayHostname))
569 static int rpc_in_channel_init(rdpRpc* rpc,
RpcInChannel* inChannel,
const GUID* guid)
572 WINPR_ASSERT(inChannel);
574 inChannel->common.rpc = rpc;
575 inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL;
576 inChannel->BytesSent = 0;
577 inChannel->SenderAvailableWindow = rpc->ReceiveWindow;
578 inChannel->PingOriginator.ConnectionTimeout = 30;
579 inChannel->PingOriginator.KeepAliveInterval = 0;
581 if (rpc_channel_rpch_init(rpc->client, &inChannel->common,
"RPC_IN_DATA", guid) < 0)
587 static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc,
const GUID* guid)
593 rpc_in_channel_init(rpc, inChannel, guid);
604 credssp_auth_free(channel->auth);
605 http_context_free(channel->http);
606 freerdp_tls_free(channel->tls);
610 BOOL rpc_out_channel_transition_to_state(
RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
615 outChannel->State = state;
616 WLog_Print(outChannel->common.rpc->log, WLOG_DEBUG,
"%s", client_out_state_str(state));
620 static int rpc_out_channel_init(rdpRpc* rpc,
RpcOutChannel* outChannel,
const GUID* guid)
623 WINPR_ASSERT(outChannel);
625 outChannel->common.rpc = rpc;
626 outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
627 outChannel->BytesReceived = 0;
628 outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
629 outChannel->ReceiveWindow = rpc->ReceiveWindow;
630 outChannel->ReceiveWindowSize = rpc->ReceiveWindow;
631 outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
633 if (rpc_channel_rpch_init(rpc->client, &outChannel->common,
"RPC_OUT_DATA", guid) < 0)
639 RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc,
const GUID* guid)
645 rpc_out_channel_init(rpc, outChannel, guid);
652 VIRTUAL_CONNECTION_STATE state)
658 connection->State = state;
659 WLog_Print(rpc->log, WLOG_DEBUG,
"%s", rpc_vc_state_str(state));
668 if (connection->DefaultInChannel)
669 rpc_channel_free(&connection->DefaultInChannel->common);
670 if (connection->NonDefaultInChannel)
671 rpc_channel_free(&connection->NonDefaultInChannel->common);
672 if (connection->DefaultOutChannel)
673 rpc_channel_free(&connection->DefaultOutChannel->common);
674 if (connection->NonDefaultOutChannel)
675 rpc_channel_free(&connection->NonDefaultOutChannel->common);
689 rts_generate_cookie((BYTE*)&(connection->Cookie));
690 rts_generate_cookie((BYTE*)&(connection->AssociationGroupId));
691 connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
693 connection->DefaultInChannel = rpc_in_channel_new(rpc, &connection->Cookie);
695 if (!connection->DefaultInChannel)
698 connection->DefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
700 if (!connection->DefaultOutChannel)
705 rpc_virtual_connection_free(connection);
709 static BOOL rpc_channel_tls_connect(
RpcChannel* channel, UINT32 timeout)
711 if (!channel || !channel->client || !channel->client->context ||
712 !channel->client->context->settings)
715 rdpContext* context = channel->client->context;
716 WINPR_ASSERT(context);
718 rdpSettings* settings = context->settings;
719 WINPR_ASSERT(settings);
724 rdpTransport* transport = freerdp_get_transport(context);
726 transport_connect_layer(transport, channel->client->host, channel->client->port, timeout);
731 BIO* layerBio = BIO_new(BIO_s_transport_layer());
734 transport_layer_free(layer);
737 BIO_set_data(layerBio, layer);
739 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
742 BIO_free_all(layerBio);
746 bufferedBio = BIO_push(bufferedBio, layerBio);
748 if (!BIO_set_nonblock(bufferedBio, TRUE))
750 BIO_free_all(bufferedBio);
754 if (channel->client->isProxy)
756 WINPR_ASSERT(settings->GatewayPort <= UINT16_MAX);
757 if (!proxy_connect(context, bufferedBio, proxyUsername, proxyPassword,
758 settings->GatewayHostname, (UINT16)settings->GatewayPort))
760 BIO_free_all(bufferedBio);
765 channel->bio = bufferedBio;
766 rdpTls* tls = channel->tls = freerdp_tls_new(context);
771 tls->hostname = settings->GatewayHostname;
772 tls->port = WINPR_ASSERTING_INT_CAST(int32_t, MIN(UINT16_MAX, settings->GatewayPort));
773 tls->isGatewayTransport = TRUE;
774 int tlsStatus = freerdp_tls_connect(tls, bufferedBio);
780 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
784 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
793 static int rpc_in_channel_connect(
RpcInChannel* inChannel, UINT32 timeout)
795 rdpContext* context = NULL;
797 if (!inChannel || !inChannel->common.client || !inChannel->common.client->context)
800 context = inChannel->common.client->context;
804 if (!rpc_channel_tls_connect(&inChannel->common, timeout))
807 rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);
809 if (!rpc_ncacn_http_auth_init(context, &inChannel->common))
814 if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
816 WLog_Print(inChannel->common.rpc->log, WLOG_ERROR,
817 "rpc_ncacn_http_send_in_channel_request failure");
821 if (!rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY))
827 static int rpc_out_channel_connect(
RpcOutChannel* outChannel, UINT32 timeout)
829 rdpContext* context = NULL;
831 if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
834 context = outChannel->common.client->context;
838 if (!rpc_channel_tls_connect(&outChannel->common, timeout))
841 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
843 if (!rpc_ncacn_http_auth_init(context, &outChannel->common))
848 if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
850 WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
851 "rpc_ncacn_http_send_out_channel_request failure");
855 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
859 int rpc_out_channel_replacement_connect(
RpcOutChannel* outChannel, uint32_t timeout)
861 rdpContext* context = NULL;
863 if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
866 context = outChannel->common.client->context;
870 if (!rpc_channel_tls_connect(&outChannel->common, timeout))
873 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
875 if (!rpc_ncacn_http_auth_init(context, (
RpcChannel*)outChannel))
880 if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, TRUE))
882 WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
883 "rpc_ncacn_http_send_out_channel_request failure");
887 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
891 BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout)
896 rpc->VirtualConnection = rpc_virtual_connection_new(rpc);
898 if (!rpc->VirtualConnection)
901 connection = rpc->VirtualConnection;
902 inChannel = connection->DefaultInChannel;
903 outChannel = connection->DefaultOutChannel;
904 rpc_virtual_connection_transition_to_state(rpc, connection, VIRTUAL_CONNECTION_STATE_INITIAL);
906 if (rpc_in_channel_connect(inChannel, timeout) < 0)
909 if (rpc_out_channel_connect(outChannel, timeout) < 0)
915 rdpRpc* rpc_new(rdpTransport* transport)
917 rdpContext* context = transport_get_context(transport);
920 WINPR_ASSERT(context);
922 rpc = (rdpRpc*)calloc(1,
sizeof(rdpRpc));
927 rpc->log = WLog_Get(TAG);
928 rpc->State = RPC_CLIENT_STATE_INITIAL;
929 rpc->transport = transport;
931 rpc->auth = credssp_auth_new(context);
938 rpc->StubFragCount = 0;
940 rpc->rpc_vers_minor = 0;
942 rpc->packed_drep[0] = 0x10;
943 rpc->packed_drep[1] = 0x00;
944 rpc->packed_drep[2] = 0x00;
945 rpc->packed_drep[3] = 0x00;
946 rpc->max_xmit_frag = 0x0FF8;
947 rpc->max_recv_frag = 0x0FF8;
948 rpc->ReceiveWindow = 0x00010000;
949 rpc->ChannelLifetime = 0x40000000;
950 rpc->KeepAliveInterval = 300000;
951 rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
952 rpc->CurrentKeepAliveTime = 0;
954 rpc->client = rpc_client_new(context, rpc->max_recv_frag);
961 WINPR_PRAGMA_DIAG_PUSH
962 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
964 WINPR_PRAGMA_DIAG_POP
968 void rpc_free(rdpRpc* rpc)
972 rpc_client_free(rpc->client);
973 credssp_auth_free(rpc->auth);
974 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.