22 #include <freerdp/config.h>
24 #include "../settings.h"
26 #include <winpr/crt.h>
27 #include <winpr/assert.h>
28 #include <winpr/tchar.h>
29 #include <winpr/synch.h>
30 #include <winpr/dsparse.h>
31 #include <winpr/crypto.h>
33 #include <freerdp/log.h>
35 #ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
36 #include <valgrind/memcheck.h>
41 #include "../credssp_auth.h"
42 #include "ncacn_http.h"
44 #include "rpc_fault.h"
45 #include "rpc_client.h"
50 #define TAG FREERDP_TAG("core.gateway.rpc")
52 static const char* PTYPE_STRINGS[] = {
"PTYPE_REQUEST",
"PTYPE_PING",
53 "PTYPE_RESPONSE",
"PTYPE_FAULT",
54 "PTYPE_WORKING",
"PTYPE_NOCALL",
55 "PTYPE_REJECT",
"PTYPE_ACK",
56 "PTYPE_CL_CANCEL",
"PTYPE_FACK",
57 "PTYPE_CANCEL_ACK",
"PTYPE_BIND",
58 "PTYPE_BIND_ACK",
"PTYPE_BIND_NAK",
59 "PTYPE_ALTER_CONTEXT",
"PTYPE_ALTER_CONTEXT_RESP",
60 "PTYPE_RPC_AUTH_3",
"PTYPE_SHUTDOWN",
61 "PTYPE_CO_CANCEL",
"PTYPE_ORPHANED",
64 static const char* client_in_state_str(CLIENT_IN_CHANNEL_STATE state)
67 const char* str =
"CLIENT_IN_CHANNEL_STATE_UNKNOWN";
71 case CLIENT_IN_CHANNEL_STATE_INITIAL:
72 str =
"CLIENT_IN_CHANNEL_STATE_INITIAL";
75 case CLIENT_IN_CHANNEL_STATE_CONNECTED:
76 str =
"CLIENT_IN_CHANNEL_STATE_CONNECTED";
79 case CLIENT_IN_CHANNEL_STATE_SECURITY:
80 str =
"CLIENT_IN_CHANNEL_STATE_SECURITY";
83 case CLIENT_IN_CHANNEL_STATE_NEGOTIATED:
84 str =
"CLIENT_IN_CHANNEL_STATE_NEGOTIATED";
87 case CLIENT_IN_CHANNEL_STATE_OPENED:
88 str =
"CLIENT_IN_CHANNEL_STATE_OPENED";
91 case CLIENT_IN_CHANNEL_STATE_OPENED_A4W:
92 str =
"CLIENT_IN_CHANNEL_STATE_OPENED_A4W";
95 case CLIENT_IN_CHANNEL_STATE_FINAL:
96 str =
"CLIENT_IN_CHANNEL_STATE_FINAL";
104 static const char* client_out_state_str(CLIENT_OUT_CHANNEL_STATE state)
107 const char* str =
"CLIENT_OUT_CHANNEL_STATE_UNKNOWN";
111 case CLIENT_OUT_CHANNEL_STATE_INITIAL:
112 str =
"CLIENT_OUT_CHANNEL_STATE_INITIAL";
115 case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
116 str =
"CLIENT_OUT_CHANNEL_STATE_CONNECTED";
119 case CLIENT_OUT_CHANNEL_STATE_SECURITY:
120 str =
"CLIENT_OUT_CHANNEL_STATE_SECURITY";
123 case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
124 str =
"CLIENT_OUT_CHANNEL_STATE_NEGOTIATED";
127 case CLIENT_OUT_CHANNEL_STATE_OPENED:
128 str =
"CLIENT_OUT_CHANNEL_STATE_OPENED";
131 case CLIENT_OUT_CHANNEL_STATE_OPENED_A6W:
132 str =
"CLIENT_OUT_CHANNEL_STATE_OPENED_A6W";
135 case CLIENT_OUT_CHANNEL_STATE_OPENED_A10W:
136 str =
"CLIENT_OUT_CHANNEL_STATE_OPENED_A10W";
139 case CLIENT_OUT_CHANNEL_STATE_OPENED_B3W:
140 str =
"CLIENT_OUT_CHANNEL_STATE_OPENED_B3W";
143 case CLIENT_OUT_CHANNEL_STATE_RECYCLED:
144 str =
"CLIENT_OUT_CHANNEL_STATE_RECYCLED";
147 case CLIENT_OUT_CHANNEL_STATE_FINAL:
148 str =
"CLIENT_OUT_CHANNEL_STATE_FINAL";
156 const char* rpc_vc_state_str(VIRTUAL_CONNECTION_STATE state)
159 const char* str =
"VIRTUAL_CONNECTION_STATE_UNKNOWN";
163 case VIRTUAL_CONNECTION_STATE_INITIAL:
164 str =
"VIRTUAL_CONNECTION_STATE_INITIAL";
167 case VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT:
168 str =
"VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT";
171 case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
172 str =
"VIRTUAL_CONNECTION_STATE_WAIT_A3W";
175 case VIRTUAL_CONNECTION_STATE_WAIT_C2:
176 str =
"VIRTUAL_CONNECTION_STATE_WAIT_C2";
179 case VIRTUAL_CONNECTION_STATE_OPENED:
180 str =
"VIRTUAL_CONNECTION_STATE_OPENED";
183 case VIRTUAL_CONNECTION_STATE_FINAL:
184 str =
"VIRTUAL_CONNECTION_STATE_FINAL";
219 void rpc_pdu_header_print(wLog* log,
const rpcconn_hdr_t* header)
221 WINPR_ASSERT(header);
223 WLog_Print(log, WLOG_INFO,
"rpc_vers: %" PRIu8
"", header->common.rpc_vers);
224 WLog_Print(log, WLOG_INFO,
"rpc_vers_minor: %" PRIu8
"", header->common.rpc_vers_minor);
226 if (header->common.ptype > PTYPE_RTS)
227 WLog_Print(log, WLOG_INFO,
"ptype: %s (%" PRIu8
")",
"PTYPE_UNKNOWN", header->common.ptype);
229 WLog_Print(log, WLOG_INFO,
"ptype: %s (%" PRIu8
")", PTYPE_STRINGS[header->common.ptype],
230 header->common.ptype);
232 WLog_Print(log, WLOG_INFO,
"pfc_flags (0x%02" PRIX8
") = {", header->common.pfc_flags);
234 if (header->common.pfc_flags & PFC_FIRST_FRAG)
235 WLog_Print(log, WLOG_INFO,
" PFC_FIRST_FRAG");
237 if (header->common.pfc_flags & PFC_LAST_FRAG)
238 WLog_Print(log, WLOG_INFO,
" PFC_LAST_FRAG");
240 if (header->common.pfc_flags & PFC_PENDING_CANCEL)
241 WLog_Print(log, WLOG_INFO,
" PFC_PENDING_CANCEL");
243 if (header->common.pfc_flags & PFC_RESERVED_1)
244 WLog_Print(log, WLOG_INFO,
" PFC_RESERVED_1");
246 if (header->common.pfc_flags & PFC_CONC_MPX)
247 WLog_Print(log, WLOG_INFO,
" PFC_CONC_MPX");
249 if (header->common.pfc_flags & PFC_DID_NOT_EXECUTE)
250 WLog_Print(log, WLOG_INFO,
" PFC_DID_NOT_EXECUTE");
252 if (header->common.pfc_flags & PFC_OBJECT_UUID)
253 WLog_Print(log, WLOG_INFO,
" PFC_OBJECT_UUID");
255 WLog_Print(log, WLOG_INFO,
" }");
256 WLog_Print(log, WLOG_INFO,
257 "packed_drep[4]: %02" PRIX8
" %02" PRIX8
" %02" PRIX8
" %02" PRIX8
"",
258 header->common.packed_drep[0], header->common.packed_drep[1],
259 header->common.packed_drep[2], header->common.packed_drep[3]);
260 WLog_Print(log, WLOG_INFO,
"frag_length: %" PRIu16
"", header->common.frag_length);
261 WLog_Print(log, WLOG_INFO,
"auth_length: %" PRIu16
"", header->common.auth_length);
262 WLog_Print(log, WLOG_INFO,
"call_id: %" PRIu32
"", header->common.call_id);
264 if (header->common.ptype == PTYPE_RESPONSE)
266 WLog_Print(log, WLOG_INFO,
"alloc_hint: %" PRIu32
"", header->response.alloc_hint);
267 WLog_Print(log, WLOG_INFO,
"p_cont_id: %" PRIu16
"", header->response.p_cont_id);
268 WLog_Print(log, WLOG_INFO,
"cancel_count: %" PRIu8
"", header->response.cancel_count);
269 WLog_Print(log, WLOG_INFO,
"reserved: %" PRIu8
"", header->response.reserved);
278 header.rpc_vers = rpc->rpc_vers;
279 header.rpc_vers_minor = rpc->rpc_vers_minor;
280 header.packed_drep[0] = rpc->packed_drep[0];
281 header.packed_drep[1] = rpc->packed_drep[1];
282 header.packed_drep[2] = rpc->packed_drep[2];
283 header.packed_drep[3] = rpc->packed_drep[3];
287 size_t rpc_offset_align(
size_t* offset,
size_t alignment)
291 *offset = (*offset + alignment - 1) & ~(alignment - 1);
296 size_t rpc_offset_pad(
size_t* offset,
size_t pad)
377 BOOL rpc_get_stub_data_info(rdpRpc* rpc,
const rpcconn_hdr_t* header,
size_t* poffset,
383 UINT32 frag_length = 0;
384 UINT32 auth_length = 0;
385 UINT32 auth_pad_length = 0;
386 UINT32 sec_trailer_offset = 0;
387 const rpc_sec_trailer* sec_trailer = NULL;
390 WINPR_ASSERT(header);
391 WINPR_ASSERT(poffset);
392 WINPR_ASSERT(length);
394 offset = RPC_COMMON_FIELDS_LENGTH;
396 switch (header->common.ptype)
400 rpc_offset_align(&offset, 8);
401 sec_trailer = &header->response.auth_verifier;
406 rpc_offset_align(&offset, 8);
407 sec_trailer = &header->request.auth_verifier;
415 WLog_Print(rpc->log, WLOG_ERROR,
"Unknown PTYPE: 0x%02" PRIX8
"", header->common.ptype);
419 frag_length = header->common.frag_length;
420 auth_length = header->common.auth_length;
426 used = offset + auth_length + 8ull;
429 auth_pad_length = sec_trailer->auth_pad_length;
430 used += sec_trailer->auth_pad_length;
433 if (frag_length < used)
439 sec_trailer_offset = frag_length - auth_length - 8;
447 if ((frag_length - (sec_trailer_offset + 8)) != auth_length)
449 WLog_Print(rpc->log, WLOG_ERROR,
450 "invalid auth_length: actual: %" PRIu32
", expected: %" PRIu32
"", auth_length,
451 (frag_length - (sec_trailer_offset + 8)));
454 *length = sec_trailer_offset - auth_pad_length - offset;
465 if (!channel || (length > INT32_MAX))
469 status = BIO_read(channel->tls->bio, Stream_Pointer(s), (INT32)length);
473 Stream_Seek(s, (
size_t)status);
477 if (BIO_should_retry(channel->tls->bio))
480 WLog_Print(channel->rpc->log, WLOG_ERROR,
"rpc_channel_read: Out of retries");
484 SSIZE_T rpc_channel_write(
RpcChannel* channel,
const BYTE* data,
size_t length)
489 return freerdp_tls_write_all(channel->tls, data, length);
492 BOOL rpc_in_channel_transition_to_state(
RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
497 inChannel->State = state;
498 WLog_Print(inChannel->common.rpc->log, WLOG_DEBUG,
"%s", client_in_state_str(state));
502 static int rpc_channel_rpch_init(
RpcClient* client,
RpcChannel* channel,
const char* inout,
505 HttpContext* http = NULL;
506 rdpSettings* settings = NULL;
509 if (!client || !channel || !inout || !client->context || !client->context->settings)
512 settings = client->context->settings;
513 channel->auth = credssp_auth_new(client->context);
514 rts_generate_cookie((BYTE*)&channel->Cookie);
515 channel->client = client;
520 channel->http = http_context_new();
525 http = channel->http;
528 if (!http_context_set_pragma(http,
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"))
533 char* strguid = NULL;
534 RPC_STATUS rpcStatus = UuidToStringA(guid, &strguid);
536 if (rpcStatus != RPC_S_OK)
539 const BOOL rc = http_context_append_pragma(http,
"SessionId=%s", strguid);
540 RpcStringFreeA(&strguid);
546 if (!http_context_append_pragma(http,
"MinConnTimeout=%" PRIu32, timeout))
550 if (!http_context_set_rdg_correlation_id(http, guid) ||
551 !http_context_set_rdg_connection_id(http, guid))
556 if (!http_context_set_method(http, inout) ||
557 !http_context_set_uri(http,
"/rpc/rpcproxy.dll?localhost:3388") ||
558 !http_context_set_accept(http,
"application/rpc") ||
559 !http_context_set_cache_control(http,
"no-cache") ||
560 !http_context_set_connection(http,
"Keep-Alive") ||
561 !http_context_set_user_agent(http,
"MSRPC") ||
562 !http_context_set_host(http, settings->GatewayHostname))
568 static int rpc_in_channel_init(rdpRpc* rpc,
RpcInChannel* inChannel,
const GUID* guid)
571 WINPR_ASSERT(inChannel);
573 inChannel->common.rpc = rpc;
574 inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL;
575 inChannel->BytesSent = 0;
576 inChannel->SenderAvailableWindow = rpc->ReceiveWindow;
577 inChannel->PingOriginator.ConnectionTimeout = 30;
578 inChannel->PingOriginator.KeepAliveInterval = 0;
580 if (rpc_channel_rpch_init(rpc->client, &inChannel->common,
"RPC_IN_DATA", guid) < 0)
586 static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc,
const GUID* guid)
592 rpc_in_channel_init(rpc, inChannel, guid);
603 credssp_auth_free(channel->auth);
604 http_context_free(channel->http);
605 freerdp_tls_free(channel->tls);
609 BOOL rpc_out_channel_transition_to_state(
RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
614 outChannel->State = state;
615 WLog_Print(outChannel->common.rpc->log, WLOG_DEBUG,
"%s", client_out_state_str(state));
619 static int rpc_out_channel_init(rdpRpc* rpc,
RpcOutChannel* outChannel,
const GUID* guid)
622 WINPR_ASSERT(outChannel);
624 outChannel->common.rpc = rpc;
625 outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
626 outChannel->BytesReceived = 0;
627 outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
628 outChannel->ReceiveWindow = rpc->ReceiveWindow;
629 outChannel->ReceiveWindowSize = rpc->ReceiveWindow;
630 outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
632 if (rpc_channel_rpch_init(rpc->client, &outChannel->common,
"RPC_OUT_DATA", guid) < 0)
638 RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc,
const GUID* guid)
644 rpc_out_channel_init(rpc, outChannel, guid);
651 VIRTUAL_CONNECTION_STATE state)
657 connection->State = state;
658 WLog_Print(rpc->log, WLOG_DEBUG,
"%s", rpc_vc_state_str(state));
667 if (connection->DefaultInChannel)
668 rpc_channel_free(&connection->DefaultInChannel->common);
669 if (connection->NonDefaultInChannel)
670 rpc_channel_free(&connection->NonDefaultInChannel->common);
671 if (connection->DefaultOutChannel)
672 rpc_channel_free(&connection->DefaultOutChannel->common);
673 if (connection->NonDefaultOutChannel)
674 rpc_channel_free(&connection->NonDefaultOutChannel->common);
688 rts_generate_cookie((BYTE*)&(connection->Cookie));
689 rts_generate_cookie((BYTE*)&(connection->AssociationGroupId));
690 connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
692 connection->DefaultInChannel = rpc_in_channel_new(rpc, &connection->Cookie);
694 if (!connection->DefaultInChannel)
697 connection->DefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
699 if (!connection->DefaultOutChannel)
704 rpc_virtual_connection_free(connection);
708 static BOOL rpc_channel_tls_connect(
RpcChannel* channel, UINT32 timeout)
710 if (!channel || !channel->client || !channel->client->context ||
711 !channel->client->context->settings)
714 rdpContext* context = channel->client->context;
715 WINPR_ASSERT(context);
717 rdpSettings* settings = context->settings;
718 WINPR_ASSERT(settings);
723 rdpTransport* transport = freerdp_get_transport(context);
725 transport_connect_layer(transport, channel->client->host, channel->client->port, timeout);
730 BIO* layerBio = BIO_new(BIO_s_transport_layer());
733 transport_layer_free(layer);
736 BIO_set_data(layerBio, layer);
738 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
741 BIO_free_all(layerBio);
745 bufferedBio = BIO_push(bufferedBio, layerBio);
747 if (!BIO_set_nonblock(bufferedBio, TRUE))
749 BIO_free_all(bufferedBio);
753 if (channel->client->isProxy)
755 if (!proxy_connect(context, bufferedBio, proxyUsername, proxyPassword,
756 settings->GatewayHostname, settings->GatewayPort))
758 BIO_free_all(bufferedBio);
763 channel->bio = bufferedBio;
764 rdpTls* tls = channel->tls = freerdp_tls_new(context);
769 tls->hostname = settings->GatewayHostname;
770 tls->port = MIN(UINT16_MAX, settings->GatewayPort);
771 tls->isGatewayTransport = TRUE;
772 int tlsStatus = freerdp_tls_connect(tls, bufferedBio);
778 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
782 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
791 static int rpc_in_channel_connect(
RpcInChannel* inChannel, UINT32 timeout)
793 rdpContext* context = NULL;
795 if (!inChannel || !inChannel->common.client || !inChannel->common.client->context)
798 context = inChannel->common.client->context;
802 if (!rpc_channel_tls_connect(&inChannel->common, timeout))
805 rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);
807 if (!rpc_ncacn_http_auth_init(context, &inChannel->common))
812 if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
814 WLog_Print(inChannel->common.rpc->log, WLOG_ERROR,
815 "rpc_ncacn_http_send_in_channel_request failure");
819 if (!rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY))
825 static int rpc_out_channel_connect(
RpcOutChannel* outChannel,
int timeout)
827 rdpContext* context = NULL;
829 if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
832 context = outChannel->common.client->context;
836 if (!rpc_channel_tls_connect(&outChannel->common, timeout))
839 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
841 if (!rpc_ncacn_http_auth_init(context, &outChannel->common))
846 if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
848 WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
849 "rpc_ncacn_http_send_out_channel_request failure");
853 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
857 int rpc_out_channel_replacement_connect(
RpcOutChannel* outChannel,
int timeout)
859 rdpContext* context = NULL;
861 if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
864 context = outChannel->common.client->context;
868 if (!rpc_channel_tls_connect(&outChannel->common, timeout))
871 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
873 if (!rpc_ncacn_http_auth_init(context, (
RpcChannel*)outChannel))
878 if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, TRUE))
880 WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
881 "rpc_ncacn_http_send_out_channel_request failure");
885 rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
889 BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout)
894 rpc->VirtualConnection = rpc_virtual_connection_new(rpc);
896 if (!rpc->VirtualConnection)
899 connection = rpc->VirtualConnection;
900 inChannel = connection->DefaultInChannel;
901 outChannel = connection->DefaultOutChannel;
902 rpc_virtual_connection_transition_to_state(rpc, connection, VIRTUAL_CONNECTION_STATE_INITIAL);
904 if (rpc_in_channel_connect(inChannel, timeout) < 0)
907 if (rpc_out_channel_connect(outChannel, timeout) < 0)
913 rdpRpc* rpc_new(rdpTransport* transport)
915 rdpContext* context = transport_get_context(transport);
918 WINPR_ASSERT(context);
920 rpc = (rdpRpc*)calloc(1,
sizeof(rdpRpc));
925 rpc->log = WLog_Get(TAG);
926 rpc->State = RPC_CLIENT_STATE_INITIAL;
927 rpc->transport = transport;
929 rpc->auth = credssp_auth_new(context);
936 rpc->StubFragCount = 0;
938 rpc->rpc_vers_minor = 0;
940 rpc->packed_drep[0] = 0x10;
941 rpc->packed_drep[1] = 0x00;
942 rpc->packed_drep[2] = 0x00;
943 rpc->packed_drep[3] = 0x00;
944 rpc->max_xmit_frag = 0x0FF8;
945 rpc->max_recv_frag = 0x0FF8;
946 rpc->ReceiveWindow = 0x00010000;
947 rpc->ChannelLifetime = 0x40000000;
948 rpc->KeepAliveInterval = 300000;
949 rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
950 rpc->CurrentKeepAliveTime = 0;
952 rpc->client = rpc_client_new(context, rpc->max_recv_frag);
959 WINPR_PRAGMA_DIAG_PUSH
960 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
962 WINPR_PRAGMA_DIAG_POP
966 void rpc_free(rdpRpc* rpc)
970 rpc_client_free(rpc->client);
971 credssp_auth_free(rpc->auth);
972 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.