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