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