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