20 #include <freerdp/config.h>
24 #include <winpr/assert.h>
26 #include <winpr/crt.h>
27 #include <winpr/synch.h>
28 #include <winpr/print.h>
29 #include <winpr/stream.h>
30 #include <winpr/winsock.h>
31 #include <winpr/crypto.h>
33 #include <freerdp/log.h>
34 #include <freerdp/error.h>
35 #include <freerdp/utils/ringbuffer.h>
37 #include <openssl/bio.h>
44 #include <sys/socket.h>
47 #ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
48 #include <valgrind/memcheck.h>
53 #include "transport.h"
58 #include "childsession.h"
60 #include "gateway/rdg.h"
61 #include "gateway/wst.h"
62 #include "gateway/arm.h"
64 #define TAG FREERDP_TAG("core.transport")
66 #define BUFFER_SIZE 16384
70 TRANSPORT_LAYER layer;
80 TransportRecv ReceiveCallback;
81 wStreamPool* ReceivePool;
82 HANDLE connectedEvent;
92 BOOL haveMoreBytesToRead;
100 static void transport_ssl_cb(
const SSL* ssl,
int where,
int ret)
102 if (where & SSL_CB_ALERT)
104 rdpTransport* transport = (rdpTransport*)SSL_get_app_data(ssl);
105 WINPR_ASSERT(transport);
109 case (SSL3_AL_FATAL << 8) | SSL_AD_ACCESS_DENIED:
111 if (!freerdp_get_last_error(transport_get_context(transport)))
113 WLog_Print(transport->log, WLOG_ERROR,
"ACCESS DENIED");
114 freerdp_set_last_error_log(transport_get_context(transport),
115 FREERDP_ERROR_AUTHENTICATION_FAILED);
120 case (SSL3_AL_FATAL << 8) | SSL_AD_INTERNAL_ERROR:
122 if (transport->NlaMode)
124 if (!freerdp_get_last_error(transport_get_context(transport)))
128 kret = nla_get_error(transport->nla);
130 kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
131 freerdp_set_last_error_log(transport_get_context(transport), kret);
137 case (SSL3_AL_WARNING << 8) | SSL3_AD_CLOSE_NOTIFY:
141 WLog_Print(transport->log, WLOG_WARN,
142 "Unhandled SSL error (where=%d, ret=%d [%s, %s])", where, ret,
143 SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
150 wStream* transport_send_stream_init(rdpTransport* transport,
size_t size)
152 WINPR_ASSERT(transport);
154 wStream* s = StreamPool_Take(transport->ReceivePool, size);
158 if (!Stream_EnsureCapacity(s, size))
164 Stream_SetPosition(s, 0);
168 BOOL transport_attach(rdpTransport* transport,
int sockfd)
172 return IFCALLRESULT(FALSE, transport->io.TransportAttach, transport, sockfd);
175 static BOOL transport_default_attach(rdpTransport* transport,
int sockfd)
177 BIO* socketBio = NULL;
178 BIO* bufferedBio = NULL;
179 const rdpSettings* settings = NULL;
180 rdpContext* context = transport_get_context(transport);
184 WLog_WARN(TAG,
"Running peer without socket (sockfd=%d)", sockfd);
188 settings = context->settings;
189 WINPR_ASSERT(settings);
193 if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
196 socketBio = BIO_new(BIO_s_simple_socket());
202 bufferedBio = BIO_new(BIO_s_buffered_socket());
208 bufferedBio = BIO_push(bufferedBio, socketBio);
217 BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
219 EnterCriticalSection(&(transport->ReadLock));
220 EnterCriticalSection(&(transport->WriteLock));
221 transport->frontBio = bufferedBio;
222 LeaveCriticalSection(&(transport->WriteLock));
223 LeaveCriticalSection(&(transport->ReadLock));
229 BIO_free_all(socketBio);
231 closesocket((SOCKET)sockfd);
236 BOOL transport_connect_rdp(rdpTransport* transport)
241 switch (utils_authenticate(transport_get_context(transport)->instance, AUTH_RDP, FALSE))
245 case AUTH_NO_CREDENTIALS:
248 freerdp_set_last_error_if_not(transport_get_context(transport),
249 FREERDP_ERROR_CONNECT_CANCELLED);
256 BOOL transport_connect_tls(rdpTransport* transport)
258 const rdpSettings* settings = NULL;
259 rdpContext* context = transport_get_context(transport);
261 settings = context->settings;
262 WINPR_ASSERT(settings);
265 if (settings->SelectedProtocol == PROTOCOL_SSL)
267 switch (utils_authenticate(context->instance, AUTH_TLS, FALSE))
271 case AUTH_NO_CREDENTIALS:
274 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
281 return IFCALLRESULT(FALSE, transport->io.TLSConnect, transport);
284 static BOOL transport_default_connect_tls(rdpTransport* transport)
288 rdpContext* context = NULL;
289 rdpSettings* settings = NULL;
291 WINPR_ASSERT(transport);
293 context = transport_get_context(transport);
294 WINPR_ASSERT(context);
296 settings = context->settings;
297 WINPR_ASSERT(settings);
299 if (!(tls = freerdp_tls_new(context)))
302 transport->tls = tls;
304 if (transport->GatewayEnabled)
305 transport->layer = TRANSPORT_LAYER_TSG_TLS;
307 transport->layer = TRANSPORT_LAYER_TLS;
309 tls->hostname = settings->ServerHostname;
310 tls->serverName = settings->UserSpecifiedServerName;
311 tls->port = WINPR_ASSERTING_INT_CAST(int32_t, MIN(UINT16_MAX, settings->ServerPort));
316 tls->isGatewayTransport = FALSE;
317 tlsStatus = freerdp_tls_connect(tls, transport->frontBio);
323 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
327 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
333 transport->frontBio = tls->bio;
342 typedef void (*ssl_cb_t)(
const SSL* ssl,
int type,
int val);
343 ssl_cb_t fkt = transport_ssl_cb;
345 BIO_info_cb* bfkt = WINPR_FUNC_PTR_CAST(fkt, BIO_info_cb*);
346 BIO_callback_ctrl(tls->bio, BIO_CTRL_SET_CALLBACK, bfkt);
347 SSL_set_app_data(tls->ssl, transport);
349 if (!transport->frontBio)
351 WLog_Print(transport->log, WLOG_ERROR,
"unable to prepend a filtering TLS bio");
358 BOOL transport_connect_nla(rdpTransport* transport, BOOL earlyUserAuth)
360 rdpContext* context = NULL;
361 rdpSettings* settings = NULL;
366 context = transport_get_context(transport);
367 WINPR_ASSERT(context);
369 settings = context->settings;
370 WINPR_ASSERT(settings);
375 if (!transport_connect_tls(transport))
378 if (!settings->Authentication)
382 rdp->nla = nla_new(context, transport);
387 nla_set_early_user_auth(rdp->nla, earlyUserAuth);
389 transport_set_nla_mode(transport, TRUE);
391 if (settings->AuthenticationServiceClass)
393 if (!nla_set_service_principal(rdp->nla, settings->AuthenticationServiceClass,
398 if (nla_client_begin(rdp->nla) < 0)
400 WLog_Print(transport->log, WLOG_ERROR,
"NLA begin failed");
402 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
404 transport_set_nla_mode(transport, FALSE);
408 return rdp_client_transition_to_state(rdp, CONNECTION_STATE_NLA);
411 BOOL transport_connect_rdstls(rdpTransport* transport)
414 rdpRdstls* rdstls = NULL;
415 rdpContext* context = NULL;
417 WINPR_ASSERT(transport);
419 context = transport_get_context(transport);
420 WINPR_ASSERT(context);
422 if (!transport_connect_tls(transport))
425 rdstls = rdstls_new(context, transport);
429 transport_set_rdstls_mode(transport, TRUE);
431 if (rdstls_authenticate(rdstls) < 0)
433 WLog_Print(transport->log, WLOG_ERROR,
"RDSTLS authentication failed");
434 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
438 transport_set_rdstls_mode(transport, FALSE);
445 BOOL transport_connect_aad(rdpTransport* transport)
447 rdpContext* context = NULL;
448 rdpSettings* settings = NULL;
453 context = transport_get_context(transport);
454 WINPR_ASSERT(context);
456 settings = context->settings;
457 WINPR_ASSERT(settings);
462 if (!transport_connect_tls(transport))
465 if (!settings->Authentication)
471 transport_set_aad_mode(transport, TRUE);
473 if (aad_client_begin(rdp->aad) < 0)
475 WLog_Print(transport->log, WLOG_ERROR,
"AAD begin failed");
477 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
479 transport_set_aad_mode(transport, FALSE);
483 return rdp_client_transition_to_state(rdp, CONNECTION_STATE_AAD);
486 BOOL transport_connect(rdpTransport* transport,
const char* hostname, UINT16 port, DWORD timeout)
489 rdpSettings* settings = NULL;
490 rdpContext* context = transport_get_context(transport);
491 BOOL rpcFallback = 0;
493 WINPR_ASSERT(context);
494 WINPR_ASSERT(hostname);
496 settings = context->settings;
497 WINPR_ASSERT(settings);
499 rpcFallback = !settings->GatewayHttpTransport;
501 if (transport->GatewayEnabled)
503 if (settings->GatewayUrl)
505 WINPR_ASSERT(!transport->wst);
506 transport->wst = wst_new(context);
511 status = wst_connect(transport->wst, timeout);
515 transport->frontBio = wst_get_front_bio_and_take_ownership(transport->wst);
516 WINPR_ASSERT(transport->frontBio);
517 BIO_set_nonblock(transport->frontBio, 0);
518 transport->layer = TRANSPORT_LAYER_TSG;
523 wst_free(transport->wst);
524 transport->wst = NULL;
527 if (!status && settings->GatewayHttpTransport)
529 WINPR_ASSERT(!transport->rdg);
530 transport->rdg = rdg_new(context);
535 status = rdg_connect(transport->rdg, timeout, &rpcFallback);
539 transport->frontBio = rdg_get_front_bio_and_take_ownership(transport->rdg);
540 WINPR_ASSERT(transport->frontBio);
541 BIO_set_nonblock(transport->frontBio, 0);
542 transport->layer = TRANSPORT_LAYER_TSG;
547 rdg_free(transport->rdg);
548 transport->rdg = NULL;
552 if (!status && settings->GatewayRpcTransport && rpcFallback)
554 WINPR_ASSERT(!transport->tsg);
555 transport->tsg = tsg_new(transport);
561 freerdp_set_last_error_log(context, FREERDP_ERROR_SUCCESS);
562 status = tsg_connect(transport->tsg, hostname, port, timeout);
566 transport->frontBio = tsg_get_bio(transport->tsg);
567 transport->layer = TRANSPORT_LAYER_TSG;
572 tsg_free(transport->tsg);
573 transport->tsg = NULL;
580 const char* proxyHostname = NULL;
581 const char* proxyUsername = NULL;
582 const char* proxyPassword = NULL;
583 BOOL isProxyConnection =
584 proxy_prepare(settings, &proxyHostname, &peerPort, &proxyUsername, &proxyPassword);
587 if (isProxyConnection)
588 layer = transport_connect_layer(transport, proxyHostname, peerPort, timeout);
590 layer = transport_connect_layer(transport, hostname, port, timeout);
595 if (!transport_attach_layer(transport, layer))
597 transport_layer_free(layer);
601 if (isProxyConnection)
603 if (!proxy_connect(context, transport->frontBio, proxyUsername, proxyPassword, hostname,
614 BOOL transport_connect_childsession(rdpTransport* transport)
616 WINPR_ASSERT(transport);
618 transport->frontBio = createChildSessionBio();
619 if (!transport->frontBio)
622 transport->layer = TRANSPORT_LAYER_TSG;
626 BOOL transport_accept_rdp(rdpTransport* transport)
634 BOOL transport_accept_tls(rdpTransport* transport)
638 return IFCALLRESULT(FALSE, transport->io.TLSAccept, transport);
641 static BOOL transport_default_accept_tls(rdpTransport* transport)
643 rdpContext* context = transport_get_context(transport);
644 rdpSettings* settings = NULL;
646 WINPR_ASSERT(context);
648 settings = context->settings;
649 WINPR_ASSERT(settings);
652 transport->tls = freerdp_tls_new(context);
654 transport->layer = TRANSPORT_LAYER_TLS;
656 if (!freerdp_tls_accept(transport->tls, transport->frontBio, settings))
659 transport->frontBio = transport->tls->bio;
663 BOOL transport_accept_nla(rdpTransport* transport)
665 rdpContext* context = transport_get_context(transport);
666 rdpSettings* settings = NULL;
668 WINPR_ASSERT(context);
670 settings = context->settings;
671 WINPR_ASSERT(settings);
673 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
678 if (!settings->Authentication)
683 transport->nla = nla_new(context, transport);
684 transport_set_nla_mode(transport, TRUE);
687 if (nla_authenticate(transport->nla) < 0)
689 WLog_Print(transport->log, WLOG_ERROR,
"client authentication failure");
690 transport_set_nla_mode(transport, FALSE);
691 nla_free(transport->nla);
692 transport->nla = NULL;
693 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
694 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
695 freerdp_tls_send_alert(transport->tls);
700 transport_set_nla_mode(transport, FALSE);
704 BOOL transport_accept_rdstls(rdpTransport* transport)
707 rdpRdstls* rdstls = NULL;
708 rdpContext* context = NULL;
710 WINPR_ASSERT(transport);
712 context = transport_get_context(transport);
713 WINPR_ASSERT(context);
715 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
718 rdstls = rdstls_new(context, transport);
722 transport_set_rdstls_mode(transport, TRUE);
724 if (rdstls_authenticate(rdstls) < 0)
726 WLog_Print(transport->log, WLOG_ERROR,
"client authentication failure");
727 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
728 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
729 freerdp_tls_send_alert(transport->tls);
733 transport_set_rdstls_mode(transport, FALSE);
740 #define WLog_ERR_BIO(transport, biofunc, bio) \
741 transport_bio_error_log(transport, biofunc, bio, __FILE__, __func__, __LINE__)
743 static void transport_bio_error_log(rdpTransport* transport, LPCSTR biofunc, BIO* bio, LPCSTR file,
744 LPCSTR func, DWORD line)
746 unsigned long sslerr = 0;
750 WINPR_ASSERT(transport);
755 if (level < WLog_GetLogLevel(transport->log))
758 if (ERR_peek_error() == 0)
760 char ebuffer[256] = { 0 };
761 const char* fmt =
"%s returned a system error %d: %s";
763 fmt =
"%s retries exceeded";
764 WLog_PrintMessage(transport->log, WLOG_MESSAGE_TEXT, level, line, file, func, fmt, biofunc,
765 saveerrno, winpr_strerror(saveerrno, ebuffer,
sizeof(ebuffer)));
769 while ((sslerr = ERR_get_error()))
771 char buf[120] = { 0 };
772 const char* fmt =
"%s returned an error: %s";
774 ERR_error_string_n(sslerr, buf, 120);
775 WLog_PrintMessage(transport->log, WLOG_MESSAGE_TEXT, level, line, file, func, fmt, biofunc,
780 static SSIZE_T transport_read_layer(rdpTransport* transport, BYTE* data,
size_t bytes)
784 rdpContext* context = NULL;
786 WINPR_ASSERT(transport);
788 context = transport_get_context(transport);
789 WINPR_ASSERT(context);
794 if (!transport->frontBio || (bytes > SSIZE_MAX))
796 transport->layer = TRANSPORT_LAYER_CLOSED;
797 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
801 while (read < (SSIZE_T)bytes)
803 const SSIZE_T tr = (SSIZE_T)bytes - read;
804 int r = (int)((tr > INT_MAX) ? INT_MAX : tr);
806 int status = BIO_read(transport->frontBio, data + read, r);
808 if (freerdp_shall_disconnect_context(context))
813 if (!transport->frontBio || !BIO_should_retry(transport->frontBio))
816 if (!transport->frontBio)
818 WLog_Print(transport->log, WLOG_ERROR,
"BIO_read: transport->frontBio null");
822 WLog_ERR_BIO(transport,
"BIO_read", transport->frontBio);
823 transport->layer = TRANSPORT_LAYER_CLOSED;
824 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
829 if (!transport->blocking)
834 if (BIO_wait_read(transport->frontBio, 100) < 0)
836 WLog_ERR_BIO(transport,
"BIO_wait_read", transport->frontBio);
843 #ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
844 VALGRIND_MAKE_MEM_DEFINED(data + read, bytes - read);
847 rdp->inBytes += WINPR_ASSERTING_INT_CAST(uint64_t, status);
867 static SSIZE_T transport_read_layer_bytes(rdpTransport* transport,
wStream* s,
size_t toRead)
873 if (toRead > SSIZE_MAX)
876 status = IFCALLRESULT(-1, transport->io.ReadBytes, transport, Stream_Pointer(s), toRead);
881 Stream_Seek(s, (
size_t)status);
882 return status == (SSIZE_T)toRead ? 1 : 0;
897 int transport_read_pdu(rdpTransport* transport,
wStream* s)
901 return IFCALLRESULT(-1, transport->io.ReadPdu, transport, s);
904 static SSIZE_T parse_nla_mode_pdu(rdpTransport* transport,
wStream* stream)
906 SSIZE_T pduLength = 0;
908 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
915 UINT8 typeEncoding = 0;
916 if (Stream_GetRemainingLength(s) < 1)
918 Stream_Read_UINT8(s, typeEncoding);
919 if (typeEncoding == 0x30)
922 UINT8 lengthEncoding = 0;
923 if (Stream_GetRemainingLength(s) < 1)
925 Stream_Read_UINT8(s, lengthEncoding);
926 if (lengthEncoding & 0x80)
928 if ((lengthEncoding & ~(0x80)) == 1)
931 if (Stream_GetRemainingLength(s) < 1)
933 Stream_Read_UINT8(s, length);
937 else if ((lengthEncoding & ~(0x80)) == 2)
941 if (Stream_GetRemainingLength(s) < 2)
943 Stream_Read_UINT16_BE(s, length);
949 WLog_Print(transport->log, WLOG_ERROR,
"Error reading TSRequest!");
955 pduLength = lengthEncoding;
963 static SSIZE_T parse_default_mode_pdu(rdpTransport* transport,
wStream* stream)
965 SSIZE_T pduLength = 0;
967 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
970 if (Stream_GetRemainingLength(s) < 1)
972 Stream_Read_UINT8(s, version);
977 if (Stream_GetRemainingLength(s) < 3)
980 Stream_Read_UINT16_BE(s, length);
984 if ((pduLength < 7) || (pduLength > 0xFFFF))
986 WLog_Print(transport->log, WLOG_ERROR,
"tpkt - invalid pduLength: %" PRIdz, pduLength);
994 if (Stream_GetRemainingLength(s) < 1)
996 Stream_Read_UINT8(s, length1);
1000 if (Stream_GetRemainingLength(s) < 1)
1002 Stream_Read_UINT8(s, length2);
1003 pduLength = ((length1 & 0x7F) << 8) | length2;
1006 pduLength = length1;
1013 if (pduLength < 3 || pduLength > 0x8000)
1015 WLog_Print(transport->log, WLOG_ERROR,
"fast path - invalid pduLength: %" PRIdz,
1024 SSIZE_T transport_parse_pdu(rdpTransport* transport,
wStream* s, BOOL* incomplete)
1026 SSIZE_T pduLength = 0;
1037 Stream_SealLength(s);
1038 if (transport->NlaMode)
1039 pduLength = parse_nla_mode_pdu(transport, s);
1040 else if (transport->RdstlsMode)
1041 pduLength = rdstls_parse_pdu(transport->log, s);
1043 pduLength = parse_default_mode_pdu(transport, s);
1048 const size_t len = Stream_Length(s);
1049 if (len > WINPR_ASSERTING_INT_CAST(
size_t, pduLength))
1053 *incomplete = len < WINPR_ASSERTING_INT_CAST(
size_t, pduLength);
1058 static int transport_default_read_pdu(rdpTransport* transport,
wStream* s)
1060 BOOL incomplete = 0;
1062 size_t pduLength = 0;
1063 size_t position = 0;
1065 WINPR_ASSERT(transport);
1070 if (transport->AadMode)
1075 const SSIZE_T rc = transport_read_layer(transport, &c, 1);
1077 return (rc == 0) ? 0 : -1;
1078 if (!Stream_EnsureRemainingCapacity(s, 1))
1080 Stream_Write_UINT8(s, c);
1081 }
while (c !=
'\0');
1083 else if (transport->earlyUserAuth)
1085 if (!Stream_EnsureCapacity(s, 4))
1087 const SSIZE_T rc = transport_read_layer_bytes(transport, s, 4);
1089 return (rc == 0) ? 0 : -1;
1094 status = transport_parse_pdu(transport, s, &incomplete);
1095 while ((status == 0) && incomplete)
1097 if (!Stream_EnsureRemainingCapacity(s, 1))
1099 SSIZE_T rc = transport_read_layer_bytes(transport, s, 1);
1104 status = transport_parse_pdu(transport, s, &incomplete);
1110 pduLength = (size_t)status;
1113 if (!Stream_EnsureCapacity(s, pduLength))
1116 position = Stream_GetPosition(s);
1117 if (position > pduLength)
1119 else if (position < pduLength)
1121 status = transport_read_layer_bytes(transport, s, pduLength - position);
1124 if ((status < INT32_MIN) || (status > INT32_MAX))
1130 if (Stream_GetPosition(s) >= pduLength)
1131 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength,
1132 WLOG_PACKET_INBOUND);
1135 Stream_SealLength(s);
1136 Stream_SetPosition(s, 0);
1137 const size_t len = Stream_Length(s);
1138 if (len > INT32_MAX)
1143 int transport_write(rdpTransport* transport,
wStream* s)
1148 return IFCALLRESULT(-1, transport->io.WritePdu, transport, s);
1151 static int transport_default_write(rdpTransport* transport,
wStream* s)
1154 rdpContext* context = transport_get_context(transport);
1156 WINPR_ASSERT(transport);
1157 WINPR_ASSERT(context);
1164 rdpRdp* rdp = context->rdp;
1168 EnterCriticalSection(&(transport->WriteLock));
1169 if (!transport->frontBio)
1172 size_t length = Stream_GetPosition(s);
1173 size_t writtenlength = length;
1174 Stream_SetPosition(s, 0);
1178 rdp->outBytes += length;
1179 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
1185 const int towrite = (length > INT32_MAX) ? INT32_MAX : (
int)length;
1186 status = BIO_write(transport->frontBio, Stream_ConstPointer(s), towrite);
1194 if (!BIO_should_retry(transport->frontBio))
1196 WLog_ERR_BIO(transport,
"BIO_should_retry", transport->frontBio);
1201 if (!transport->blocking)
1203 WLog_ERR_BIO(transport,
"BIO_write", transport->frontBio);
1207 if (BIO_wait_write(transport->frontBio, 100) < 0)
1209 WLog_ERR_BIO(transport,
"BIO_wait_write", transport->frontBio);
1217 WINPR_ASSERT(context->settings);
1218 if (transport->blocking || context->settings->WaitForOutputBufferFlush)
1220 while (BIO_write_blocked(transport->frontBio))
1222 if (BIO_wait_write(transport->frontBio, 100) < 0)
1224 WLog_Print(transport->log, WLOG_ERROR,
"error when selecting for write");
1229 if (BIO_flush(transport->frontBio) < 1)
1231 WLog_Print(transport->log, WLOG_ERROR,
"error when flushing outputBuffer");
1238 length -= (size_t)status;
1239 Stream_Seek(s, (
size_t)status);
1242 transport->written += writtenlength;
1248 transport->layer = TRANSPORT_LAYER_CLOSED;
1249 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1252 LeaveCriticalSection(&(transport->WriteLock));
1258 BOOL transport_get_public_key(rdpTransport* transport,
const BYTE** data, DWORD* length)
1260 return IFCALLRESULT(FALSE, transport->io.GetPublicKey, transport, data, length);
1263 static BOOL transport_default_get_public_key(rdpTransport* transport,
const BYTE** data,
1266 rdpTls* tls = transport_get_tls(transport);
1270 *data = tls->PublicKey;
1271 *length = tls->PublicKeyLength;
1276 DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count)
1280 WINPR_ASSERT(transport);
1281 WINPR_ASSERT(events);
1282 WINPR_ASSERT(count > 0);
1288 WLog_Print(transport->log, WLOG_ERROR,
"provided handles array is too small");
1292 events[nCount++] = transport->rereadEvent;
1294 if (transport->useIoEvent)
1298 events[nCount++] = transport->ioEvent;
1302 if (!transport->GatewayEnabled)
1306 if (nCount >= count)
1308 WLog_Print(transport->log, WLOG_ERROR,
1309 "provided handles array is too small (count=%" PRIu32
" nCount=%" PRIu32
1315 if (transport->frontBio)
1317 if (BIO_get_event(transport->frontBio, &events[nCount]) != 1)
1319 WLog_Print(transport->log, WLOG_ERROR,
"error getting the frontBio handle");
1331 rdg_get_event_handles(transport->rdg, &events[nCount], count - nCount);
1338 else if (transport->tsg)
1341 tsg_get_event_handles(transport->tsg, &events[nCount], count - nCount);
1348 else if (transport->wst)
1351 wst_get_event_handles(transport->wst, &events[nCount], count - nCount);
1363 #if defined(WITH_FREERDP_DEPRECATED)
1364 void transport_get_fds(rdpTransport* transport,
void** rfds,
int* rcount)
1367 HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
1369 WINPR_ASSERT(transport);
1371 WINPR_ASSERT(rcount);
1373 nCount = transport_get_event_handles(transport, events, ARRAYSIZE(events));
1374 *rcount = nCount + 1;
1376 for (DWORD index = 0; index < nCount; index++)
1378 rfds[index] = GetEventWaitObject(events[index]);
1381 rfds[nCount] = GetEventWaitObject(transport->rereadEvent);
1385 BOOL transport_is_write_blocked(rdpTransport* transport)
1387 WINPR_ASSERT(transport);
1388 WINPR_ASSERT(transport->frontBio);
1389 return BIO_write_blocked(transport->frontBio) != 0;
1392 int transport_drain_output_buffer(rdpTransport* transport)
1394 BOOL status = FALSE;
1396 WINPR_ASSERT(transport);
1397 WINPR_ASSERT(transport->frontBio);
1398 if (BIO_write_blocked(transport->frontBio))
1400 if (BIO_flush(transport->frontBio) < 1)
1403 const long rc = BIO_write_blocked(transport->frontBio);
1410 int transport_check_fds(rdpTransport* transport)
1413 state_run_t recv_status = STATE_RUN_FAILED;
1415 rdpContext* context = transport_get_context(transport);
1417 WINPR_ASSERT(context);
1419 if (transport->layer == TRANSPORT_LAYER_CLOSED)
1421 WLog_Print(transport->log, WLOG_DEBUG,
"transport_check_fds: transport layer closed");
1422 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1435 if ((status = transport_read_pdu(transport, transport->ReceiveBuffer)) <= 0)
1438 WLog_Print(transport->log, WLOG_DEBUG,
"transport_check_fds: transport_read_pdu() - %i",
1440 if (transport->haveMoreBytesToRead)
1442 transport->haveMoreBytesToRead = FALSE;
1443 (void)ResetEvent(transport->rereadEvent);
1448 received = transport->ReceiveBuffer;
1450 if (!(transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0)))
1459 WINPR_ASSERT(transport->ReceiveCallback);
1460 recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
1461 Stream_Release(received);
1463 if (state_run_failed(recv_status))
1465 char buffer[64] = { 0 };
1466 WLog_Print(transport->log, WLOG_ERROR,
1467 "transport_check_fds: transport->ReceiveCallback() - %s",
1468 state_run_result_string(recv_status, buffer, ARRAYSIZE(buffer)));
1475 if (!transport->haveMoreBytesToRead)
1477 transport->haveMoreBytesToRead = TRUE;
1478 (void)SetEvent(transport->rereadEvent);
1483 BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1485 WINPR_ASSERT(transport);
1487 return IFCALLRESULT(FALSE, transport->io.SetBlockingMode, transport, blocking);
1490 static BOOL transport_default_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1492 WINPR_ASSERT(transport);
1494 transport->blocking = blocking;
1496 if (transport->frontBio)
1498 if (!BIO_set_nonblock(transport->frontBio, blocking ? FALSE : TRUE))
1505 rdpTransportLayer* transport_connect_layer(rdpTransport* transport,
const char* hostname,
int port,
1508 WINPR_ASSERT(transport);
1510 return IFCALLRESULT(NULL, transport->io.ConnectLayer, transport, hostname, port, timeout);
1513 static rdpTransportLayer* transport_default_connect_layer(rdpTransport* transport,
1514 const char* hostname,
int port,
1517 rdpContext* context = transport_get_context(transport);
1518 WINPR_ASSERT(context);
1520 return freerdp_tcp_connect_layer(context, hostname, port, timeout);
1525 WINPR_ASSERT(transport);
1526 WINPR_ASSERT(layer);
1528 return IFCALLRESULT(FALSE, transport->io.AttachLayer, transport, layer);
1531 static BOOL transport_default_attach_layer(rdpTransport* transport,
rdpTransportLayer* layer)
1533 BIO* layerBio = BIO_new(BIO_s_transport_layer());
1537 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
1541 bufferedBio = BIO_push(bufferedBio, layerBio);
1546 BIO_set_data(layerBio, layer);
1548 transport->frontBio = bufferedBio;
1554 BIO_free_all(layerBio);
1559 void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled)
1561 WINPR_ASSERT(transport);
1562 transport->GatewayEnabled = GatewayEnabled;
1565 void transport_set_nla_mode(rdpTransport* transport, BOOL NlaMode)
1567 WINPR_ASSERT(transport);
1568 transport->NlaMode = NlaMode;
1571 void transport_set_rdstls_mode(rdpTransport* transport, BOOL RdstlsMode)
1573 WINPR_ASSERT(transport);
1574 transport->RdstlsMode = RdstlsMode;
1577 void transport_set_aad_mode(rdpTransport* transport, BOOL AadMode)
1579 WINPR_ASSERT(transport);
1580 transport->AadMode = AadMode;
1583 BOOL transport_disconnect(rdpTransport* transport)
1587 return IFCALLRESULT(FALSE, transport->io.TransportDisconnect, transport);
1590 static BOOL transport_default_disconnect(rdpTransport* transport)
1597 EnterCriticalSection(&(transport->ReadLock));
1598 EnterCriticalSection(&(transport->WriteLock));
1601 freerdp_tls_free(transport->tls);
1602 transport->tls = NULL;
1606 if (transport->frontBio)
1607 BIO_free_all(transport->frontBio);
1612 tsg_free(transport->tsg);
1613 transport->tsg = NULL;
1618 rdg_free(transport->rdg);
1619 transport->rdg = NULL;
1624 wst_free(transport->wst);
1625 transport->wst = NULL;
1628 transport->frontBio = NULL;
1629 transport->layer = TRANSPORT_LAYER_TCP;
1630 transport->earlyUserAuth = FALSE;
1631 LeaveCriticalSection(&(transport->WriteLock));
1632 LeaveCriticalSection(&(transport->ReadLock));
1636 rdpTransport* transport_new(rdpContext* context)
1638 rdpTransport* transport = (rdpTransport*)calloc(1,
sizeof(rdpTransport));
1640 WINPR_ASSERT(context);
1644 transport->log = WLog_Get(TAG);
1646 if (!transport->log)
1650 transport->io.TCPConnect = freerdp_tcp_default_connect;
1651 transport->io.TLSConnect = transport_default_connect_tls;
1652 transport->io.TLSAccept = transport_default_accept_tls;
1653 transport->io.TransportAttach = transport_default_attach;
1654 transport->io.TransportDisconnect = transport_default_disconnect;
1655 transport->io.ReadPdu = transport_default_read_pdu;
1656 transport->io.WritePdu = transport_default_write;
1657 transport->io.ReadBytes = transport_read_layer;
1658 transport->io.GetPublicKey = transport_default_get_public_key;
1659 transport->io.SetBlockingMode = transport_default_set_blocking_mode;
1660 transport->io.ConnectLayer = transport_default_connect_layer;
1661 transport->io.AttachLayer = transport_default_attach_layer;
1663 transport->context = context;
1664 transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
1666 if (!transport->ReceivePool)
1670 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1672 if (!transport->ReceiveBuffer)
1675 transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1677 if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
1680 transport->rereadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1682 if (!transport->rereadEvent || transport->rereadEvent == INVALID_HANDLE_VALUE)
1685 transport->ioEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1687 if (!transport->ioEvent || transport->ioEvent == INVALID_HANDLE_VALUE)
1690 transport->haveMoreBytesToRead = FALSE;
1691 transport->blocking = TRUE;
1692 transport->GatewayEnabled = FALSE;
1693 transport->layer = TRANSPORT_LAYER_TCP;
1695 if (!InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000))
1698 if (!InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000))
1703 WINPR_PRAGMA_DIAG_PUSH
1704 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1705 transport_free(transport);
1706 WINPR_PRAGMA_DIAG_POP
1710 void transport_free(rdpTransport* transport)
1715 transport_disconnect(transport);
1717 EnterCriticalSection(&(transport->ReadLock));
1718 if (transport->ReceiveBuffer)
1719 Stream_Release(transport->ReceiveBuffer);
1720 LeaveCriticalSection(&(transport->ReadLock));
1722 (void)StreamPool_WaitForReturn(transport->ReceivePool, INFINITE);
1724 EnterCriticalSection(&(transport->ReadLock));
1725 EnterCriticalSection(&(transport->WriteLock));
1727 nla_free(transport->nla);
1728 StreamPool_Free(transport->ReceivePool);
1729 (void)CloseHandle(transport->connectedEvent);
1730 (void)CloseHandle(transport->rereadEvent);
1731 (void)CloseHandle(transport->ioEvent);
1733 LeaveCriticalSection(&(transport->ReadLock));
1734 DeleteCriticalSection(&(transport->ReadLock));
1736 LeaveCriticalSection(&(transport->WriteLock));
1737 DeleteCriticalSection(&(transport->WriteLock));
1741 BOOL transport_set_io_callbacks(rdpTransport* transport,
const rdpTransportIo* io_callbacks)
1743 if (!transport || !io_callbacks)
1746 transport->io = *io_callbacks;
1750 const rdpTransportIo* transport_get_io_callbacks(rdpTransport* transport)
1754 return &transport->io;
1757 rdpContext* transport_get_context(rdpTransport* transport)
1759 WINPR_ASSERT(transport);
1760 return transport->context;
1763 rdpTransport* freerdp_get_transport(rdpContext* context)
1765 WINPR_ASSERT(context);
1766 WINPR_ASSERT(context->rdp);
1767 return context->rdp->transport;
1770 BOOL transport_set_nla(rdpTransport* transport, rdpNla* nla)
1772 WINPR_ASSERT(transport);
1773 nla_free(transport->nla);
1774 transport->nla = nla;
1778 rdpNla* transport_get_nla(rdpTransport* transport)
1780 WINPR_ASSERT(transport);
1781 return transport->nla;
1784 BOOL transport_set_tls(rdpTransport* transport, rdpTls* tls)
1786 WINPR_ASSERT(transport);
1787 freerdp_tls_free(transport->tls);
1788 transport->tls = tls;
1792 rdpTls* transport_get_tls(rdpTransport* transport)
1794 WINPR_ASSERT(transport);
1795 return transport->tls;
1798 BOOL transport_set_tsg(rdpTransport* transport, rdpTsg* tsg)
1800 WINPR_ASSERT(transport);
1801 tsg_free(transport->tsg);
1802 transport->tsg = tsg;
1806 rdpTsg* transport_get_tsg(rdpTransport* transport)
1808 WINPR_ASSERT(transport);
1809 return transport->tsg;
1812 wStream* transport_take_from_pool(rdpTransport* transport,
size_t size)
1814 WINPR_ASSERT(transport);
1815 if (!transport->frontBio)
1817 return StreamPool_Take(transport->ReceivePool, size);
1820 ULONG transport_get_bytes_sent(rdpTransport* transport, BOOL resetCount)
1823 WINPR_ASSERT(transport);
1824 rc = transport->written;
1826 transport->written = 0;
1830 TRANSPORT_LAYER transport_get_layer(rdpTransport* transport)
1832 WINPR_ASSERT(transport);
1833 return transport->layer;
1836 BOOL transport_set_layer(rdpTransport* transport, TRANSPORT_LAYER layer)
1838 WINPR_ASSERT(transport);
1839 transport->layer = layer;
1843 BOOL transport_set_connected_event(rdpTransport* transport)
1845 WINPR_ASSERT(transport);
1846 return SetEvent(transport->connectedEvent);
1849 BOOL transport_set_recv_callbacks(rdpTransport* transport, TransportRecv recv,
void* extra)
1851 WINPR_ASSERT(transport);
1852 transport->ReceiveCallback = recv;
1853 transport->ReceiveExtra = extra;
1857 BOOL transport_get_blocking(rdpTransport* transport)
1859 WINPR_ASSERT(transport);
1860 return transport->blocking;
1863 BOOL transport_set_blocking(rdpTransport* transport, BOOL blocking)
1865 WINPR_ASSERT(transport);
1866 transport->blocking = blocking;
1870 BOOL transport_have_more_bytes_to_read(rdpTransport* transport)
1872 WINPR_ASSERT(transport);
1873 return transport->haveMoreBytesToRead;
1876 int transport_tcp_connect(rdpTransport* transport,
const char* hostname,
int port, DWORD timeout)
1878 rdpContext* context = transport_get_context(transport);
1879 WINPR_ASSERT(context);
1880 WINPR_ASSERT(context->settings);
1881 return IFCALLRESULT(-1, transport->io.TCPConnect, context, context->settings, hostname, port,
1885 HANDLE transport_get_front_bio(rdpTransport* transport)
1887 HANDLE hEvent = NULL;
1888 WINPR_ASSERT(transport);
1889 WINPR_ASSERT(transport->frontBio);
1891 BIO_get_event(transport->frontBio, &hEvent);
1895 BOOL transport_io_callback_set_event(rdpTransport* transport, BOOL set)
1897 WINPR_ASSERT(transport);
1898 transport->useIoEvent = TRUE;
1900 return ResetEvent(transport->ioEvent);
1901 return SetEvent(transport->ioEvent);
1904 void transport_set_early_user_auth_mode(rdpTransport* transport, BOOL EUAMode)
1906 WINPR_ASSERT(transport);
1907 transport->earlyUserAuth = EUAMode;
1908 WLog_Print(transport->log, WLOG_DEBUG,
"Early User Auth Mode: %s", EUAMode ?
"on" :
"off");
1911 rdpTransportLayer* transport_layer_new(rdpTransport* transport,
size_t contextSize)
1919 layer->userContext = calloc(1, contextSize);
1920 if (!layer->userContext)
1935 IFCALL(layer->Close, layer->userContext);
1936 free(layer->userContext);
1940 static int transport_layer_bio_write(BIO* bio,
const char* buf,
int size)
1953 BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
1955 int status = IFCALLRESULT(-1, layer->Write, layer->userContext, buf, size);
1957 if (status >= 0 && status < size)
1958 BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
1963 static int transport_layer_bio_read(BIO* bio,
char* buf,
int size)
1976 BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
1978 int status = IFCALLRESULT(-1, layer->Read, layer->userContext, buf, size);
1981 BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
1986 static int transport_layer_bio_puts(BIO* bio,
const char* str)
1991 static int transport_layer_bio_gets(BIO* bio,
char* str,
int size)
1996 static long transport_layer_bio_ctrl(BIO* bio,
int cmd,
long arg1,
void* arg2)
2007 case BIO_C_GET_EVENT:
2008 *((HANDLE*)arg2) = IFCALLRESULT(NULL, layer->GetEvent, layer->userContext);
2012 case BIO_C_SET_NONBLOCK:
2016 case BIO_C_WAIT_READ:
2018 int timeout = (int)arg1;
2019 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, FALSE,
2020 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2032 case BIO_C_WAIT_WRITE:
2034 int timeout = (int)arg1;
2035 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, TRUE,
2036 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2048 case BIO_CTRL_GET_CLOSE:
2049 status = BIO_get_shutdown(bio);
2052 case BIO_CTRL_SET_CLOSE:
2053 BIO_set_shutdown(bio, (
int)arg1);
2057 case BIO_CTRL_FLUSH:
2070 static int transport_layer_bio_new(BIO* bio)
2074 BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
2075 BIO_set_init(bio, 1);
2079 static int transport_layer_bio_free(BIO* bio)
2086 transport_layer_free(layer);
2088 BIO_set_data(bio, NULL);
2089 BIO_set_init(bio, 0);
2090 BIO_set_flags(bio, 0);
2095 BIO_METHOD* BIO_s_transport_layer(
void)
2097 static BIO_METHOD* bio_methods = NULL;
2099 if (bio_methods == NULL)
2101 if (!(bio_methods = BIO_meth_new(BIO_TYPE_SIMPLE,
"TransportLayer")))
2104 BIO_meth_set_write(bio_methods, transport_layer_bio_write);
2105 BIO_meth_set_read(bio_methods, transport_layer_bio_read);
2106 BIO_meth_set_puts(bio_methods, transport_layer_bio_puts);
2107 BIO_meth_set_gets(bio_methods, transport_layer_bio_gets);
2108 BIO_meth_set_ctrl(bio_methods, transport_layer_bio_ctrl);
2109 BIO_meth_set_create(bio_methods, transport_layer_bio_new);
2110 BIO_meth_set_destroy(bio_methods, transport_layer_bio_free);
FREERDP_API const char * freerdp_settings_get_server_name(const rdpSettings *settings)
A helper function to return the correct server name.