20#include <freerdp/config.h>
24#include <winpr/assert.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>
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;
103 void* userContextShadowPtr;
104} rdpTransportLayerInt;
106static void transport_ssl_cb(
const SSL* ssl,
int where,
int ret)
108 if (where & SSL_CB_ALERT)
110 rdpTransport* transport = (rdpTransport*)SSL_get_app_data(ssl);
111 WINPR_ASSERT(transport);
115 case (SSL3_AL_FATAL << 8) | SSL_AD_ACCESS_DENIED:
117 if (!freerdp_get_last_error(transport_get_context(transport)))
119 WLog_Print(transport->log, WLOG_ERROR,
"ACCESS DENIED");
120 freerdp_set_last_error_log(transport_get_context(transport),
121 FREERDP_ERROR_AUTHENTICATION_FAILED);
126 case (SSL3_AL_FATAL << 8) | SSL_AD_INTERNAL_ERROR:
128 if (transport->NlaMode)
130 if (!freerdp_get_last_error(transport_get_context(transport)))
134 kret = nla_get_error(transport->nla);
136 kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
137 freerdp_set_last_error_log(transport_get_context(transport), kret);
143 case (SSL3_AL_WARNING << 8) | SSL3_AD_CLOSE_NOTIFY:
147 WLog_Print(transport->log, WLOG_WARN,
148 "Unhandled SSL error (where=%d, ret=%d [%s, %s])", where, ret,
149 SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
156wStream* transport_send_stream_init(WINPR_ATTR_UNUSED rdpTransport* transport,
size_t size)
158 WINPR_ASSERT(transport);
160 return Stream_New(NULL, size);
163BOOL transport_attach(rdpTransport* transport,
int sockfd)
167 return IFCALLRESULT(FALSE, transport->io.TransportAttach, transport, sockfd);
170static BOOL transport_default_attach(rdpTransport* transport,
int sockfd)
172 BIO* socketBio = NULL;
173 BIO* bufferedBio = NULL;
174 const rdpSettings* settings = NULL;
175 rdpContext* context = transport_get_context(transport);
179 WLog_WARN(TAG,
"Running peer without socket (sockfd=%d)", sockfd);
183 settings = context->settings;
184 WINPR_ASSERT(settings);
188 if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
191 socketBio = BIO_new(BIO_s_simple_socket());
197 bufferedBio = BIO_new(BIO_s_buffered_socket());
203 bufferedBio = BIO_push(bufferedBio, socketBio);
212 BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
214 EnterCriticalSection(&(transport->ReadLock));
215 EnterCriticalSection(&(transport->WriteLock));
216 transport->frontBio = bufferedBio;
217 LeaveCriticalSection(&(transport->WriteLock));
218 LeaveCriticalSection(&(transport->ReadLock));
224 BIO_free_all(socketBio);
226 closesocket((SOCKET)sockfd);
231BOOL transport_connect_rdp(rdpTransport* transport)
236 switch (utils_authenticate(transport_get_context(transport)->instance, AUTH_RDP, FALSE))
240 case AUTH_NO_CREDENTIALS:
243 freerdp_set_last_error_if_not(transport_get_context(transport),
244 FREERDP_ERROR_CONNECT_CANCELLED);
251BOOL transport_connect_tls(rdpTransport* transport)
253 const rdpSettings* settings = NULL;
254 rdpContext* context = transport_get_context(transport);
256 settings = context->settings;
257 WINPR_ASSERT(settings);
260 if (settings->SelectedProtocol == PROTOCOL_SSL)
262 switch (utils_authenticate(context->instance, AUTH_TLS, FALSE))
266 case AUTH_NO_CREDENTIALS:
269 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
276 return IFCALLRESULT(FALSE, transport->io.TLSConnect, transport);
279static BOOL transport_default_connect_tls(rdpTransport* transport)
283 rdpContext* context = NULL;
284 rdpSettings* settings = NULL;
286 WINPR_ASSERT(transport);
288 context = transport_get_context(transport);
289 WINPR_ASSERT(context);
291 settings = context->settings;
292 WINPR_ASSERT(settings);
294 if (!(tls = freerdp_tls_new(context)))
297 transport->tls = tls;
299 if (transport->GatewayEnabled)
300 transport->layer = TRANSPORT_LAYER_TSG_TLS;
302 transport->layer = TRANSPORT_LAYER_TLS;
304 tls->hostname = settings->ServerHostname;
305 tls->serverName = settings->UserSpecifiedServerName;
306 tls->port = WINPR_ASSERTING_INT_CAST(int32_t, MIN(UINT16_MAX, settings->ServerPort));
311 tls->isGatewayTransport = FALSE;
312 tlsStatus = freerdp_tls_connect(tls, transport->frontBio);
318 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
322 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
328 transport->frontBio = tls->bio;
337 typedef void (*ssl_cb_t)(
const SSL* ssl,
int type,
int val);
338 ssl_cb_t fkt = transport_ssl_cb;
340 BIO_info_cb* bfkt = WINPR_FUNC_PTR_CAST(fkt, BIO_info_cb*);
341 BIO_callback_ctrl(tls->bio, BIO_CTRL_SET_CALLBACK, bfkt);
342 SSL_set_app_data(tls->ssl, transport);
344 if (!transport->frontBio)
346 WLog_Print(transport->log, WLOG_ERROR,
"unable to prepend a filtering TLS bio");
353BOOL transport_connect_nla(rdpTransport* transport, BOOL earlyUserAuth)
355 rdpContext* context = NULL;
356 rdpSettings* settings = NULL;
361 context = transport_get_context(transport);
362 WINPR_ASSERT(context);
364 settings = context->settings;
365 WINPR_ASSERT(settings);
370 if (!transport_connect_tls(transport))
373 if (!settings->Authentication)
377 rdp->nla = nla_new(context, transport);
382 nla_set_early_user_auth(rdp->nla, earlyUserAuth);
384 transport_set_nla_mode(transport, TRUE);
386 if (settings->AuthenticationServiceClass)
388 if (!nla_set_service_principal(rdp->nla, settings->AuthenticationServiceClass,
393 if (nla_client_begin(rdp->nla) < 0)
395 WLog_Print(transport->log, WLOG_ERROR,
"NLA begin failed");
397 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
399 transport_set_nla_mode(transport, FALSE);
403 return rdp_client_transition_to_state(rdp, CONNECTION_STATE_NLA);
406BOOL transport_connect_rdstls(rdpTransport* transport)
409 rdpRdstls* rdstls = NULL;
410 rdpContext* context = NULL;
412 WINPR_ASSERT(transport);
414 context = transport_get_context(transport);
415 WINPR_ASSERT(context);
417 if (!transport_connect_tls(transport))
420 rdstls = rdstls_new(context, transport);
424 transport_set_rdstls_mode(transport, TRUE);
426 if (rdstls_authenticate(rdstls) < 0)
428 WLog_Print(transport->log, WLOG_ERROR,
"RDSTLS authentication failed");
429 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
433 transport_set_rdstls_mode(transport, FALSE);
440BOOL transport_connect_aad(rdpTransport* transport)
442 rdpContext* context = NULL;
443 rdpSettings* settings = NULL;
448 context = transport_get_context(transport);
449 WINPR_ASSERT(context);
451 settings = context->settings;
452 WINPR_ASSERT(settings);
457 if (!transport_connect_tls(transport))
460 if (!settings->Authentication)
466 transport_set_aad_mode(transport, TRUE);
468 if (aad_client_begin(rdp->aad) < 0)
470 WLog_Print(transport->log, WLOG_ERROR,
"AAD begin failed");
472 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
474 transport_set_aad_mode(transport, FALSE);
478 return rdp_client_transition_to_state(rdp, CONNECTION_STATE_AAD);
481BOOL transport_connect(rdpTransport* transport,
const char* hostname, UINT16 port, DWORD timeout)
484 rdpSettings* settings = NULL;
485 rdpContext* context = transport_get_context(transport);
486 BOOL rpcFallback = 0;
488 WINPR_ASSERT(context);
489 WINPR_ASSERT(hostname);
491 settings = context->settings;
492 WINPR_ASSERT(settings);
494 rpcFallback = !settings->GatewayHttpTransport;
496 if (transport->GatewayEnabled)
498 if (settings->GatewayUrl)
500 WINPR_ASSERT(!transport->wst);
501 transport->wst = wst_new(context);
506 status = wst_connect(transport->wst, timeout);
510 transport->frontBio = wst_get_front_bio_and_take_ownership(transport->wst);
511 WINPR_ASSERT(transport->frontBio);
512 BIO_set_nonblock(transport->frontBio, 0);
513 transport->layer = TRANSPORT_LAYER_TSG;
518 wst_free(transport->wst);
519 transport->wst = NULL;
522 if (!status && settings->GatewayHttpTransport)
524 WINPR_ASSERT(!transport->rdg);
525 transport->rdg = rdg_new(context);
530 status = rdg_connect(transport->rdg, timeout, &rpcFallback);
534 transport->frontBio = rdg_get_front_bio_and_take_ownership(transport->rdg);
535 WINPR_ASSERT(transport->frontBio);
536 BIO_set_nonblock(transport->frontBio, 0);
537 transport->layer = TRANSPORT_LAYER_TSG;
542 rdg_free(transport->rdg);
543 transport->rdg = NULL;
547 if (!status && settings->GatewayRpcTransport && rpcFallback)
549 WINPR_ASSERT(!transport->tsg);
550 transport->tsg = tsg_new(transport);
556 freerdp_set_last_error_log(context, FREERDP_ERROR_SUCCESS);
557 status = tsg_connect(transport->tsg, hostname, port, timeout);
561 transport->frontBio = tsg_get_bio(transport->tsg);
562 transport->layer = TRANSPORT_LAYER_TSG;
567 tsg_free(transport->tsg);
568 transport->tsg = NULL;
575 const char* proxyHostname = NULL;
576 const char* proxyUsername = NULL;
577 const char* proxyPassword = NULL;
578 BOOL isProxyConnection =
579 proxy_prepare(settings, &proxyHostname, &peerPort, &proxyUsername, &proxyPassword);
582 if (isProxyConnection)
583 layer = transport_connect_layer(transport, proxyHostname, peerPort, timeout);
585 layer = transport_connect_layer(transport, hostname, port, timeout);
590 if (!transport_attach_layer(transport, layer))
592 transport_layer_free(layer);
596 if (isProxyConnection)
598 if (!proxy_connect(context, transport->frontBio, proxyUsername, proxyPassword, hostname,
609BOOL transport_connect_childsession(rdpTransport* transport)
611 WINPR_ASSERT(transport);
613 transport->frontBio = createChildSessionBio();
614 if (!transport->frontBio)
617 transport->layer = TRANSPORT_LAYER_TSG;
621BOOL transport_accept_rdp(rdpTransport* transport)
629BOOL transport_accept_tls(rdpTransport* transport)
633 return IFCALLRESULT(FALSE, transport->io.TLSAccept, transport);
636static BOOL transport_default_accept_tls(rdpTransport* transport)
638 rdpContext* context = transport_get_context(transport);
639 rdpSettings* settings = NULL;
641 WINPR_ASSERT(context);
643 settings = context->settings;
644 WINPR_ASSERT(settings);
647 transport->tls = freerdp_tls_new(context);
649 transport->layer = TRANSPORT_LAYER_TLS;
651 if (!freerdp_tls_accept(transport->tls, transport->frontBio, settings))
654 transport->frontBio = transport->tls->bio;
658BOOL transport_accept_nla(rdpTransport* transport)
660 rdpContext* context = transport_get_context(transport);
661 rdpSettings* settings = NULL;
663 WINPR_ASSERT(context);
665 settings = context->settings;
666 WINPR_ASSERT(settings);
668 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
673 if (!settings->Authentication)
678 transport->nla = nla_new(context, transport);
679 transport_set_nla_mode(transport, TRUE);
682 if (nla_authenticate(transport->nla) < 0)
684 WLog_Print(transport->log, WLOG_ERROR,
"client authentication failure");
685 transport_set_nla_mode(transport, FALSE);
686 nla_free(transport->nla);
687 transport->nla = NULL;
688 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
689 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
690 freerdp_tls_send_alert(transport->tls);
695 transport_set_nla_mode(transport, FALSE);
699BOOL transport_accept_rdstls(rdpTransport* transport)
702 rdpRdstls* rdstls = NULL;
703 rdpContext* context = NULL;
705 WINPR_ASSERT(transport);
707 context = transport_get_context(transport);
708 WINPR_ASSERT(context);
710 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
713 rdstls = rdstls_new(context, transport);
717 transport_set_rdstls_mode(transport, TRUE);
719 if (rdstls_authenticate(rdstls) < 0)
721 WLog_Print(transport->log, WLOG_ERROR,
"client authentication failure");
722 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
723 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
724 freerdp_tls_send_alert(transport->tls);
728 transport_set_rdstls_mode(transport, FALSE);
735#define WLog_ERR_BIO(transport, biofunc, bio) \
736 transport_bio_error_log(transport, biofunc, bio, __FILE__, __func__, __LINE__)
738static void transport_bio_error_log(rdpTransport* transport, LPCSTR biofunc,
739 WINPR_ATTR_UNUSED BIO* bio, LPCSTR file, LPCSTR func,
742 unsigned long sslerr = 0;
746 WINPR_ASSERT(transport);
751 if (level < WLog_GetLogLevel(transport->log))
754 if (ERR_peek_error() == 0)
756 char ebuffer[256] = { 0 };
757 const char* fmt =
"%s returned a system error %d: %s";
759 fmt =
"%s retries exceeded";
760 WLog_PrintMessage(transport->log, WLOG_MESSAGE_TEXT, level, line, file, func, fmt, biofunc,
761 saveerrno, winpr_strerror(saveerrno, ebuffer,
sizeof(ebuffer)));
765 while ((sslerr = ERR_get_error()))
767 char buf[120] = { 0 };
768 const char* fmt =
"%s returned an error: %s";
770 ERR_error_string_n(sslerr, buf, 120);
771 WLog_PrintMessage(transport->log, WLOG_MESSAGE_TEXT, level, line, file, func, fmt, biofunc,
776static SSIZE_T transport_read_layer(rdpTransport* transport, BYTE* data,
size_t bytes)
780 rdpContext* context = NULL;
782 WINPR_ASSERT(transport);
784 context = transport_get_context(transport);
785 WINPR_ASSERT(context);
790 if (!transport->frontBio || (bytes > SSIZE_MAX))
792 transport->layer = TRANSPORT_LAYER_CLOSED;
793 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
797 while (read < (SSIZE_T)bytes)
799 const SSIZE_T tr = (SSIZE_T)bytes - read;
800 int r = (int)((tr > INT_MAX) ? INT_MAX : tr);
802 int status = BIO_read(transport->frontBio, data + read, r);
804 if (freerdp_shall_disconnect_context(context))
809 if (!transport->frontBio || !BIO_should_retry(transport->frontBio))
812 if (!transport->frontBio)
814 WLog_Print(transport->log, WLOG_ERROR,
"BIO_read: transport->frontBio null");
818 WLog_ERR_BIO(transport,
"BIO_read", transport->frontBio);
819 transport->layer = TRANSPORT_LAYER_CLOSED;
820 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
825 if (!transport->blocking)
830 if (BIO_wait_read(transport->frontBio, 100) < 0)
832 WLog_ERR_BIO(transport,
"BIO_wait_read", transport->frontBio);
839#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
840 VALGRIND_MAKE_MEM_DEFINED(data + read, bytes - read);
843 rdp->inBytes += WINPR_ASSERTING_INT_CAST(uint64_t, status);
863static SSIZE_T transport_read_layer_bytes(rdpTransport* transport,
wStream* s,
size_t toRead)
869 if (toRead > SSIZE_MAX)
872 status = IFCALLRESULT(-1, transport->io.ReadBytes, transport, Stream_Pointer(s), toRead);
877 Stream_Seek(s, (
size_t)status);
878 return status == (SSIZE_T)toRead ? 1 : 0;
893int transport_read_pdu(rdpTransport* transport,
wStream* s)
897 return IFCALLRESULT(-1, transport->io.ReadPdu, transport, s);
900static SSIZE_T parse_nla_mode_pdu(rdpTransport* transport,
wStream* stream)
902 SSIZE_T pduLength = 0;
904 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
911 UINT8 typeEncoding = 0;
912 if (Stream_GetRemainingLength(s) < 1)
914 Stream_Read_UINT8(s, typeEncoding);
915 if (typeEncoding == 0x30)
918 UINT8 lengthEncoding = 0;
919 if (Stream_GetRemainingLength(s) < 1)
921 Stream_Read_UINT8(s, lengthEncoding);
922 if (lengthEncoding & 0x80)
924 if ((lengthEncoding & ~(0x80)) == 1)
927 if (Stream_GetRemainingLength(s) < 1)
929 Stream_Read_UINT8(s, length);
933 else if ((lengthEncoding & ~(0x80)) == 2)
937 if (Stream_GetRemainingLength(s) < 2)
939 Stream_Read_UINT16_BE(s, length);
945 WLog_Print(transport->log, WLOG_ERROR,
"Error reading TSRequest!");
951 pduLength = lengthEncoding;
959static SSIZE_T parse_default_mode_pdu(rdpTransport* transport,
wStream* stream)
961 SSIZE_T pduLength = 0;
963 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
966 if (Stream_GetRemainingLength(s) < 1)
968 Stream_Read_UINT8(s, version);
973 if (Stream_GetRemainingLength(s) < 3)
976 Stream_Read_UINT16_BE(s, length);
980 if ((pduLength < 7) || (pduLength > 0xFFFF))
982 WLog_Print(transport->log, WLOG_ERROR,
"tpkt - invalid pduLength: %" PRIdz, pduLength);
990 if (Stream_GetRemainingLength(s) < 1)
992 Stream_Read_UINT8(s, length1);
996 if (Stream_GetRemainingLength(s) < 1)
998 Stream_Read_UINT8(s, length2);
999 pduLength = ((length1 & 0x7F) << 8) | length2;
1002 pduLength = length1;
1009 if (pduLength < 3 || pduLength > 0x8000)
1011 WLog_Print(transport->log, WLOG_ERROR,
"fast path - invalid pduLength: %" PRIdz,
1020SSIZE_T transport_parse_pdu(rdpTransport* transport,
wStream* s, BOOL* incomplete)
1022 SSIZE_T pduLength = 0;
1033 Stream_SealLength(s);
1034 if (transport->NlaMode)
1035 pduLength = parse_nla_mode_pdu(transport, s);
1036 else if (transport->RdstlsMode)
1037 pduLength = rdstls_parse_pdu(transport->log, s);
1039 pduLength = parse_default_mode_pdu(transport, s);
1044 const size_t len = Stream_Length(s);
1045 if (len > WINPR_ASSERTING_INT_CAST(
size_t, pduLength))
1049 *incomplete = len < WINPR_ASSERTING_INT_CAST(
size_t, pduLength);
1054static int transport_default_read_pdu(rdpTransport* transport,
wStream* s)
1056 BOOL incomplete = 0;
1058 size_t pduLength = 0;
1059 size_t position = 0;
1061 WINPR_ASSERT(transport);
1066 if (transport->AadMode)
1071 const SSIZE_T rc = transport_read_layer(transport, &c, 1);
1073 return (rc == 0) ? 0 : -1;
1074 if (!Stream_EnsureRemainingCapacity(s, 1))
1076 Stream_Write_UINT8(s, c);
1077 }
while (c !=
'\0');
1079 else if (transport->earlyUserAuth)
1081 if (!Stream_EnsureCapacity(s, 4))
1083 const SSIZE_T rc = transport_read_layer_bytes(transport, s, 4);
1085 return (rc == 0) ? 0 : -1;
1090 status = transport_parse_pdu(transport, s, &incomplete);
1091 while ((status == 0) && incomplete)
1093 if (!Stream_EnsureRemainingCapacity(s, 1))
1095 SSIZE_T rc = transport_read_layer_bytes(transport, s, 1);
1100 status = transport_parse_pdu(transport, s, &incomplete);
1106 pduLength = (size_t)status;
1109 if (!Stream_EnsureCapacity(s, pduLength))
1112 position = Stream_GetPosition(s);
1113 if (position > pduLength)
1115 else if (position < pduLength)
1117 status = transport_read_layer_bytes(transport, s, pduLength - position);
1120 if ((status < INT32_MIN) || (status > INT32_MAX))
1126 if (Stream_GetPosition(s) >= pduLength)
1127 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength,
1128 WLOG_PACKET_INBOUND);
1131 Stream_SealLength(s);
1132 Stream_SetPosition(s, 0);
1133 const size_t len = Stream_Length(s);
1134 if (len > INT32_MAX)
1139int transport_write(rdpTransport* transport,
wStream* s)
1144 return IFCALLRESULT(-1, transport->io.WritePdu, transport, s);
1147static int transport_default_write(rdpTransport* transport,
wStream* s)
1150 rdpContext* context = transport_get_context(transport);
1152 WINPR_ASSERT(transport);
1153 WINPR_ASSERT(context);
1160 rdpRdp* rdp = context->rdp;
1164 EnterCriticalSection(&(transport->WriteLock));
1165 if (!transport->frontBio)
1168 size_t length = Stream_GetPosition(s);
1169 size_t writtenlength = length;
1170 Stream_SetPosition(s, 0);
1174 rdp->outBytes += length;
1175 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
1181 const int towrite = (length > INT32_MAX) ? INT32_MAX : (int)length;
1182 status = BIO_write(transport->frontBio, Stream_ConstPointer(s), towrite);
1190 if (!BIO_should_retry(transport->frontBio))
1192 WLog_ERR_BIO(transport,
"BIO_should_retry", transport->frontBio);
1197 if (!transport->blocking)
1199 WLog_ERR_BIO(transport,
"BIO_write", transport->frontBio);
1203 if (BIO_wait_write(transport->frontBio, 100) < 0)
1205 WLog_ERR_BIO(transport,
"BIO_wait_write", transport->frontBio);
1213 WINPR_ASSERT(context->settings);
1214 if (transport->blocking || context->settings->WaitForOutputBufferFlush)
1216 while (BIO_write_blocked(transport->frontBio))
1218 if (BIO_wait_write(transport->frontBio, 100) < 0)
1220 WLog_Print(transport->log, WLOG_ERROR,
"error when selecting for write");
1225 if (BIO_flush(transport->frontBio) < 1)
1227 WLog_Print(transport->log, WLOG_ERROR,
"error when flushing outputBuffer");
1234 const size_t ustatus = (size_t)status;
1235 if (ustatus > length)
1242 Stream_Seek(s, ustatus);
1245 transport->written += writtenlength;
1251 transport->layer = TRANSPORT_LAYER_CLOSED;
1252 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1255 LeaveCriticalSection(&(transport->WriteLock));
1261BOOL transport_get_public_key(rdpTransport* transport,
const BYTE** data, DWORD* length)
1263 return IFCALLRESULT(FALSE, transport->io.GetPublicKey, transport, data, length);
1266static BOOL transport_default_get_public_key(rdpTransport* transport,
const BYTE** data,
1269 rdpTls* tls = transport_get_tls(transport);
1273 *data = tls->PublicKey;
1274 *length = tls->PublicKeyLength;
1279DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count)
1283 WINPR_ASSERT(transport);
1284 WINPR_ASSERT(events);
1285 WINPR_ASSERT(count > 0);
1291 WLog_Print(transport->log, WLOG_ERROR,
"provided handles array is too small");
1295 events[nCount++] = transport->rereadEvent;
1297 if (transport->useIoEvent)
1301 events[nCount++] = transport->ioEvent;
1305 if (!transport->GatewayEnabled)
1309 if (nCount >= count)
1311 WLog_Print(transport->log, WLOG_ERROR,
1312 "provided handles array is too small (count=%" PRIu32
" nCount=%" PRIu32
1318 if (transport->frontBio)
1320 if (BIO_get_event(transport->frontBio, &events[nCount]) != 1)
1322 WLog_Print(transport->log, WLOG_ERROR,
"error getting the frontBio handle");
1334 rdg_get_event_handles(transport->rdg, &events[nCount], count - nCount);
1341 else if (transport->tsg)
1344 tsg_get_event_handles(transport->tsg, &events[nCount], count - nCount);
1351 else if (transport->wst)
1354 wst_get_event_handles(transport->wst, &events[nCount], count - nCount);
1366#if defined(WITH_FREERDP_DEPRECATED)
1367void transport_get_fds(rdpTransport* transport,
void** rfds,
int* rcount)
1370 HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
1372 WINPR_ASSERT(transport);
1374 WINPR_ASSERT(rcount);
1376 nCount = transport_get_event_handles(transport, events, ARRAYSIZE(events));
1377 *rcount = nCount + 1;
1379 for (DWORD index = 0; index < nCount; index++)
1381 rfds[index] = GetEventWaitObject(events[index]);
1384 rfds[nCount] = GetEventWaitObject(transport->rereadEvent);
1388BOOL transport_is_write_blocked(rdpTransport* transport)
1390 WINPR_ASSERT(transport);
1391 WINPR_ASSERT(transport->frontBio);
1392 return BIO_write_blocked(transport->frontBio) != 0;
1395int transport_drain_output_buffer(rdpTransport* transport)
1397 BOOL status = FALSE;
1399 WINPR_ASSERT(transport);
1400 WINPR_ASSERT(transport->frontBio);
1401 if (BIO_write_blocked(transport->frontBio))
1403 if (BIO_flush(transport->frontBio) < 1)
1406 const long rc = BIO_write_blocked(transport->frontBio);
1413int transport_check_fds(rdpTransport* transport)
1416 state_run_t recv_status = STATE_RUN_FAILED;
1418 rdpContext* context = transport_get_context(transport);
1420 WINPR_ASSERT(context);
1422 if (transport->layer == TRANSPORT_LAYER_CLOSED)
1424 WLog_Print(transport->log, WLOG_DEBUG,
"transport_check_fds: transport layer closed");
1425 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1438 if ((status = transport_read_pdu(transport, transport->ReceiveBuffer)) <= 0)
1441 WLog_Print(transport->log, WLOG_DEBUG,
"transport_check_fds: transport_read_pdu() - %i",
1443 if (transport->haveMoreBytesToRead)
1445 transport->haveMoreBytesToRead = FALSE;
1446 (void)ResetEvent(transport->rereadEvent);
1451 received = transport->ReceiveBuffer;
1452 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1453 if (!transport->ReceiveBuffer)
1455 Stream_Release(received);
1465 WINPR_ASSERT(transport->ReceiveCallback);
1466 recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
1467 Stream_Release(received);
1469 if (state_run_failed(recv_status))
1471 char buffer[64] = { 0 };
1472 WLog_Print(transport->log, WLOG_ERROR,
1473 "transport_check_fds: transport->ReceiveCallback() - %s",
1474 state_run_result_string(recv_status, buffer, ARRAYSIZE(buffer)));
1481 if (!transport->haveMoreBytesToRead)
1483 transport->haveMoreBytesToRead = TRUE;
1484 (void)SetEvent(transport->rereadEvent);
1489BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1491 WINPR_ASSERT(transport);
1493 return IFCALLRESULT(FALSE, transport->io.SetBlockingMode, transport, blocking);
1496static BOOL transport_default_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1498 WINPR_ASSERT(transport);
1500 transport->blocking = blocking;
1502 if (transport->frontBio)
1504 if (!BIO_set_nonblock(transport->frontBio, blocking ? FALSE : TRUE))
1511rdpTransportLayer* transport_connect_layer(rdpTransport* transport,
const char* hostname,
int port,
1514 WINPR_ASSERT(transport);
1516 return IFCALLRESULT(NULL, transport->io.ConnectLayer, transport, hostname, port, timeout);
1519static rdpTransportLayer* transport_default_connect_layer(rdpTransport* transport,
1520 const char* hostname,
int port,
1523 rdpContext* context = transport_get_context(transport);
1524 WINPR_ASSERT(context);
1526 return freerdp_tcp_connect_layer(context, hostname, port, timeout);
1531 WINPR_ASSERT(transport);
1532 WINPR_ASSERT(layer);
1534 return IFCALLRESULT(FALSE, transport->io.AttachLayer, transport, layer);
1537static BOOL transport_default_attach_layer(rdpTransport* transport,
rdpTransportLayer* layer)
1539 BIO* layerBio = BIO_new(BIO_s_transport_layer());
1543 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
1547 bufferedBio = BIO_push(bufferedBio, layerBio);
1552 BIO_set_data(layerBio, layer);
1554 transport->frontBio = bufferedBio;
1560 BIO_free_all(layerBio);
1565void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled)
1567 WINPR_ASSERT(transport);
1568 transport->GatewayEnabled = GatewayEnabled;
1571void transport_set_nla_mode(rdpTransport* transport, BOOL NlaMode)
1573 WINPR_ASSERT(transport);
1574 transport->NlaMode = NlaMode;
1577void transport_set_rdstls_mode(rdpTransport* transport, BOOL RdstlsMode)
1579 WINPR_ASSERT(transport);
1580 transport->RdstlsMode = RdstlsMode;
1583void transport_set_aad_mode(rdpTransport* transport, BOOL AadMode)
1585 WINPR_ASSERT(transport);
1586 transport->AadMode = AadMode;
1589BOOL transport_disconnect(rdpTransport* transport)
1593 return IFCALLRESULT(FALSE, transport->io.TransportDisconnect, transport);
1596static BOOL transport_default_disconnect(rdpTransport* transport)
1603 EnterCriticalSection(&(transport->ReadLock));
1604 EnterCriticalSection(&(transport->WriteLock));
1607 freerdp_tls_free(transport->tls);
1608 transport->tls = NULL;
1612 if (transport->frontBio)
1613 BIO_free_all(transport->frontBio);
1618 tsg_free(transport->tsg);
1619 transport->tsg = NULL;
1624 rdg_free(transport->rdg);
1625 transport->rdg = NULL;
1630 wst_free(transport->wst);
1631 transport->wst = NULL;
1634 transport->frontBio = NULL;
1635 transport->layer = TRANSPORT_LAYER_TCP;
1636 transport->earlyUserAuth = FALSE;
1637 LeaveCriticalSection(&(transport->WriteLock));
1638 LeaveCriticalSection(&(transport->ReadLock));
1642rdpTransport* transport_new(rdpContext* context)
1644 rdpTransport* transport = (rdpTransport*)calloc(1,
sizeof(rdpTransport));
1646 WINPR_ASSERT(context);
1650 transport->log = WLog_Get(TAG);
1652 if (!transport->log)
1655 transport->context = context;
1656 transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
1658 if (!transport->ReceivePool)
1662 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1664 if (!transport->ReceiveBuffer)
1667 transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1669 if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
1672 transport->rereadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1674 if (!transport->rereadEvent || transport->rereadEvent == INVALID_HANDLE_VALUE)
1677 transport->ioEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1679 if (!transport->ioEvent || transport->ioEvent == INVALID_HANDLE_VALUE)
1682 transport->haveMoreBytesToRead = FALSE;
1683 transport->blocking = TRUE;
1684 transport->GatewayEnabled = FALSE;
1685 transport->layer = TRANSPORT_LAYER_TCP;
1687 if (!InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000))
1690 if (!InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000))
1694 transport->io.TCPConnect = freerdp_tcp_default_connect;
1695 transport->io.TLSConnect = transport_default_connect_tls;
1696 transport->io.TLSAccept = transport_default_accept_tls;
1697 transport->io.TransportAttach = transport_default_attach;
1698 transport->io.TransportDisconnect = transport_default_disconnect;
1699 transport->io.ReadPdu = transport_default_read_pdu;
1700 transport->io.WritePdu = transport_default_write;
1701 transport->io.ReadBytes = transport_read_layer;
1702 transport->io.GetPublicKey = transport_default_get_public_key;
1703 transport->io.SetBlockingMode = transport_default_set_blocking_mode;
1704 transport->io.ConnectLayer = transport_default_connect_layer;
1705 transport->io.AttachLayer = transport_default_attach_layer;
1709 WINPR_PRAGMA_DIAG_PUSH
1710 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1711 transport_free(transport);
1712 WINPR_PRAGMA_DIAG_POP
1716void transport_free(rdpTransport* transport)
1721 transport_disconnect(transport);
1723 EnterCriticalSection(&(transport->ReadLock));
1724 if (transport->ReceiveBuffer)
1725 Stream_Release(transport->ReceiveBuffer);
1726 LeaveCriticalSection(&(transport->ReadLock));
1728 (void)StreamPool_WaitForReturn(transport->ReceivePool, INFINITE);
1730 EnterCriticalSection(&(transport->ReadLock));
1731 EnterCriticalSection(&(transport->WriteLock));
1733 nla_free(transport->nla);
1734 StreamPool_Free(transport->ReceivePool);
1735 (void)CloseHandle(transport->connectedEvent);
1736 (void)CloseHandle(transport->rereadEvent);
1737 (void)CloseHandle(transport->ioEvent);
1739 LeaveCriticalSection(&(transport->ReadLock));
1740 DeleteCriticalSection(&(transport->ReadLock));
1742 LeaveCriticalSection(&(transport->WriteLock));
1743 DeleteCriticalSection(&(transport->WriteLock));
1747BOOL transport_set_io_callbacks(rdpTransport* transport,
const rdpTransportIo* io_callbacks)
1749 if (!transport || !io_callbacks)
1752 transport->io = *io_callbacks;
1756const rdpTransportIo* transport_get_io_callbacks(rdpTransport* transport)
1760 return &transport->io;
1763rdpContext* transport_get_context(rdpTransport* transport)
1765 WINPR_ASSERT(transport);
1766 return transport->context;
1769rdpTransport* freerdp_get_transport(rdpContext* context)
1771 WINPR_ASSERT(context);
1772 WINPR_ASSERT(context->rdp);
1773 return context->rdp->transport;
1776BOOL transport_set_nla(rdpTransport* transport, rdpNla* nla)
1778 WINPR_ASSERT(transport);
1779 nla_free(transport->nla);
1780 transport->nla = nla;
1784rdpNla* transport_get_nla(rdpTransport* transport)
1786 WINPR_ASSERT(transport);
1787 return transport->nla;
1790BOOL transport_set_tls(rdpTransport* transport, rdpTls* tls)
1792 WINPR_ASSERT(transport);
1793 freerdp_tls_free(transport->tls);
1794 transport->tls = tls;
1798rdpTls* transport_get_tls(rdpTransport* transport)
1800 WINPR_ASSERT(transport);
1801 return transport->tls;
1804BOOL transport_set_tsg(rdpTransport* transport, rdpTsg* tsg)
1806 WINPR_ASSERT(transport);
1807 tsg_free(transport->tsg);
1808 transport->tsg = tsg;
1812rdpTsg* transport_get_tsg(rdpTransport* transport)
1814 WINPR_ASSERT(transport);
1815 return transport->tsg;
1818wStream* transport_take_from_pool(rdpTransport* transport,
size_t size)
1820 WINPR_ASSERT(transport);
1821 if (!transport->frontBio)
1823 return StreamPool_Take(transport->ReceivePool, size);
1826UINT64 transport_get_bytes_sent(rdpTransport* transport, BOOL resetCount)
1829 WINPR_ASSERT(transport);
1830 rc = transport->written;
1832 transport->written = 0;
1836TRANSPORT_LAYER transport_get_layer(rdpTransport* transport)
1838 WINPR_ASSERT(transport);
1839 return transport->layer;
1842BOOL transport_set_layer(rdpTransport* transport, TRANSPORT_LAYER layer)
1844 WINPR_ASSERT(transport);
1845 transport->layer = layer;
1849BOOL transport_set_connected_event(rdpTransport* transport)
1851 WINPR_ASSERT(transport);
1852 return SetEvent(transport->connectedEvent);
1855BOOL transport_set_recv_callbacks(rdpTransport* transport, TransportRecv recv,
void* extra)
1857 WINPR_ASSERT(transport);
1858 transport->ReceiveCallback = recv;
1859 transport->ReceiveExtra = extra;
1863BOOL transport_get_blocking(rdpTransport* transport)
1865 WINPR_ASSERT(transport);
1866 return transport->blocking;
1869BOOL transport_set_blocking(rdpTransport* transport, BOOL blocking)
1871 WINPR_ASSERT(transport);
1872 transport->blocking = blocking;
1876BOOL transport_have_more_bytes_to_read(rdpTransport* transport)
1878 WINPR_ASSERT(transport);
1879 return transport->haveMoreBytesToRead;
1882int transport_tcp_connect(rdpTransport* transport,
const char* hostname,
int port, DWORD timeout)
1884 rdpContext* context = transport_get_context(transport);
1885 WINPR_ASSERT(context);
1886 WINPR_ASSERT(context->settings);
1887 return IFCALLRESULT(-1, transport->io.TCPConnect, context, context->settings, hostname, port,
1891HANDLE transport_get_front_bio(rdpTransport* transport)
1893 HANDLE hEvent = NULL;
1894 WINPR_ASSERT(transport);
1895 WINPR_ASSERT(transport->frontBio);
1897 BIO_get_event(transport->frontBio, &hEvent);
1901BOOL transport_io_callback_set_event(rdpTransport* transport, BOOL set)
1903 WINPR_ASSERT(transport);
1904 transport->useIoEvent = TRUE;
1906 return ResetEvent(transport->ioEvent);
1907 return SetEvent(transport->ioEvent);
1910void transport_set_early_user_auth_mode(rdpTransport* transport, BOOL EUAMode)
1912 WINPR_ASSERT(transport);
1913 transport->earlyUserAuth = EUAMode;
1914 WLog_Print(transport->log, WLOG_DEBUG,
"Early User Auth Mode: %s", EUAMode ?
"on" :
"off");
1917rdpTransportLayer* transport_layer_new(WINPR_ATTR_UNUSED rdpTransport* transport,
1920 rdpTransportLayerInt* layer = (rdpTransportLayerInt*)calloc(1,
sizeof(rdpTransportLayerInt));
1926 layer->userContextShadowPtr = calloc(1, contextSize);
1927 if (!layer->userContextShadowPtr)
1933 layer->pub.userContext = layer->userContextShadowPtr;
1940 rdpTransportLayerInt* intern = (rdpTransportLayerInt*)layer;
1944 IFCALL(intern->pub.Close, intern->pub.userContext);
1945 free(intern->userContextShadowPtr);
1949static int transport_layer_bio_write(BIO* bio,
const char* buf,
int size)
1962 BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
1964 int status = IFCALLRESULT(-1, layer->Write, layer->userContext, buf, size);
1966 if (status >= 0 && status < size)
1967 BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
1972static int transport_layer_bio_read(BIO* bio,
char* buf,
int size)
1985 BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
1987 int status = IFCALLRESULT(-1, layer->Read, layer->userContext, buf, size);
1990 BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
1995static int transport_layer_bio_puts(WINPR_ATTR_UNUSED BIO* bio, WINPR_ATTR_UNUSED
const char* str)
2000static int transport_layer_bio_gets(WINPR_ATTR_UNUSED BIO* bio, WINPR_ATTR_UNUSED
char* str,
2001 WINPR_ATTR_UNUSED
int size)
2006static long transport_layer_bio_ctrl(BIO* bio,
int cmd,
long arg1,
void* arg2)
2017 case BIO_C_GET_EVENT:
2018 *((HANDLE*)arg2) = IFCALLRESULT(NULL, layer->GetEvent, layer->userContext);
2022 case BIO_C_SET_NONBLOCK:
2026 case BIO_C_WAIT_READ:
2028 int timeout = (int)arg1;
2029 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, FALSE,
2030 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2042 case BIO_C_WAIT_WRITE:
2044 int timeout = (int)arg1;
2045 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, TRUE,
2046 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2058 case BIO_CTRL_GET_CLOSE:
2059 status = BIO_get_shutdown(bio);
2062 case BIO_CTRL_SET_CLOSE:
2063 BIO_set_shutdown(bio, (
int)arg1);
2067 case BIO_CTRL_FLUSH:
2080static int transport_layer_bio_new(BIO* bio)
2084 BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
2085 BIO_set_init(bio, 1);
2089static int transport_layer_bio_free(BIO* bio)
2096 transport_layer_free(layer);
2098 BIO_set_data(bio, NULL);
2099 BIO_set_init(bio, 0);
2100 BIO_set_flags(bio, 0);
2105BIO_METHOD* BIO_s_transport_layer(
void)
2107 static BIO_METHOD* bio_methods = NULL;
2109 if (bio_methods == NULL)
2111 if (!(bio_methods = BIO_meth_new(BIO_TYPE_SIMPLE,
"TransportLayer")))
2114 BIO_meth_set_write(bio_methods, transport_layer_bio_write);
2115 BIO_meth_set_read(bio_methods, transport_layer_bio_read);
2116 BIO_meth_set_puts(bio_methods, transport_layer_bio_puts);
2117 BIO_meth_set_gets(bio_methods, transport_layer_bio_gets);
2118 BIO_meth_set_ctrl(bio_methods, transport_layer_bio_ctrl);
2119 BIO_meth_set_create(bio_methods, transport_layer_bio_new);
2120 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.