FreeRDP
Loading...
Searching...
No Matches
transport.c
1
20#include <freerdp/config.h>
21
22#include "settings.h"
23
24#include <winpr/assert.h>
25
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>
32
33#include <freerdp/log.h>
34#include <freerdp/error.h>
35#include <freerdp/utils/ringbuffer.h>
36
37#include <openssl/bio.h>
38#include <time.h>
39#include <errno.h>
40#include <fcntl.h>
41
42#ifndef _WIN32
43#include <netdb.h>
44#include <sys/socket.h>
45#endif /* _WIN32 */
46
47#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
48#include <valgrind/memcheck.h>
49#endif
50
51#include "tpkt.h"
52#include "fastpath.h"
53#include "transport.h"
54#include "rdp.h"
55#include "proxy.h"
56#include "utils.h"
57#include "state.h"
58#include "childsession.h"
59
60#include "gateway/rdg.h"
61#include "gateway/wst.h"
62#include "gateway/arm.h"
63
64#define TAG FREERDP_TAG("core.transport")
65
66#define BUFFER_SIZE 16384
67
68struct rdp_transport
69{
70 TRANSPORT_LAYER layer;
71 BIO* frontBio;
72 rdpRdg* rdg;
73 rdpTsg* tsg;
74 rdpWst* wst;
75 rdpTls* tls;
76 rdpContext* context;
77 rdpNla* nla;
78 void* ReceiveExtra;
79 wStream* ReceiveBuffer;
80 TransportRecv ReceiveCallback;
81 wStreamPool* ReceivePool;
82 HANDLE connectedEvent;
83 BOOL NlaMode;
84 BOOL RdstlsMode;
85 BOOL AadMode;
86 BOOL blocking;
87 BOOL GatewayEnabled;
88 BOOL haveReadLock;
89 CRITICAL_SECTION ReadLock;
90 BOOL haveWriteLock;
91 CRITICAL_SECTION WriteLock;
92 UINT64 written;
93 HANDLE rereadEvent;
94 BOOL haveMoreBytesToRead;
95 wLog* log;
96 rdpTransportIo io;
97 HANDLE ioEvent;
98 BOOL useIoEvent;
99 BOOL earlyUserAuth;
100};
101
102typedef struct
103{
105 void* userContextShadowPtr;
106} rdpTransportLayerInt;
107
108static const char* where2str(int where, char* ibuffer, size_t ilen)
109{
110 if (!ibuffer || (ilen < 2))
111 return NULL;
112
113 ibuffer[0] = '[';
114 size_t len = ilen - 1;
115 char* buffer = &ibuffer[1];
116 if (where & SSL_CB_ALERT)
117 winpr_str_append("SSL_CB_ALERT", buffer, len, "|");
118 if (where & SSL_ST_ACCEPT)
119 winpr_str_append("SSL_ST_ACCEPT", buffer, len, "|");
120 if (where & SSL_ST_CONNECT)
121 winpr_str_append("SSL_ST_CONNECT", buffer, len, "|");
122 if (where & SSL_CB_HANDSHAKE_DONE)
123 winpr_str_append("SSL_CB_HANDSHAKE_DONE", buffer, len, "|");
124 if (where & SSL_CB_HANDSHAKE_START)
125 winpr_str_append("SSL_CB_HANDSHAKE_START", buffer, len, "|");
126 if (where & SSL_CB_WRITE)
127 winpr_str_append("SSL_CB_WRITE", buffer, len, "|");
128 if (where & SSL_CB_READ)
129 winpr_str_append("SSL_CB_READ", buffer, len, "|");
130 if (where & SSL_CB_EXIT)
131 winpr_str_append("SSL_CB_EXIT", buffer, len, "|");
132 if (where & SSL_CB_LOOP)
133 winpr_str_append("SSL_CB_LOOP", buffer, len, "|");
134
135 char nr[32] = { 0 };
136 (void)_snprintf(nr, sizeof(nr), "]{0x%08" PRIx32 "}", (unsigned)where);
137 winpr_str_append(nr, buffer, len, "");
138 return buffer;
139}
140
141static void transport_ssl_cb(const SSL* ssl, int where, int ret)
142{
143 if (where & SSL_CB_ALERT)
144 {
145 char buffer[128] = { 0 };
146 rdpTransport* transport = (rdpTransport*)SSL_get_app_data(ssl);
147 WINPR_ASSERT(transport);
148
149 switch (ret)
150 {
151 case (SSL3_AL_FATAL << 8) | SSL_AD_ACCESS_DENIED:
152 {
153 if (!freerdp_get_last_error(transport_get_context(transport)))
154 {
155 WLog_Print(transport->log, WLOG_ERROR, "where=%s ACCESS DENIED",
156 where2str(where, buffer, sizeof(buffer)));
157 freerdp_set_last_error_log(transport_get_context(transport),
158 FREERDP_ERROR_AUTHENTICATION_FAILED);
159 }
160 }
161 break;
162
163 case (SSL3_AL_FATAL << 8) | SSL_AD_INTERNAL_ERROR:
164 {
165 WLog_Print(transport->log, WLOG_WARN, "SSL error (where=%s, ret=%d [%s, %s])",
166 where2str(where, buffer, sizeof(buffer)), ret,
167 SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
168
169 if (transport->NlaMode)
170 {
171 if (!freerdp_get_last_error(transport_get_context(transport)))
172 {
173 UINT32 kret = 0;
174 if (transport->nla)
175 kret = nla_get_error(transport->nla);
176 if (kret == 0)
177 kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
178 freerdp_set_last_error_log(transport_get_context(transport), kret);
179 }
180 }
181 }
182 break;
183
184 case (SSL3_AL_WARNING << 8) | SSL3_AD_CLOSE_NOTIFY:
185 WLog_Print(transport->log, WLOG_DEBUG, "SSL warning (where=%s, ret=%d [%s, %s])",
186 where2str(where, buffer, sizeof(buffer)), ret,
187 SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
188 break;
189
190 default:
191 WLog_Print(transport->log, WLOG_WARN,
192 "Unhandled SSL error (where=%s, ret=%d [%s, %s])",
193 where2str(where, buffer, sizeof(buffer)), ret,
194 SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
195 break;
196 }
197 }
198}
199
200wStream* transport_send_stream_init(WINPR_ATTR_UNUSED rdpTransport* transport, size_t size)
201{
202 WINPR_ASSERT(transport);
203
204 return Stream_New(NULL, size);
205}
206
207BOOL transport_attach(rdpTransport* transport, int sockfd)
208{
209 if (!transport)
210 return FALSE;
211 return IFCALLRESULT(FALSE, transport->io.TransportAttach, transport, sockfd);
212}
213
214static BOOL transport_default_attach(rdpTransport* transport, int sockfd)
215{
216 BIO* socketBio = NULL;
217 BIO* bufferedBio = NULL;
218 const rdpSettings* settings = NULL;
219 rdpContext* context = transport_get_context(transport);
220
221 if (sockfd < 0)
222 {
223 WLog_WARN(TAG, "Running peer without socket (sockfd=%d)", sockfd);
224 return TRUE;
225 }
226
227 settings = context->settings;
228 WINPR_ASSERT(settings);
229
230 if (sockfd >= 0)
231 {
232 if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
233 goto fail;
234
235 socketBio = BIO_new(BIO_s_simple_socket());
236
237 if (!socketBio)
238 goto fail;
239 }
240
241 bufferedBio = BIO_new(BIO_s_buffered_socket());
242 if (!bufferedBio)
243 goto fail;
244
245 if (socketBio)
246 {
247 bufferedBio = BIO_push(bufferedBio, socketBio);
248 if (!bufferedBio)
249 goto fail;
250
251 /* Attach the socket only when this function can no longer fail.
252 * This ensures solid ownership:
253 * - if this function fails, the caller is responsible to clean up
254 * - if this function is successful, the caller MUST NOT close the socket any more.
255 */
256 BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
257 }
258 EnterCriticalSection(&(transport->ReadLock));
259 EnterCriticalSection(&(transport->WriteLock));
260 transport->frontBio = bufferedBio;
261 LeaveCriticalSection(&(transport->WriteLock));
262 LeaveCriticalSection(&(transport->ReadLock));
263
264 return TRUE;
265fail:
266
267 if (socketBio)
268 BIO_free_all(socketBio);
269 else
270 closesocket((SOCKET)sockfd);
271
272 return FALSE;
273}
274
275BOOL transport_connect_rdp(rdpTransport* transport)
276{
277 if (!transport)
278 return FALSE;
279
280 switch (utils_authenticate(transport_get_context(transport)->instance, AUTH_RDP, FALSE))
281 {
282 case AUTH_SKIP:
283 case AUTH_SUCCESS:
284 case AUTH_NO_CREDENTIALS:
285 return TRUE;
286 case AUTH_CANCELLED:
287 freerdp_set_last_error_if_not(transport_get_context(transport),
288 FREERDP_ERROR_CONNECT_CANCELLED);
289 return FALSE;
290 default:
291 return FALSE;
292 }
293}
294
295BOOL transport_connect_tls(rdpTransport* transport)
296{
297 const rdpSettings* settings = NULL;
298 rdpContext* context = transport_get_context(transport);
299
300 settings = context->settings;
301 WINPR_ASSERT(settings);
302
303 /* Only prompt for password if we use TLS (NLA also calls this function) */
304 if (settings->SelectedProtocol == PROTOCOL_SSL)
305 {
306 switch (utils_authenticate(context->instance, AUTH_TLS, FALSE))
307 {
308 case AUTH_SKIP:
309 case AUTH_SUCCESS:
310 case AUTH_NO_CREDENTIALS:
311 break;
312 case AUTH_CANCELLED:
313 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
314 return FALSE;
315 default:
316 return FALSE;
317 }
318 }
319
320 return IFCALLRESULT(FALSE, transport->io.TLSConnect, transport);
321}
322
323static BOOL transport_default_connect_tls(rdpTransport* transport)
324{
325 int tlsStatus = 0;
326 rdpTls* tls = NULL;
327 rdpContext* context = NULL;
328 rdpSettings* settings = NULL;
329
330 WINPR_ASSERT(transport);
331
332 context = transport_get_context(transport);
333 WINPR_ASSERT(context);
334
335 settings = context->settings;
336 WINPR_ASSERT(settings);
337
338 if (!(tls = freerdp_tls_new(context)))
339 return FALSE;
340
341 transport->tls = tls;
342
343 if (transport->GatewayEnabled)
344 transport->layer = TRANSPORT_LAYER_TSG_TLS;
345 else
346 transport->layer = TRANSPORT_LAYER_TLS;
347
348 tls->hostname = settings->ServerHostname;
349 tls->serverName = settings->UserSpecifiedServerName;
350 tls->port = WINPR_ASSERTING_INT_CAST(int32_t, MIN(UINT16_MAX, settings->ServerPort));
351
352 if (tls->port == 0)
353 tls->port = 3389;
354
355 tls->isGatewayTransport = FALSE;
356 tlsStatus = freerdp_tls_connect(tls, transport->frontBio);
357
358 if (tlsStatus < 1)
359 {
360 if (tlsStatus < 0)
361 {
362 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
363 }
364 else
365 {
366 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
367 }
368
369 return FALSE;
370 }
371
372 transport->frontBio = tls->bio;
373
374 /* See libfreerdp/crypto/tls.c transport_default_connect_tls
375 *
376 * we are wrapping a SSL object in the BIO and actually want to set
377 *
378 * SSL_set_info_callback there. So ensure our callback is of appropriate
379 * type for that instead of what the function prototype suggests.
380 */
381 typedef void (*ssl_cb_t)(const SSL* ssl, int type, int val);
382 ssl_cb_t fkt = transport_ssl_cb;
383
384 BIO_info_cb* bfkt = WINPR_FUNC_PTR_CAST(fkt, BIO_info_cb*);
385 BIO_callback_ctrl(tls->bio, BIO_CTRL_SET_CALLBACK, bfkt);
386 SSL_set_app_data(tls->ssl, transport);
387
388 if (!transport->frontBio)
389 {
390 WLog_Print(transport->log, WLOG_ERROR, "unable to prepend a filtering TLS bio");
391 return FALSE;
392 }
393
394 return TRUE;
395}
396
397BOOL transport_connect_nla(rdpTransport* transport, BOOL earlyUserAuth)
398{
399 rdpContext* context = NULL;
400 rdpSettings* settings = NULL;
401 rdpRdp* rdp = NULL;
402 if (!transport)
403 return FALSE;
404
405 context = transport_get_context(transport);
406 WINPR_ASSERT(context);
407
408 settings = context->settings;
409 WINPR_ASSERT(settings);
410
411 rdp = context->rdp;
412 WINPR_ASSERT(rdp);
413
414 if (!transport_connect_tls(transport))
415 return FALSE;
416
417 if (!settings->Authentication)
418 return TRUE;
419
420 nla_free(rdp->nla);
421 rdp->nla = nla_new(context, transport);
422
423 if (!rdp->nla)
424 return FALSE;
425
426 nla_set_early_user_auth(rdp->nla, earlyUserAuth);
427
428 transport_set_nla_mode(transport, TRUE);
429
430 if (settings->AuthenticationServiceClass)
431 {
432 if (!nla_set_service_principal(rdp->nla, settings->AuthenticationServiceClass,
434 return FALSE;
435 }
436
437 if (nla_client_begin(rdp->nla) < 0)
438 {
439 WLog_Print(transport->log, WLOG_ERROR, "NLA begin failed");
440
441 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
442
443 transport_set_nla_mode(transport, FALSE);
444 return FALSE;
445 }
446
447 return rdp_client_transition_to_state(rdp, CONNECTION_STATE_NLA);
448}
449
450BOOL transport_connect_rdstls(rdpTransport* transport)
451{
452 BOOL rc = FALSE;
453 rdpRdstls* rdstls = NULL;
454 rdpContext* context = NULL;
455
456 WINPR_ASSERT(transport);
457
458 context = transport_get_context(transport);
459 WINPR_ASSERT(context);
460
461 if (!transport_connect_tls(transport))
462 goto fail;
463
464 rdstls = rdstls_new(context, transport);
465 if (!rdstls)
466 goto fail;
467
468 transport_set_rdstls_mode(transport, TRUE);
469
470 if (rdstls_authenticate(rdstls) < 0)
471 {
472 WLog_Print(transport->log, WLOG_ERROR, "RDSTLS authentication failed");
473 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
474 goto fail;
475 }
476
477 transport_set_rdstls_mode(transport, FALSE);
478 rc = TRUE;
479fail:
480 rdstls_free(rdstls);
481 return rc;
482}
483
484BOOL transport_connect_aad(rdpTransport* transport)
485{
486 rdpContext* context = NULL;
487 rdpSettings* settings = NULL;
488 rdpRdp* rdp = NULL;
489 if (!transport)
490 return FALSE;
491
492 context = transport_get_context(transport);
493 WINPR_ASSERT(context);
494
495 settings = context->settings;
496 WINPR_ASSERT(settings);
497
498 rdp = context->rdp;
499 WINPR_ASSERT(rdp);
500
501 if (!transport_connect_tls(transport))
502 return FALSE;
503
504 if (!settings->Authentication)
505 return TRUE;
506
507 if (!rdp->aad)
508 return FALSE;
509
510 transport_set_aad_mode(transport, TRUE);
511
512 if (aad_client_begin(rdp->aad) < 0)
513 {
514 WLog_Print(transport->log, WLOG_ERROR, "AAD begin failed");
515
516 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
517
518 transport_set_aad_mode(transport, FALSE);
519 return FALSE;
520 }
521
522 return rdp_client_transition_to_state(rdp, CONNECTION_STATE_AAD);
523}
524
525static BOOL transport_can_retry(const rdpContext* context, BOOL status)
526{
527 switch (freerdp_get_last_error(context))
528 {
529 case FREERDP_ERROR_CONNECT_TARGET_BOOTING:
530 return FALSE;
531 default:
532 return !status;
533 }
534}
535
536BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, DWORD timeout)
537{
538 BOOL status = FALSE;
539 rdpSettings* settings = NULL;
540 rdpContext* context = transport_get_context(transport);
541 BOOL rpcFallback = 0;
542
543 WINPR_ASSERT(context);
544 WINPR_ASSERT(hostname);
545
546 settings = context->settings;
547 WINPR_ASSERT(settings);
548
549 rpcFallback = !settings->GatewayHttpTransport;
550
551 if (transport->GatewayEnabled)
552 {
553 if (settings->GatewayUrl)
554 {
555 WINPR_ASSERT(!transport->wst);
556 transport->wst = wst_new(context);
557
558 if (!transport->wst)
559 return FALSE;
560
561 status = wst_connect(transport->wst, timeout);
562
563 if (status)
564 {
565 transport->frontBio = wst_get_front_bio_and_take_ownership(transport->wst);
566 WINPR_ASSERT(transport->frontBio);
567 BIO_set_nonblock(transport->frontBio, 0);
568 transport->layer = TRANSPORT_LAYER_TSG;
569 status = TRUE;
570 }
571 else
572 {
573 wst_free(transport->wst);
574 transport->wst = NULL;
575 }
576 }
577 if (transport_can_retry(transport->context, status) && settings->GatewayHttpTransport)
578 {
579 WINPR_ASSERT(!transport->rdg);
580 transport->rdg = rdg_new(context);
581
582 if (!transport->rdg)
583 return FALSE;
584
585 status = rdg_connect(transport->rdg, timeout, &rpcFallback);
586
587 if (status)
588 {
589 transport->frontBio = rdg_get_front_bio_and_take_ownership(transport->rdg);
590 WINPR_ASSERT(transport->frontBio);
591 BIO_set_nonblock(transport->frontBio, 0);
592 transport->layer = TRANSPORT_LAYER_TSG;
593 status = TRUE;
594 }
595 else
596 {
597 rdg_free(transport->rdg);
598 transport->rdg = NULL;
599 }
600 }
601
602 if (transport_can_retry(transport->context, status) && settings->GatewayRpcTransport &&
603 rpcFallback)
604 {
605 WINPR_ASSERT(!transport->tsg);
606 transport->tsg = tsg_new(transport);
607
608 if (!transport->tsg)
609 return FALSE;
610
611 /* Reset error condition from RDG */
612 freerdp_set_last_error_log(context, FREERDP_ERROR_SUCCESS);
613 status = tsg_connect(transport->tsg, hostname, port, timeout);
614
615 if (status)
616 {
617 transport->frontBio = tsg_get_bio(transport->tsg);
618 transport->layer = TRANSPORT_LAYER_TSG;
619 status = TRUE;
620 }
621 else
622 {
623 tsg_free(transport->tsg);
624 transport->tsg = NULL;
625 }
626 }
627 }
628 else
629 {
630 UINT16 peerPort = 0;
631 const char* proxyHostname = NULL;
632 const char* proxyUsername = NULL;
633 const char* proxyPassword = NULL;
634 BOOL isProxyConnection =
635 proxy_prepare(settings, &proxyHostname, &peerPort, &proxyUsername, &proxyPassword);
636
637 rdpTransportLayer* layer = NULL;
638 if (isProxyConnection)
639 layer = transport_connect_layer(transport, proxyHostname, peerPort, timeout);
640 else
641 layer = transport_connect_layer(transport, hostname, port, timeout);
642
643 if (!layer)
644 return FALSE;
645
646 if (!transport_attach_layer(transport, layer))
647 {
648 transport_layer_free(layer);
649 return FALSE;
650 }
651
652 if (isProxyConnection)
653 {
654 if (!proxy_connect(context, transport->frontBio, proxyUsername, proxyPassword, hostname,
655 port))
656 return FALSE;
657 }
658
659 status = TRUE;
660 }
661
662 return status;
663}
664
665BOOL transport_connect_childsession(rdpTransport* transport)
666{
667 WINPR_ASSERT(transport);
668
669 transport->frontBio = createChildSessionBio();
670 if (!transport->frontBio)
671 return FALSE;
672
673 transport->layer = TRANSPORT_LAYER_TSG;
674 return TRUE;
675}
676
677BOOL transport_accept_rdp(rdpTransport* transport)
678{
679 if (!transport)
680 return FALSE;
681 /* RDP encryption */
682 return TRUE;
683}
684
685BOOL transport_accept_tls(rdpTransport* transport)
686{
687 if (!transport)
688 return FALSE;
689 return IFCALLRESULT(FALSE, transport->io.TLSAccept, transport);
690}
691
692static BOOL transport_default_accept_tls(rdpTransport* transport)
693{
694 rdpContext* context = transport_get_context(transport);
695 rdpSettings* settings = NULL;
696
697 WINPR_ASSERT(context);
698
699 settings = context->settings;
700 WINPR_ASSERT(settings);
701
702 if (!transport->tls)
703 transport->tls = freerdp_tls_new(context);
704
705 transport->layer = TRANSPORT_LAYER_TLS;
706
707 if (!freerdp_tls_accept(transport->tls, transport->frontBio, settings))
708 return FALSE;
709
710 transport->frontBio = transport->tls->bio;
711 return TRUE;
712}
713
714BOOL transport_accept_nla(rdpTransport* transport)
715{
716 rdpContext* context = transport_get_context(transport);
717 rdpSettings* settings = NULL;
718
719 WINPR_ASSERT(context);
720
721 settings = context->settings;
722 WINPR_ASSERT(settings);
723
724 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
725 return FALSE;
726
727 /* Network Level Authentication */
728
729 if (!settings->Authentication)
730 return TRUE;
731
732 if (!transport->nla)
733 {
734 transport->nla = nla_new(context, transport);
735 transport_set_nla_mode(transport, TRUE);
736 }
737
738 if (nla_authenticate(transport->nla) < 0)
739 {
740 WLog_Print(transport->log, WLOG_ERROR, "client authentication failure");
741 transport_set_nla_mode(transport, FALSE);
742 nla_free(transport->nla);
743 transport->nla = NULL;
744 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
745 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
746 freerdp_tls_send_alert(transport->tls);
747 return FALSE;
748 }
749
750 /* don't free nla module yet, we need to copy the credentials from it first */
751 transport_set_nla_mode(transport, FALSE);
752 return TRUE;
753}
754
755BOOL transport_accept_rdstls(rdpTransport* transport)
756{
757 BOOL rc = FALSE;
758 rdpRdstls* rdstls = NULL;
759 rdpContext* context = NULL;
760
761 WINPR_ASSERT(transport);
762
763 context = transport_get_context(transport);
764 WINPR_ASSERT(context);
765
766 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
767 goto fail;
768
769 rdstls = rdstls_new(context, transport);
770 if (!rdstls)
771 goto fail;
772
773 transport_set_rdstls_mode(transport, TRUE);
774
775 if (rdstls_authenticate(rdstls) < 0)
776 {
777 WLog_Print(transport->log, WLOG_ERROR, "client authentication failure");
778 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
779 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
780 freerdp_tls_send_alert(transport->tls);
781 goto fail;
782 }
783
784 transport_set_rdstls_mode(transport, FALSE);
785 rc = TRUE;
786fail:
787 rdstls_free(rdstls);
788 return rc;
789}
790
791#define WLog_ERR_BIO(transport, biofunc, bio) \
792 transport_bio_error_log(transport, biofunc, bio, __FILE__, __func__, __LINE__)
793
794static void transport_bio_error_log(rdpTransport* transport, LPCSTR biofunc,
795 WINPR_ATTR_UNUSED BIO* bio, LPCSTR file, LPCSTR func,
796 DWORD line)
797{
798 unsigned long sslerr = 0;
799 int saveerrno = 0;
800 DWORD level = 0;
801
802 WINPR_ASSERT(transport);
803
804 saveerrno = errno;
805 level = WLOG_ERROR;
806
807 if (level < WLog_GetLogLevel(transport->log))
808 return;
809
810 if (ERR_peek_error() == 0)
811 {
812 char ebuffer[256] = { 0 };
813
814 if (saveerrno == 0)
815 WLog_PrintTextMessage(transport->log, level, line, file, func, "%s retries exceeded",
816 biofunc);
817 else
818 WLog_PrintTextMessage(transport->log, level, line, file, func,
819 "%s returned a system error %d: %s", biofunc, saveerrno,
820 winpr_strerror(saveerrno, ebuffer, sizeof(ebuffer)));
821 return;
822 }
823
824 while ((sslerr = ERR_get_error()))
825 {
826 char buf[120] = { 0 };
827
828 ERR_error_string_n(sslerr, buf, 120);
829 WLog_PrintTextMessage(transport->log, level, line, file, func, "%s returned an error: %s",
830 biofunc, buf);
831 }
832}
833
834static SSIZE_T transport_read_layer(rdpTransport* transport, BYTE* data, size_t bytes)
835{
836 SSIZE_T read = 0;
837 rdpRdp* rdp = NULL;
838 rdpContext* context = NULL;
839
840 WINPR_ASSERT(transport);
841
842 context = transport_get_context(transport);
843 WINPR_ASSERT(context);
844
845 rdp = context->rdp;
846 WINPR_ASSERT(rdp);
847
848 if (!transport->frontBio || (bytes > SSIZE_MAX))
849 {
850 transport->layer = TRANSPORT_LAYER_CLOSED;
851 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
852 return -1;
853 }
854
855 while (read < (SSIZE_T)bytes)
856 {
857 const SSIZE_T tr = (SSIZE_T)bytes - read;
858 int r = (int)((tr > INT_MAX) ? INT_MAX : tr);
859 ERR_clear_error();
860 int status = BIO_read(transport->frontBio, data + read, r);
861
862 if (freerdp_shall_disconnect_context(context))
863 return -1;
864
865 if (status <= 0)
866 {
867 if (!transport->frontBio || !BIO_should_retry(transport->frontBio))
868 {
869 /* something unexpected happened, let's close */
870 if (!transport->frontBio)
871 {
872 WLog_Print(transport->log, WLOG_ERROR, "BIO_read: transport->frontBio null");
873 return -1;
874 }
875
876 WLog_ERR_BIO(transport, "BIO_read", transport->frontBio);
877 transport->layer = TRANSPORT_LAYER_CLOSED;
878 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
879 return -1;
880 }
881
882 /* non blocking will survive a partial read */
883 if (!transport->blocking)
884 return read;
885
886 /* blocking means that we can't continue until we have read the number of requested
887 * bytes */
888 if (BIO_wait_read(transport->frontBio, 100) < 0)
889 {
890 WLog_ERR_BIO(transport, "BIO_wait_read", transport->frontBio);
891 return -1;
892 }
893
894 continue;
895 }
896
897#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
898 VALGRIND_MAKE_MEM_DEFINED(data + read, bytes - read);
899#endif
900 read += status;
901 rdp->inBytes += WINPR_ASSERTING_INT_CAST(uint64_t, status);
902 }
903
904 return read;
905}
906
921static SSIZE_T transport_read_layer_bytes(rdpTransport* transport, wStream* s, size_t toRead)
922{
923 SSIZE_T status = 0;
924 if (!transport)
925 return -1;
926
927 if (toRead > SSIZE_MAX)
928 return 0;
929
930 status = IFCALLRESULT(-1, transport->io.ReadBytes, transport, Stream_Pointer(s), toRead);
931
932 if (status <= 0)
933 return status;
934
935 Stream_Seek(s, (size_t)status);
936 return status == (SSIZE_T)toRead ? 1 : 0;
937}
938
951int transport_read_pdu(rdpTransport* transport, wStream* s)
952{
953 if (!transport)
954 return -1;
955 return IFCALLRESULT(-1, transport->io.ReadPdu, transport, s);
956}
957
958static SSIZE_T parse_nla_mode_pdu(rdpTransport* transport, wStream* stream)
959{
960 SSIZE_T pduLength = 0;
961 wStream sbuffer = { 0 };
962 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
963 /*
964 * In case NlaMode is set TSRequest package(s) are expected
965 * 0x30 = DER encoded data with these bits set:
966 * bit 6 P/C constructed
967 * bit 5 tag number - sequence
968 */
969 UINT8 typeEncoding = 0;
970 if (Stream_GetRemainingLength(s) < 1)
971 return 0;
972 Stream_Read_UINT8(s, typeEncoding);
973 if (typeEncoding == 0x30)
974 {
975 /* TSRequest (NLA) */
976 UINT8 lengthEncoding = 0;
977 if (Stream_GetRemainingLength(s) < 1)
978 return 0;
979 Stream_Read_UINT8(s, lengthEncoding);
980 if (lengthEncoding & 0x80)
981 {
982 if ((lengthEncoding & ~(0x80)) == 1)
983 {
984 UINT8 length = 0;
985 if (Stream_GetRemainingLength(s) < 1)
986 return 0;
987 Stream_Read_UINT8(s, length);
988 pduLength = length;
989 pduLength += 3;
990 }
991 else if ((lengthEncoding & ~(0x80)) == 2)
992 {
993 /* check for header bytes already read in previous calls */
994 UINT16 length = 0;
995 if (Stream_GetRemainingLength(s) < 2)
996 return 0;
997 Stream_Read_UINT16_BE(s, length);
998 pduLength = length;
999 pduLength += 4;
1000 }
1001 else
1002 {
1003 WLog_Print(transport->log, WLOG_ERROR, "Error reading TSRequest!");
1004 return -1;
1005 }
1006 }
1007 else
1008 {
1009 pduLength = lengthEncoding;
1010 pduLength += 2;
1011 }
1012 }
1013
1014 return pduLength;
1015}
1016
1017static SSIZE_T parse_default_mode_pdu(rdpTransport* transport, wStream* stream)
1018{
1019 SSIZE_T pduLength = 0;
1020 wStream sbuffer = { 0 };
1021 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
1022
1023 UINT8 version = 0;
1024 if (Stream_GetRemainingLength(s) < 1)
1025 return 0;
1026 Stream_Read_UINT8(s, version);
1027 if (version == 0x03)
1028 {
1029 /* TPKT header */
1030 UINT16 length = 0;
1031 if (Stream_GetRemainingLength(s) < 3)
1032 return 0;
1033 Stream_Seek(s, 1);
1034 Stream_Read_UINT16_BE(s, length);
1035 pduLength = length;
1036
1037 /* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */
1038 if ((pduLength < 7) || (pduLength > 0xFFFF))
1039 {
1040 WLog_Print(transport->log, WLOG_ERROR, "tpkt - invalid pduLength: %" PRIdz, pduLength);
1041 return -1;
1042 }
1043 }
1044 else
1045 {
1046 /* Fast-Path Header */
1047 UINT8 length1 = 0;
1048 if (Stream_GetRemainingLength(s) < 1)
1049 return 0;
1050 Stream_Read_UINT8(s, length1);
1051 if (length1 & 0x80)
1052 {
1053 UINT8 length2 = 0;
1054 if (Stream_GetRemainingLength(s) < 1)
1055 return 0;
1056 Stream_Read_UINT8(s, length2);
1057 pduLength = ((length1 & 0x7F) << 8) | length2;
1058 }
1059 else
1060 pduLength = length1;
1061
1062 /*
1063 * fast-path has 7 bits for length so the maximum size, including headers is 0x8000
1064 * The theoretical minimum fast-path PDU consists only of two header bytes plus one
1065 * byte for data (e.g. fast-path input synchronize pdu)
1066 */
1067 if (pduLength < 3 || pduLength > 0x8000)
1068 {
1069 WLog_Print(transport->log, WLOG_ERROR, "fast path - invalid pduLength: %" PRIdz,
1070 pduLength);
1071 return -1;
1072 }
1073 }
1074
1075 return pduLength;
1076}
1077
1078SSIZE_T transport_parse_pdu(rdpTransport* transport, wStream* s, BOOL* incomplete)
1079{
1080 SSIZE_T pduLength = 0;
1081
1082 if (!transport)
1083 return -1;
1084
1085 if (!s)
1086 return -1;
1087
1088 if (incomplete)
1089 *incomplete = TRUE;
1090
1091 Stream_SealLength(s);
1092 if (transport->NlaMode)
1093 pduLength = parse_nla_mode_pdu(transport, s);
1094 else if (transport->RdstlsMode)
1095 pduLength = rdstls_parse_pdu(transport->log, s);
1096 else
1097 pduLength = parse_default_mode_pdu(transport, s);
1098
1099 if (pduLength <= 0)
1100 return pduLength;
1101
1102 const size_t len = Stream_Length(s);
1103 if (len > WINPR_ASSERTING_INT_CAST(size_t, pduLength))
1104 return -1;
1105
1106 if (incomplete)
1107 *incomplete = len < WINPR_ASSERTING_INT_CAST(size_t, pduLength);
1108
1109 return pduLength;
1110}
1111
1112static int transport_default_read_pdu(rdpTransport* transport, wStream* s)
1113{
1114 BOOL incomplete = 0;
1115 SSIZE_T status = 0;
1116 size_t pduLength = 0;
1117 size_t position = 0;
1118
1119 WINPR_ASSERT(transport);
1120 WINPR_ASSERT(s);
1121
1122 /* RDS AAD Auth PDUs have no length indicator. We need to determine the end of the PDU by
1123 * reading in one byte at a time until we encounter the terminating null byte */
1124 if (transport->AadMode)
1125 {
1126 BYTE c = '\0';
1127 do
1128 {
1129 const SSIZE_T rc = transport_read_layer(transport, &c, 1);
1130 if (rc != 1)
1131 return (rc == 0) ? 0 : -1;
1132 if (!Stream_EnsureRemainingCapacity(s, 1))
1133 return -1;
1134 Stream_Write_UINT8(s, c);
1135 } while (c != '\0');
1136 }
1137 else if (transport->earlyUserAuth)
1138 {
1139 if (!Stream_EnsureCapacity(s, 4))
1140 return -1;
1141 const SSIZE_T rc = transport_read_layer_bytes(transport, s, 4);
1142 if (rc != 1)
1143 return (rc == 0) ? 0 : -1;
1144 }
1145 else
1146 {
1147 /* Read in pdu length */
1148 status = transport_parse_pdu(transport, s, &incomplete);
1149 while ((status == 0) && incomplete)
1150 {
1151 if (!Stream_EnsureRemainingCapacity(s, 1))
1152 return -1;
1153 SSIZE_T rc = transport_read_layer_bytes(transport, s, 1);
1154 if (rc > INT32_MAX)
1155 return INT32_MAX;
1156 if (rc != 1)
1157 return (int)rc;
1158 status = transport_parse_pdu(transport, s, &incomplete);
1159 }
1160
1161 if (status < 0)
1162 return -1;
1163
1164 pduLength = (size_t)status;
1165
1166 /* Read in rest of the PDU */
1167 if (!Stream_EnsureCapacity(s, pduLength))
1168 return -1;
1169
1170 position = Stream_GetPosition(s);
1171 if (position > pduLength)
1172 return -1;
1173 else if (position < pduLength)
1174 {
1175 status = transport_read_layer_bytes(transport, s, pduLength - position);
1176 if (status != 1)
1177 {
1178 if ((status < INT32_MIN) || (status > INT32_MAX))
1179 return -1;
1180 return (int)status;
1181 }
1182 }
1183
1184 if (Stream_GetPosition(s) >= pduLength)
1185 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength,
1186 WLOG_PACKET_INBOUND);
1187 }
1188
1189 Stream_SealLength(s);
1190 Stream_SetPosition(s, 0);
1191 const size_t len = Stream_Length(s);
1192 if (len > INT32_MAX)
1193 return -1;
1194 return (int)len;
1195}
1196
1197int transport_write(rdpTransport* transport, wStream* s)
1198{
1199 if (!transport)
1200 return -1;
1201
1202 return IFCALLRESULT(-1, transport->io.WritePdu, transport, s);
1203}
1204
1205static int transport_default_write(rdpTransport* transport, wStream* s)
1206{
1207 int status = -1;
1208 rdpContext* context = transport_get_context(transport);
1209
1210 WINPR_ASSERT(transport);
1211 WINPR_ASSERT(context);
1212
1213 if (!s)
1214 return -1;
1215
1216 Stream_AddRef(s);
1217
1218 rdpRdp* rdp = context->rdp;
1219 if (!rdp)
1220 goto fail;
1221
1222 EnterCriticalSection(&(transport->WriteLock));
1223 if (!transport->frontBio)
1224 goto out_cleanup;
1225
1226 {
1227 size_t length = Stream_GetPosition(s);
1228 size_t writtenlength = length;
1229 Stream_SetPosition(s, 0);
1230
1231 if (length > 0)
1232 {
1233 rdp->outBytes += length;
1234 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
1235 }
1236
1237 while (length > 0)
1238 {
1239 ERR_clear_error();
1240 const int towrite = (length > INT32_MAX) ? INT32_MAX : (int)length;
1241 status = BIO_write(transport->frontBio, Stream_ConstPointer(s), towrite);
1242
1243 if (status <= 0)
1244 {
1245 /* the buffered BIO that is at the end of the chain always says OK for writing,
1246 * so a retry means that for any reason we need to read. The most probable
1247 * is a SSL or TSG BIO in the chain.
1248 */
1249 if (!BIO_should_retry(transport->frontBio))
1250 {
1251 WLog_ERR_BIO(transport, "BIO_should_retry", transport->frontBio);
1252 goto out_cleanup;
1253 }
1254
1255 /* non-blocking can live with blocked IOs */
1256 if (!transport->blocking)
1257 {
1258 WLog_ERR_BIO(transport, "BIO_write", transport->frontBio);
1259 goto out_cleanup;
1260 }
1261
1262 if (BIO_wait_write(transport->frontBio, 100) < 0)
1263 {
1264 WLog_ERR_BIO(transport, "BIO_wait_write", transport->frontBio);
1265 status = -1;
1266 goto out_cleanup;
1267 }
1268
1269 continue;
1270 }
1271
1272 WINPR_ASSERT(context->settings);
1273 if (transport->blocking || context->settings->WaitForOutputBufferFlush)
1274 {
1275 while (BIO_write_blocked(transport->frontBio))
1276 {
1277 if (BIO_wait_write(transport->frontBio, 100) < 0)
1278 {
1279 WLog_Print(transport->log, WLOG_ERROR, "error when selecting for write");
1280 status = -1;
1281 goto out_cleanup;
1282 }
1283
1284 if (BIO_flush(transport->frontBio) < 1)
1285 {
1286 WLog_Print(transport->log, WLOG_ERROR, "error when flushing outputBuffer");
1287 status = -1;
1288 goto out_cleanup;
1289 }
1290 }
1291 }
1292
1293 const size_t ustatus = (size_t)status;
1294 if (ustatus > length)
1295 {
1296 status = -1;
1297 goto out_cleanup;
1298 }
1299
1300 length -= ustatus;
1301 Stream_Seek(s, ustatus);
1302 }
1303
1304 transport->written += writtenlength;
1305 }
1306out_cleanup:
1307
1308 if (status < 0)
1309 {
1310 /* A write error indicates that the peer has dropped the connection */
1311 transport->layer = TRANSPORT_LAYER_CLOSED;
1312 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1313 }
1314
1315 LeaveCriticalSection(&(transport->WriteLock));
1316fail:
1317 Stream_Release(s);
1318 return status;
1319}
1320
1321BOOL transport_get_public_key(rdpTransport* transport, const BYTE** data, DWORD* length)
1322{
1323 return IFCALLRESULT(FALSE, transport->io.GetPublicKey, transport, data, length);
1324}
1325
1326static BOOL transport_default_get_public_key(rdpTransport* transport, const BYTE** data,
1327 DWORD* length)
1328{
1329 rdpTls* tls = transport_get_tls(transport);
1330 if (!tls)
1331 return FALSE;
1332
1333 *data = tls->PublicKey;
1334 *length = tls->PublicKeyLength;
1335
1336 return TRUE;
1337}
1338
1339DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count)
1340{
1341 DWORD nCount = 0; /* always the reread Event */
1342
1343 WINPR_ASSERT(transport);
1344 WINPR_ASSERT(events);
1345 WINPR_ASSERT(count > 0);
1346
1347 if (events)
1348 {
1349 if (count < 1)
1350 {
1351 WLog_Print(transport->log, WLOG_ERROR, "provided handles array is too small");
1352 return 0;
1353 }
1354
1355 events[nCount++] = transport->rereadEvent;
1356
1357 if (transport->useIoEvent)
1358 {
1359 if (count < 2)
1360 return 0;
1361 events[nCount++] = transport->ioEvent;
1362 }
1363 }
1364
1365 if (!transport->GatewayEnabled)
1366 {
1367 if (events)
1368 {
1369 if (nCount >= count)
1370 {
1371 WLog_Print(transport->log, WLOG_ERROR,
1372 "provided handles array is too small (count=%" PRIu32 " nCount=%" PRIu32
1373 ")",
1374 count, nCount);
1375 return 0;
1376 }
1377
1378 if (transport->frontBio)
1379 {
1380 if (BIO_get_event(transport->frontBio, &events[nCount]) != 1)
1381 {
1382 WLog_Print(transport->log, WLOG_ERROR, "error getting the frontBio handle");
1383 return 0;
1384 }
1385 nCount++;
1386 }
1387 }
1388 }
1389 else
1390 {
1391 if (transport->rdg)
1392 {
1393 const DWORD tmp =
1394 rdg_get_event_handles(transport->rdg, &events[nCount], count - nCount);
1395
1396 if (tmp == 0)
1397 return 0;
1398
1399 nCount += tmp;
1400 }
1401 else if (transport->tsg)
1402 {
1403 const DWORD tmp =
1404 tsg_get_event_handles(transport->tsg, &events[nCount], count - nCount);
1405
1406 if (tmp == 0)
1407 return 0;
1408
1409 nCount += tmp;
1410 }
1411 else if (transport->wst)
1412 {
1413 const DWORD tmp =
1414 wst_get_event_handles(transport->wst, &events[nCount], count - nCount);
1415
1416 if (tmp == 0)
1417 return 0;
1418
1419 nCount += tmp;
1420 }
1421 }
1422
1423 return nCount;
1424}
1425
1426#if defined(WITH_FREERDP_DEPRECATED)
1427void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
1428{
1429 DWORD nCount = 0;
1430 HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
1431
1432 WINPR_ASSERT(transport);
1433 WINPR_ASSERT(rfds);
1434 WINPR_ASSERT(rcount);
1435
1436 nCount = transport_get_event_handles(transport, events, ARRAYSIZE(events));
1437 *rcount = nCount + 1;
1438
1439 for (DWORD index = 0; index < nCount; index++)
1440 {
1441 rfds[index] = GetEventWaitObject(events[index]);
1442 }
1443
1444 rfds[nCount] = GetEventWaitObject(transport->rereadEvent);
1445}
1446#endif
1447
1448BOOL transport_is_write_blocked(rdpTransport* transport)
1449{
1450 WINPR_ASSERT(transport);
1451 WINPR_ASSERT(transport->frontBio);
1452 return BIO_write_blocked(transport->frontBio) != 0;
1453}
1454
1455int transport_drain_output_buffer(rdpTransport* transport)
1456{
1457 BOOL status = FALSE;
1458
1459 WINPR_ASSERT(transport);
1460 WINPR_ASSERT(transport->frontBio);
1461 if (BIO_write_blocked(transport->frontBio))
1462 {
1463 if (BIO_flush(transport->frontBio) < 1)
1464 return -1;
1465
1466 const long rc = BIO_write_blocked(transport->frontBio);
1467 status = (rc != 0);
1468 }
1469
1470 return status;
1471}
1472
1473int transport_check_fds(rdpTransport* transport)
1474{
1475 int status = 0;
1476 state_run_t recv_status = STATE_RUN_FAILED;
1477 wStream* received = NULL;
1478 rdpContext* context = transport_get_context(transport);
1479
1480 WINPR_ASSERT(context);
1481
1482 if (transport->layer == TRANSPORT_LAYER_CLOSED)
1483 {
1484 WLog_Print(transport->log, WLOG_DEBUG, "transport_check_fds: transport layer closed");
1485 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1486 return -1;
1487 }
1488
1498 if ((status = transport_read_pdu(transport, transport->ReceiveBuffer)) <= 0)
1499 {
1500 if (status < 0)
1501 WLog_Print(transport->log, WLOG_DEBUG, "transport_check_fds: transport_read_pdu() - %i",
1502 status);
1503 if (transport->haveMoreBytesToRead)
1504 {
1505 transport->haveMoreBytesToRead = FALSE;
1506 (void)ResetEvent(transport->rereadEvent);
1507 }
1508 return status;
1509 }
1510
1511 received = transport->ReceiveBuffer;
1512 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1513 if (!transport->ReceiveBuffer)
1514 {
1515 Stream_Release(received);
1516 return -1;
1517 }
1518
1525 WINPR_ASSERT(transport->ReceiveCallback);
1526 recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
1527 Stream_Release(received);
1528
1529 if (state_run_failed(recv_status))
1530 {
1531 char buffer[64] = { 0 };
1532 WLog_Print(transport->log, WLOG_ERROR,
1533 "transport_check_fds: transport->ReceiveCallback() - %s",
1534 state_run_result_string(recv_status, buffer, ARRAYSIZE(buffer)));
1535 return -1;
1536 }
1537
1538 /* Run this again to be sure we consumed all input data.
1539 * This will be repeated until a (not fully) received packet is in buffer
1540 */
1541 if (!transport->haveMoreBytesToRead)
1542 {
1543 transport->haveMoreBytesToRead = TRUE;
1544 (void)SetEvent(transport->rereadEvent);
1545 }
1546 return recv_status;
1547}
1548
1549BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1550{
1551 WINPR_ASSERT(transport);
1552
1553 return IFCALLRESULT(FALSE, transport->io.SetBlockingMode, transport, blocking);
1554}
1555
1556static BOOL transport_default_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1557{
1558 WINPR_ASSERT(transport);
1559
1560 transport->blocking = blocking;
1561
1562 if (transport->frontBio)
1563 {
1564 if (!BIO_set_nonblock(transport->frontBio, blocking ? FALSE : TRUE))
1565 return FALSE;
1566 }
1567
1568 return TRUE;
1569}
1570
1571rdpTransportLayer* transport_connect_layer(rdpTransport* transport, const char* hostname, int port,
1572 DWORD timeout)
1573{
1574 WINPR_ASSERT(transport);
1575
1576 return IFCALLRESULT(NULL, transport->io.ConnectLayer, transport, hostname, port, timeout);
1577}
1578
1579static rdpTransportLayer* transport_default_connect_layer(rdpTransport* transport,
1580 const char* hostname, int port,
1581 DWORD timeout)
1582{
1583 rdpContext* context = transport_get_context(transport);
1584 WINPR_ASSERT(context);
1585
1586 return freerdp_tcp_connect_layer(context, hostname, port, timeout);
1587}
1588
1589BOOL transport_attach_layer(rdpTransport* transport, rdpTransportLayer* layer)
1590{
1591 WINPR_ASSERT(transport);
1592 WINPR_ASSERT(layer);
1593
1594 return IFCALLRESULT(FALSE, transport->io.AttachLayer, transport, layer);
1595}
1596
1597static BOOL transport_default_attach_layer(rdpTransport* transport, rdpTransportLayer* layer)
1598{
1599 BIO* layerBio = BIO_new(BIO_s_transport_layer());
1600 if (!layerBio)
1601 goto fail;
1602
1603 {
1604 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
1605 if (!bufferedBio)
1606 goto fail;
1607
1608 bufferedBio = BIO_push(bufferedBio, layerBio);
1609 if (!bufferedBio)
1610 goto fail;
1611
1612 /* BIO takes over the layer reference at this point. */
1613 BIO_set_data(layerBio, layer);
1614
1615 transport->frontBio = bufferedBio;
1616 }
1617 return TRUE;
1618
1619fail:
1620 if (layerBio)
1621 BIO_free_all(layerBio);
1622
1623 return FALSE;
1624}
1625
1626void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled)
1627{
1628 WINPR_ASSERT(transport);
1629 transport->GatewayEnabled = GatewayEnabled;
1630}
1631
1632void transport_set_nla_mode(rdpTransport* transport, BOOL NlaMode)
1633{
1634 WINPR_ASSERT(transport);
1635 transport->NlaMode = NlaMode;
1636}
1637
1638void transport_set_rdstls_mode(rdpTransport* transport, BOOL RdstlsMode)
1639{
1640 WINPR_ASSERT(transport);
1641 transport->RdstlsMode = RdstlsMode;
1642}
1643
1644void transport_set_aad_mode(rdpTransport* transport, BOOL AadMode)
1645{
1646 WINPR_ASSERT(transport);
1647 transport->AadMode = AadMode;
1648}
1649
1650BOOL transport_disconnect(rdpTransport* transport)
1651{
1652 if (!transport)
1653 return FALSE;
1654 return IFCALLRESULT(FALSE, transport->io.TransportDisconnect, transport);
1655}
1656
1657static BOOL transport_default_disconnect(rdpTransport* transport)
1658{
1659 BOOL status = TRUE;
1660
1661 if (!transport)
1662 return FALSE;
1663
1664 EnterCriticalSection(&(transport->ReadLock));
1665 EnterCriticalSection(&(transport->WriteLock));
1666 if (transport->tls)
1667 {
1668 freerdp_tls_free(transport->tls);
1669 transport->tls = NULL;
1670 }
1671 else
1672 {
1673 if (transport->frontBio)
1674 BIO_free_all(transport->frontBio);
1675 }
1676
1677 if (transport->tsg)
1678 {
1679 tsg_free(transport->tsg);
1680 transport->tsg = NULL;
1681 }
1682
1683 if (transport->rdg)
1684 {
1685 rdg_free(transport->rdg);
1686 transport->rdg = NULL;
1687 }
1688
1689 if (transport->wst)
1690 {
1691 wst_free(transport->wst);
1692 transport->wst = NULL;
1693 }
1694
1695 transport->frontBio = NULL;
1696 transport->layer = TRANSPORT_LAYER_TCP;
1697 transport->earlyUserAuth = FALSE;
1698 LeaveCriticalSection(&(transport->WriteLock));
1699 LeaveCriticalSection(&(transport->ReadLock));
1700 return status;
1701}
1702
1703rdpTransport* transport_new(rdpContext* context)
1704{
1705 rdpTransport* transport = (rdpTransport*)calloc(1, sizeof(rdpTransport));
1706
1707 WINPR_ASSERT(context);
1708 if (!transport)
1709 return NULL;
1710
1711 transport->log = WLog_Get(TAG);
1712
1713 if (!transport->log)
1714 goto fail;
1715
1716 transport->context = context;
1717 transport->haveReadLock = InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000);
1718 transport->haveWriteLock = InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000);
1719 if (!transport->haveReadLock || !transport->haveWriteLock)
1720 goto fail;
1721
1722 transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
1723
1724 if (!transport->ReceivePool)
1725 goto fail;
1726
1727 /* receive buffer for non-blocking read. */
1728 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1729
1730 if (!transport->ReceiveBuffer)
1731 goto fail;
1732
1733 transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1734
1735 if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
1736 goto fail;
1737
1738 transport->rereadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1739
1740 if (!transport->rereadEvent || transport->rereadEvent == INVALID_HANDLE_VALUE)
1741 goto fail;
1742
1743 transport->ioEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1744
1745 if (!transport->ioEvent || transport->ioEvent == INVALID_HANDLE_VALUE)
1746 goto fail;
1747
1748 transport->haveMoreBytesToRead = FALSE;
1749 transport->blocking = TRUE;
1750 transport->GatewayEnabled = FALSE;
1751 transport->layer = TRANSPORT_LAYER_TCP;
1752
1753 // transport->io.DataHandler = transport_data_handler;
1754 transport->io.TCPConnect = freerdp_tcp_default_connect;
1755 transport->io.TLSConnect = transport_default_connect_tls;
1756 transport->io.TLSAccept = transport_default_accept_tls;
1757 transport->io.TransportAttach = transport_default_attach;
1758 transport->io.TransportDisconnect = transport_default_disconnect;
1759 transport->io.ReadPdu = transport_default_read_pdu;
1760 transport->io.WritePdu = transport_default_write;
1761 transport->io.ReadBytes = transport_read_layer;
1762 transport->io.GetPublicKey = transport_default_get_public_key;
1763 transport->io.SetBlockingMode = transport_default_set_blocking_mode;
1764 transport->io.ConnectLayer = transport_default_connect_layer;
1765 transport->io.AttachLayer = transport_default_attach_layer;
1766
1767 return transport;
1768fail:
1769 WINPR_PRAGMA_DIAG_PUSH
1770 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1771 transport_free(transport);
1772 WINPR_PRAGMA_DIAG_POP
1773 return NULL;
1774}
1775
1776void transport_free(rdpTransport* transport)
1777{
1778 if (!transport)
1779 return;
1780
1781 transport_disconnect(transport);
1782
1783 if (transport->haveReadLock)
1784 EnterCriticalSection(&(transport->ReadLock));
1785
1786 if (transport->ReceiveBuffer)
1787 Stream_Release(transport->ReceiveBuffer);
1788
1789 if (transport->haveReadLock)
1790 LeaveCriticalSection(&(transport->ReadLock));
1791
1792 if (transport->ReceivePool)
1793 (void)StreamPool_WaitForReturn(transport->ReceivePool, INFINITE);
1794
1795 if (transport->haveReadLock)
1796 EnterCriticalSection(&(transport->ReadLock));
1797
1798 if (transport->haveWriteLock)
1799 EnterCriticalSection(&(transport->WriteLock));
1800
1801 nla_free(transport->nla);
1802 StreamPool_Free(transport->ReceivePool);
1803 (void)CloseHandle(transport->connectedEvent);
1804 (void)CloseHandle(transport->rereadEvent);
1805 (void)CloseHandle(transport->ioEvent);
1806
1807 if (transport->haveReadLock)
1808 LeaveCriticalSection(&(transport->ReadLock));
1809 DeleteCriticalSection(&(transport->ReadLock));
1810
1811 if (transport->haveWriteLock)
1812 LeaveCriticalSection(&(transport->WriteLock));
1813 DeleteCriticalSection(&(transport->WriteLock));
1814 free(transport);
1815}
1816
1817BOOL transport_set_io_callbacks(rdpTransport* transport, const rdpTransportIo* io_callbacks)
1818{
1819 if (!transport || !io_callbacks)
1820 return FALSE;
1821
1822 transport->io = *io_callbacks;
1823 return TRUE;
1824}
1825
1826const rdpTransportIo* transport_get_io_callbacks(const rdpTransport* transport)
1827{
1828 if (!transport)
1829 return NULL;
1830 return &transport->io;
1831}
1832
1833rdpContext* transport_get_context(rdpTransport* transport)
1834{
1835 WINPR_ASSERT(transport);
1836 return transport->context;
1837}
1838
1839rdpTransport* freerdp_get_transport(rdpContext* context)
1840{
1841 WINPR_ASSERT(context);
1842 WINPR_ASSERT(context->rdp);
1843 return context->rdp->transport;
1844}
1845
1846BOOL transport_set_nla(rdpTransport* transport, rdpNla* nla)
1847{
1848 WINPR_ASSERT(transport);
1849 nla_free(transport->nla);
1850 transport->nla = nla;
1851 return TRUE;
1852}
1853
1854rdpNla* transport_get_nla(rdpTransport* transport)
1855{
1856 WINPR_ASSERT(transport);
1857 return transport->nla;
1858}
1859
1860BOOL transport_set_tls(rdpTransport* transport, rdpTls* tls)
1861{
1862 WINPR_ASSERT(transport);
1863 freerdp_tls_free(transport->tls);
1864 transport->tls = tls;
1865 return TRUE;
1866}
1867
1868rdpTls* transport_get_tls(rdpTransport* transport)
1869{
1870 WINPR_ASSERT(transport);
1871 return transport->tls;
1872}
1873
1874BOOL transport_set_tsg(rdpTransport* transport, rdpTsg* tsg)
1875{
1876 WINPR_ASSERT(transport);
1877 tsg_free(transport->tsg);
1878 transport->tsg = tsg;
1879 return TRUE;
1880}
1881
1882rdpTsg* transport_get_tsg(rdpTransport* transport)
1883{
1884 WINPR_ASSERT(transport);
1885 return transport->tsg;
1886}
1887
1888wStream* transport_take_from_pool(rdpTransport* transport, size_t size)
1889{
1890 WINPR_ASSERT(transport);
1891 if (!transport->frontBio)
1892 return NULL;
1893 return StreamPool_Take(transport->ReceivePool, size);
1894}
1895
1896UINT64 transport_get_bytes_sent(rdpTransport* transport, BOOL resetCount)
1897{
1898 UINT64 rc = 0;
1899 WINPR_ASSERT(transport);
1900 rc = transport->written;
1901 if (resetCount)
1902 transport->written = 0;
1903 return rc;
1904}
1905
1906TRANSPORT_LAYER transport_get_layer(rdpTransport* transport)
1907{
1908 WINPR_ASSERT(transport);
1909 return transport->layer;
1910}
1911
1912BOOL transport_set_layer(rdpTransport* transport, TRANSPORT_LAYER layer)
1913{
1914 WINPR_ASSERT(transport);
1915 transport->layer = layer;
1916 return TRUE;
1917}
1918
1919BOOL transport_set_connected_event(rdpTransport* transport)
1920{
1921 WINPR_ASSERT(transport);
1922 return SetEvent(transport->connectedEvent);
1923}
1924
1925BOOL transport_set_recv_callbacks(rdpTransport* transport, TransportRecv recv, void* extra)
1926{
1927 WINPR_ASSERT(transport);
1928 transport->ReceiveCallback = recv;
1929 transport->ReceiveExtra = extra;
1930 return TRUE;
1931}
1932
1933BOOL transport_get_blocking(const rdpTransport* transport)
1934{
1935 WINPR_ASSERT(transport);
1936 return transport->blocking;
1937}
1938
1939BOOL transport_set_blocking(rdpTransport* transport, BOOL blocking)
1940{
1941 WINPR_ASSERT(transport);
1942 transport->blocking = blocking;
1943 return TRUE;
1944}
1945
1946BOOL transport_have_more_bytes_to_read(rdpTransport* transport)
1947{
1948 WINPR_ASSERT(transport);
1949 return transport->haveMoreBytesToRead;
1950}
1951
1952int transport_tcp_connect(rdpTransport* transport, const char* hostname, int port, DWORD timeout)
1953{
1954 rdpContext* context = transport_get_context(transport);
1955 WINPR_ASSERT(context);
1956 WINPR_ASSERT(context->settings);
1957 return IFCALLRESULT(-1, transport->io.TCPConnect, context, context->settings, hostname, port,
1958 timeout);
1959}
1960
1961HANDLE transport_get_front_bio(rdpTransport* transport)
1962{
1963 HANDLE hEvent = NULL;
1964 WINPR_ASSERT(transport);
1965 WINPR_ASSERT(transport->frontBio);
1966
1967 BIO_get_event(transport->frontBio, &hEvent);
1968 return hEvent;
1969}
1970
1971BOOL transport_io_callback_set_event(rdpTransport* transport, BOOL set)
1972{
1973 WINPR_ASSERT(transport);
1974 transport->useIoEvent = TRUE;
1975 if (!set)
1976 return ResetEvent(transport->ioEvent);
1977 return SetEvent(transport->ioEvent);
1978}
1979
1980void transport_set_early_user_auth_mode(rdpTransport* transport, BOOL EUAMode)
1981{
1982 WINPR_ASSERT(transport);
1983 transport->earlyUserAuth = EUAMode;
1984 WLog_Print(transport->log, WLOG_DEBUG, "Early User Auth Mode: %s", EUAMode ? "on" : "off");
1985}
1986
1987rdpTransportLayer* transport_layer_new(WINPR_ATTR_UNUSED rdpTransport* transport,
1988 size_t contextSize)
1989{
1990 rdpTransportLayerInt* layer = (rdpTransportLayerInt*)calloc(1, sizeof(rdpTransportLayerInt));
1991 if (!layer)
1992 return NULL;
1993
1994 if (contextSize)
1995 {
1996 layer->userContextShadowPtr = calloc(1, contextSize);
1997 if (!layer->userContextShadowPtr)
1998 {
1999 free(layer);
2000 return NULL;
2001 }
2002 }
2003 layer->pub.userContext = layer->userContextShadowPtr;
2004
2005 return &layer->pub;
2006}
2007
2008void transport_layer_free(rdpTransportLayer* layer)
2009{
2010 rdpTransportLayerInt* intern = (rdpTransportLayerInt*)layer;
2011 if (!layer)
2012 return;
2013
2014 IFCALL(intern->pub.Close, intern->pub.userContext);
2015 free(intern->userContextShadowPtr);
2016 free(intern);
2017}
2018
2019static int transport_layer_bio_write(BIO* bio, const char* buf, int size)
2020{
2021 if (!buf || !size)
2022 return 0;
2023 if (size < 0)
2024 return -1;
2025
2026 WINPR_ASSERT(bio);
2027
2028 rdpTransportLayer* layer = (rdpTransportLayer*)BIO_get_data(bio);
2029 if (!layer)
2030 return -1;
2031
2032 BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
2033
2034 errno = 0;
2035 const int status = IFCALLRESULT(-1, layer->Write, layer->userContext, buf, size);
2036
2037 if (status >= 0 && status < size)
2038 BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
2039
2040 switch (errno)
2041 {
2042 case EAGAIN:
2043 BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
2044 break;
2045 default:
2046 break;
2047 }
2048
2049 return status;
2050}
2051
2052static int transport_layer_bio_read(BIO* bio, char* buf, int size)
2053{
2054 if (!buf || !size)
2055 return 0;
2056 if (size < 0)
2057 return -1;
2058
2059 WINPR_ASSERT(bio);
2060
2061 rdpTransportLayer* layer = (rdpTransportLayer*)BIO_get_data(bio);
2062 if (!layer)
2063 return -1;
2064
2065 BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
2066 errno = 0;
2067 const int status = IFCALLRESULT(-1, layer->Read, layer->userContext, buf, size);
2068
2069 switch (errno)
2070 {
2071 case EAGAIN:
2072 BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
2073 break;
2074 default:
2075 break;
2076 }
2077
2078 return status;
2079}
2080
2081static int transport_layer_bio_puts(WINPR_ATTR_UNUSED BIO* bio, WINPR_ATTR_UNUSED const char* str)
2082{
2083 return -2;
2084}
2085
2086static int transport_layer_bio_gets(WINPR_ATTR_UNUSED BIO* bio, WINPR_ATTR_UNUSED char* str,
2087 WINPR_ATTR_UNUSED int size)
2088{
2089 return 1;
2090}
2091
2092static long transport_layer_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
2093{
2094 WINPR_ASSERT(bio);
2095
2096 rdpTransportLayer* layer = (rdpTransportLayer*)BIO_get_data(bio);
2097 if (!layer)
2098 return -1;
2099
2100 int status = -1;
2101 switch (cmd)
2102 {
2103 case BIO_C_GET_EVENT:
2104 *((HANDLE*)arg2) = IFCALLRESULT(NULL, layer->GetEvent, layer->userContext);
2105 status = 1;
2106 break;
2107
2108 case BIO_C_SET_NONBLOCK:
2109 status = 1;
2110 break;
2111
2112 case BIO_C_WAIT_READ:
2113 {
2114 int timeout = (int)arg1;
2115 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, FALSE,
2116 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2117 /* Convert timeout to error return */
2118 if (!r)
2119 {
2120 errno = ETIMEDOUT;
2121 status = 0;
2122 }
2123 else
2124 status = 1;
2125 break;
2126 }
2127
2128 case BIO_C_WAIT_WRITE:
2129 {
2130 int timeout = (int)arg1;
2131 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, TRUE,
2132 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2133 /* Convert timeout to error return */
2134 if (!r)
2135 {
2136 errno = ETIMEDOUT;
2137 status = 0;
2138 }
2139 else
2140 status = 1;
2141 break;
2142 }
2143
2144 case BIO_CTRL_GET_CLOSE:
2145 status = BIO_get_shutdown(bio);
2146 break;
2147
2148 case BIO_CTRL_SET_CLOSE:
2149 BIO_set_shutdown(bio, (int)arg1);
2150 status = 1;
2151 break;
2152
2153 case BIO_CTRL_FLUSH:
2154 case BIO_CTRL_DUP:
2155 status = 1;
2156 break;
2157
2158 default:
2159 status = 0;
2160 break;
2161 }
2162
2163 return status;
2164}
2165
2166static int transport_layer_bio_new(BIO* bio)
2167{
2168 WINPR_ASSERT(bio);
2169
2170 BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
2171 BIO_set_init(bio, 1);
2172 return 1;
2173}
2174
2175static int transport_layer_bio_free(BIO* bio)
2176{
2177 if (!bio)
2178 return 0;
2179
2180 rdpTransportLayer* layer = (rdpTransportLayer*)BIO_get_data(bio);
2181 if (layer)
2182 transport_layer_free(layer);
2183
2184 BIO_set_data(bio, NULL);
2185 BIO_set_init(bio, 0);
2186 BIO_set_flags(bio, 0);
2187
2188 return 1;
2189}
2190
2191BIO_METHOD* BIO_s_transport_layer(void)
2192{
2193 static BIO_METHOD* bio_methods = NULL;
2194
2195 if (bio_methods == NULL)
2196 {
2197 if (!(bio_methods = BIO_meth_new(BIO_TYPE_SIMPLE, "TransportLayer")))
2198 return NULL;
2199
2200 BIO_meth_set_write(bio_methods, transport_layer_bio_write);
2201 BIO_meth_set_read(bio_methods, transport_layer_bio_read);
2202 BIO_meth_set_puts(bio_methods, transport_layer_bio_puts);
2203 BIO_meth_set_gets(bio_methods, transport_layer_bio_gets);
2204 BIO_meth_set_ctrl(bio_methods, transport_layer_bio_ctrl);
2205 BIO_meth_set_create(bio_methods, transport_layer_bio_new);
2206 BIO_meth_set_destroy(bio_methods, transport_layer_bio_free);
2207 }
2208
2209 return bio_methods;
2210}
FREERDP_API const char * freerdp_settings_get_server_name(const rdpSettings *settings)
A helper function to return the correct server name.