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
481static BOOL transport_can_retry(const rdpContext* context, BOOL status)
482{
483 switch (freerdp_get_last_error(context))
484 {
485 case FREERDP_ERROR_CONNECT_TARGET_BOOTING:
486 return FALSE;
487 default:
488 return !status;
489 }
490}
491
492BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, DWORD timeout)
493{
494 BOOL status = FALSE;
495 rdpSettings* settings = NULL;
496 rdpContext* context = transport_get_context(transport);
497 BOOL rpcFallback = 0;
498
499 WINPR_ASSERT(context);
500 WINPR_ASSERT(hostname);
501
502 settings = context->settings;
503 WINPR_ASSERT(settings);
504
505 rpcFallback = !settings->GatewayHttpTransport;
506
507 if (transport->GatewayEnabled)
508 {
509 if (settings->GatewayUrl)
510 {
511 WINPR_ASSERT(!transport->wst);
512 transport->wst = wst_new(context);
513
514 if (!transport->wst)
515 return FALSE;
516
517 status = wst_connect(transport->wst, timeout);
518
519 if (status)
520 {
521 transport->frontBio = wst_get_front_bio_and_take_ownership(transport->wst);
522 WINPR_ASSERT(transport->frontBio);
523 BIO_set_nonblock(transport->frontBio, 0);
524 transport->layer = TRANSPORT_LAYER_TSG;
525 status = TRUE;
526 }
527 else
528 {
529 wst_free(transport->wst);
530 transport->wst = NULL;
531 }
532 }
533 if (transport_can_retry(transport->context, status) && settings->GatewayHttpTransport)
534 {
535 WINPR_ASSERT(!transport->rdg);
536 transport->rdg = rdg_new(context);
537
538 if (!transport->rdg)
539 return FALSE;
540
541 status = rdg_connect(transport->rdg, timeout, &rpcFallback);
542
543 if (status)
544 {
545 transport->frontBio = rdg_get_front_bio_and_take_ownership(transport->rdg);
546 WINPR_ASSERT(transport->frontBio);
547 BIO_set_nonblock(transport->frontBio, 0);
548 transport->layer = TRANSPORT_LAYER_TSG;
549 status = TRUE;
550 }
551 else
552 {
553 rdg_free(transport->rdg);
554 transport->rdg = NULL;
555 }
556 }
557
558 if (transport_can_retry(transport->context, status) && settings->GatewayRpcTransport &&
559 rpcFallback)
560 {
561 WINPR_ASSERT(!transport->tsg);
562 transport->tsg = tsg_new(transport);
563
564 if (!transport->tsg)
565 return FALSE;
566
567 /* Reset error condition from RDG */
568 freerdp_set_last_error_log(context, FREERDP_ERROR_SUCCESS);
569 status = tsg_connect(transport->tsg, hostname, port, timeout);
570
571 if (status)
572 {
573 transport->frontBio = tsg_get_bio(transport->tsg);
574 transport->layer = TRANSPORT_LAYER_TSG;
575 status = TRUE;
576 }
577 else
578 {
579 tsg_free(transport->tsg);
580 transport->tsg = NULL;
581 }
582 }
583 }
584 else
585 {
586 UINT16 peerPort = 0;
587 const char* proxyHostname = NULL;
588 const char* proxyUsername = NULL;
589 const char* proxyPassword = NULL;
590 BOOL isProxyConnection =
591 proxy_prepare(settings, &proxyHostname, &peerPort, &proxyUsername, &proxyPassword);
592
593 rdpTransportLayer* layer = NULL;
594 if (isProxyConnection)
595 layer = transport_connect_layer(transport, proxyHostname, peerPort, timeout);
596 else
597 layer = transport_connect_layer(transport, hostname, port, timeout);
598
599 if (!layer)
600 return FALSE;
601
602 if (!transport_attach_layer(transport, layer))
603 {
604 transport_layer_free(layer);
605 return FALSE;
606 }
607
608 if (isProxyConnection)
609 {
610 if (!proxy_connect(context, transport->frontBio, proxyUsername, proxyPassword, hostname,
611 port))
612 return FALSE;
613 }
614
615 status = TRUE;
616 }
617
618 return status;
619}
620
621BOOL transport_connect_childsession(rdpTransport* transport)
622{
623 WINPR_ASSERT(transport);
624
625 transport->frontBio = createChildSessionBio();
626 if (!transport->frontBio)
627 return FALSE;
628
629 transport->layer = TRANSPORT_LAYER_TSG;
630 return TRUE;
631}
632
633BOOL transport_accept_rdp(rdpTransport* transport)
634{
635 if (!transport)
636 return FALSE;
637 /* RDP encryption */
638 return TRUE;
639}
640
641BOOL transport_accept_tls(rdpTransport* transport)
642{
643 if (!transport)
644 return FALSE;
645 return IFCALLRESULT(FALSE, transport->io.TLSAccept, transport);
646}
647
648static BOOL transport_default_accept_tls(rdpTransport* transport)
649{
650 rdpContext* context = transport_get_context(transport);
651 rdpSettings* settings = NULL;
652
653 WINPR_ASSERT(context);
654
655 settings = context->settings;
656 WINPR_ASSERT(settings);
657
658 if (!transport->tls)
659 transport->tls = freerdp_tls_new(context);
660
661 transport->layer = TRANSPORT_LAYER_TLS;
662
663 if (!freerdp_tls_accept(transport->tls, transport->frontBio, settings))
664 return FALSE;
665
666 transport->frontBio = transport->tls->bio;
667 return TRUE;
668}
669
670BOOL transport_accept_nla(rdpTransport* transport)
671{
672 rdpContext* context = transport_get_context(transport);
673 rdpSettings* settings = NULL;
674
675 WINPR_ASSERT(context);
676
677 settings = context->settings;
678 WINPR_ASSERT(settings);
679
680 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
681 return FALSE;
682
683 /* Network Level Authentication */
684
685 if (!settings->Authentication)
686 return TRUE;
687
688 if (!transport->nla)
689 {
690 transport->nla = nla_new(context, transport);
691 transport_set_nla_mode(transport, TRUE);
692 }
693
694 if (nla_authenticate(transport->nla) < 0)
695 {
696 WLog_Print(transport->log, WLOG_ERROR, "client authentication failure");
697 transport_set_nla_mode(transport, FALSE);
698 nla_free(transport->nla);
699 transport->nla = NULL;
700 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
701 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
702 freerdp_tls_send_alert(transport->tls);
703 return FALSE;
704 }
705
706 /* don't free nla module yet, we need to copy the credentials from it first */
707 transport_set_nla_mode(transport, FALSE);
708 return TRUE;
709}
710
711BOOL transport_accept_rdstls(rdpTransport* transport)
712{
713 BOOL rc = FALSE;
714 rdpRdstls* rdstls = NULL;
715 rdpContext* context = NULL;
716
717 WINPR_ASSERT(transport);
718
719 context = transport_get_context(transport);
720 WINPR_ASSERT(context);
721
722 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
723 goto fail;
724
725 rdstls = rdstls_new(context, transport);
726 if (!rdstls)
727 goto fail;
728
729 transport_set_rdstls_mode(transport, TRUE);
730
731 if (rdstls_authenticate(rdstls) < 0)
732 {
733 WLog_Print(transport->log, WLOG_ERROR, "client authentication failure");
734 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
735 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
736 freerdp_tls_send_alert(transport->tls);
737 goto fail;
738 }
739
740 transport_set_rdstls_mode(transport, FALSE);
741 rc = TRUE;
742fail:
743 rdstls_free(rdstls);
744 return rc;
745}
746
747#define WLog_ERR_BIO(transport, biofunc, bio) \
748 transport_bio_error_log(transport, biofunc, bio, __FILE__, __func__, __LINE__)
749
750static void transport_bio_error_log(rdpTransport* transport, LPCSTR biofunc,
751 WINPR_ATTR_UNUSED BIO* bio, LPCSTR file, LPCSTR func,
752 DWORD line)
753{
754 unsigned long sslerr = 0;
755 int saveerrno = 0;
756 DWORD level = 0;
757
758 WINPR_ASSERT(transport);
759
760 saveerrno = errno;
761 level = WLOG_ERROR;
762
763 if (level < WLog_GetLogLevel(transport->log))
764 return;
765
766 if (ERR_peek_error() == 0)
767 {
768 char ebuffer[256] = { 0 };
769
770 if (saveerrno == 0)
771 WLog_PrintTextMessage(transport->log, level, line, file, func, "%s retries exceeded",
772 biofunc);
773 else
774 WLog_PrintTextMessage(transport->log, level, line, file, func,
775 "%s returned a system error %d: %s", biofunc, saveerrno,
776 winpr_strerror(saveerrno, ebuffer, sizeof(ebuffer)));
777 return;
778 }
779
780 while ((sslerr = ERR_get_error()))
781 {
782 char buf[120] = { 0 };
783
784 ERR_error_string_n(sslerr, buf, 120);
785 WLog_PrintTextMessage(transport->log, level, line, file, func, "%s returned an error: %s",
786 biofunc, buf);
787 }
788}
789
790static SSIZE_T transport_read_layer(rdpTransport* transport, BYTE* data, size_t bytes)
791{
792 SSIZE_T read = 0;
793 rdpRdp* rdp = NULL;
794 rdpContext* context = NULL;
795
796 WINPR_ASSERT(transport);
797
798 context = transport_get_context(transport);
799 WINPR_ASSERT(context);
800
801 rdp = context->rdp;
802 WINPR_ASSERT(rdp);
803
804 if (!transport->frontBio || (bytes > SSIZE_MAX))
805 {
806 transport->layer = TRANSPORT_LAYER_CLOSED;
807 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
808 return -1;
809 }
810
811 while (read < (SSIZE_T)bytes)
812 {
813 const SSIZE_T tr = (SSIZE_T)bytes - read;
814 int r = (int)((tr > INT_MAX) ? INT_MAX : tr);
815 ERR_clear_error();
816 int status = BIO_read(transport->frontBio, data + read, r);
817
818 if (freerdp_shall_disconnect_context(context))
819 return -1;
820
821 if (status <= 0)
822 {
823 if (!transport->frontBio || !BIO_should_retry(transport->frontBio))
824 {
825 /* something unexpected happened, let's close */
826 if (!transport->frontBio)
827 {
828 WLog_Print(transport->log, WLOG_ERROR, "BIO_read: transport->frontBio null");
829 return -1;
830 }
831
832 WLog_ERR_BIO(transport, "BIO_read", transport->frontBio);
833 transport->layer = TRANSPORT_LAYER_CLOSED;
834 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
835 return -1;
836 }
837
838 /* non blocking will survive a partial read */
839 if (!transport->blocking)
840 return read;
841
842 /* blocking means that we can't continue until we have read the number of requested
843 * bytes */
844 if (BIO_wait_read(transport->frontBio, 100) < 0)
845 {
846 WLog_ERR_BIO(transport, "BIO_wait_read", transport->frontBio);
847 return -1;
848 }
849
850 continue;
851 }
852
853#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
854 VALGRIND_MAKE_MEM_DEFINED(data + read, bytes - read);
855#endif
856 read += status;
857 rdp->inBytes += WINPR_ASSERTING_INT_CAST(uint64_t, status);
858 }
859
860 return read;
861}
862
877static SSIZE_T transport_read_layer_bytes(rdpTransport* transport, wStream* s, size_t toRead)
878{
879 SSIZE_T status = 0;
880 if (!transport)
881 return -1;
882
883 if (toRead > SSIZE_MAX)
884 return 0;
885
886 status = IFCALLRESULT(-1, transport->io.ReadBytes, transport, Stream_Pointer(s), toRead);
887
888 if (status <= 0)
889 return status;
890
891 Stream_Seek(s, (size_t)status);
892 return status == (SSIZE_T)toRead ? 1 : 0;
893}
894
907int transport_read_pdu(rdpTransport* transport, wStream* s)
908{
909 if (!transport)
910 return -1;
911 return IFCALLRESULT(-1, transport->io.ReadPdu, transport, s);
912}
913
914static SSIZE_T parse_nla_mode_pdu(rdpTransport* transport, wStream* stream)
915{
916 SSIZE_T pduLength = 0;
917 wStream sbuffer = { 0 };
918 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
919 /*
920 * In case NlaMode is set TSRequest package(s) are expected
921 * 0x30 = DER encoded data with these bits set:
922 * bit 6 P/C constructed
923 * bit 5 tag number - sequence
924 */
925 UINT8 typeEncoding = 0;
926 if (Stream_GetRemainingLength(s) < 1)
927 return 0;
928 Stream_Read_UINT8(s, typeEncoding);
929 if (typeEncoding == 0x30)
930 {
931 /* TSRequest (NLA) */
932 UINT8 lengthEncoding = 0;
933 if (Stream_GetRemainingLength(s) < 1)
934 return 0;
935 Stream_Read_UINT8(s, lengthEncoding);
936 if (lengthEncoding & 0x80)
937 {
938 if ((lengthEncoding & ~(0x80)) == 1)
939 {
940 UINT8 length = 0;
941 if (Stream_GetRemainingLength(s) < 1)
942 return 0;
943 Stream_Read_UINT8(s, length);
944 pduLength = length;
945 pduLength += 3;
946 }
947 else if ((lengthEncoding & ~(0x80)) == 2)
948 {
949 /* check for header bytes already read in previous calls */
950 UINT16 length = 0;
951 if (Stream_GetRemainingLength(s) < 2)
952 return 0;
953 Stream_Read_UINT16_BE(s, length);
954 pduLength = length;
955 pduLength += 4;
956 }
957 else
958 {
959 WLog_Print(transport->log, WLOG_ERROR, "Error reading TSRequest!");
960 return -1;
961 }
962 }
963 else
964 {
965 pduLength = lengthEncoding;
966 pduLength += 2;
967 }
968 }
969
970 return pduLength;
971}
972
973static SSIZE_T parse_default_mode_pdu(rdpTransport* transport, wStream* stream)
974{
975 SSIZE_T pduLength = 0;
976 wStream sbuffer = { 0 };
977 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
978
979 UINT8 version = 0;
980 if (Stream_GetRemainingLength(s) < 1)
981 return 0;
982 Stream_Read_UINT8(s, version);
983 if (version == 0x03)
984 {
985 /* TPKT header */
986 UINT16 length = 0;
987 if (Stream_GetRemainingLength(s) < 3)
988 return 0;
989 Stream_Seek(s, 1);
990 Stream_Read_UINT16_BE(s, length);
991 pduLength = length;
992
993 /* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */
994 if ((pduLength < 7) || (pduLength > 0xFFFF))
995 {
996 WLog_Print(transport->log, WLOG_ERROR, "tpkt - invalid pduLength: %" PRIdz, pduLength);
997 return -1;
998 }
999 }
1000 else
1001 {
1002 /* Fast-Path Header */
1003 UINT8 length1 = 0;
1004 if (Stream_GetRemainingLength(s) < 1)
1005 return 0;
1006 Stream_Read_UINT8(s, length1);
1007 if (length1 & 0x80)
1008 {
1009 UINT8 length2 = 0;
1010 if (Stream_GetRemainingLength(s) < 1)
1011 return 0;
1012 Stream_Read_UINT8(s, length2);
1013 pduLength = ((length1 & 0x7F) << 8) | length2;
1014 }
1015 else
1016 pduLength = length1;
1017
1018 /*
1019 * fast-path has 7 bits for length so the maximum size, including headers is 0x8000
1020 * The theoretical minimum fast-path PDU consists only of two header bytes plus one
1021 * byte for data (e.g. fast-path input synchronize pdu)
1022 */
1023 if (pduLength < 3 || pduLength > 0x8000)
1024 {
1025 WLog_Print(transport->log, WLOG_ERROR, "fast path - invalid pduLength: %" PRIdz,
1026 pduLength);
1027 return -1;
1028 }
1029 }
1030
1031 return pduLength;
1032}
1033
1034SSIZE_T transport_parse_pdu(rdpTransport* transport, wStream* s, BOOL* incomplete)
1035{
1036 SSIZE_T pduLength = 0;
1037
1038 if (!transport)
1039 return -1;
1040
1041 if (!s)
1042 return -1;
1043
1044 if (incomplete)
1045 *incomplete = TRUE;
1046
1047 Stream_SealLength(s);
1048 if (transport->NlaMode)
1049 pduLength = parse_nla_mode_pdu(transport, s);
1050 else if (transport->RdstlsMode)
1051 pduLength = rdstls_parse_pdu(transport->log, s);
1052 else
1053 pduLength = parse_default_mode_pdu(transport, s);
1054
1055 if (pduLength <= 0)
1056 return pduLength;
1057
1058 const size_t len = Stream_Length(s);
1059 if (len > WINPR_ASSERTING_INT_CAST(size_t, pduLength))
1060 return -1;
1061
1062 if (incomplete)
1063 *incomplete = len < WINPR_ASSERTING_INT_CAST(size_t, pduLength);
1064
1065 return pduLength;
1066}
1067
1068static int transport_default_read_pdu(rdpTransport* transport, wStream* s)
1069{
1070 BOOL incomplete = 0;
1071 SSIZE_T status = 0;
1072 size_t pduLength = 0;
1073 size_t position = 0;
1074
1075 WINPR_ASSERT(transport);
1076 WINPR_ASSERT(s);
1077
1078 /* RDS AAD Auth PDUs have no length indicator. We need to determine the end of the PDU by
1079 * reading in one byte at a time until we encounter the terminating null byte */
1080 if (transport->AadMode)
1081 {
1082 BYTE c = '\0';
1083 do
1084 {
1085 const SSIZE_T rc = transport_read_layer(transport, &c, 1);
1086 if (rc != 1)
1087 return (rc == 0) ? 0 : -1;
1088 if (!Stream_EnsureRemainingCapacity(s, 1))
1089 return -1;
1090 Stream_Write_UINT8(s, c);
1091 } while (c != '\0');
1092 }
1093 else if (transport->earlyUserAuth)
1094 {
1095 if (!Stream_EnsureCapacity(s, 4))
1096 return -1;
1097 const SSIZE_T rc = transport_read_layer_bytes(transport, s, 4);
1098 if (rc != 1)
1099 return (rc == 0) ? 0 : -1;
1100 }
1101 else
1102 {
1103 /* Read in pdu length */
1104 status = transport_parse_pdu(transport, s, &incomplete);
1105 while ((status == 0) && incomplete)
1106 {
1107 if (!Stream_EnsureRemainingCapacity(s, 1))
1108 return -1;
1109 SSIZE_T rc = transport_read_layer_bytes(transport, s, 1);
1110 if (rc > INT32_MAX)
1111 return INT32_MAX;
1112 if (rc != 1)
1113 return (int)rc;
1114 status = transport_parse_pdu(transport, s, &incomplete);
1115 }
1116
1117 if (status < 0)
1118 return -1;
1119
1120 pduLength = (size_t)status;
1121
1122 /* Read in rest of the PDU */
1123 if (!Stream_EnsureCapacity(s, pduLength))
1124 return -1;
1125
1126 position = Stream_GetPosition(s);
1127 if (position > pduLength)
1128 return -1;
1129 else if (position < pduLength)
1130 {
1131 status = transport_read_layer_bytes(transport, s, pduLength - position);
1132 if (status != 1)
1133 {
1134 if ((status < INT32_MIN) || (status > INT32_MAX))
1135 return -1;
1136 return (int)status;
1137 }
1138 }
1139
1140 if (Stream_GetPosition(s) >= pduLength)
1141 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength,
1142 WLOG_PACKET_INBOUND);
1143 }
1144
1145 Stream_SealLength(s);
1146 Stream_SetPosition(s, 0);
1147 const size_t len = Stream_Length(s);
1148 if (len > INT32_MAX)
1149 return -1;
1150 return (int)len;
1151}
1152
1153int transport_write(rdpTransport* transport, wStream* s)
1154{
1155 if (!transport)
1156 return -1;
1157
1158 return IFCALLRESULT(-1, transport->io.WritePdu, transport, s);
1159}
1160
1161static int transport_default_write(rdpTransport* transport, wStream* s)
1162{
1163 int status = -1;
1164 rdpContext* context = transport_get_context(transport);
1165
1166 WINPR_ASSERT(transport);
1167 WINPR_ASSERT(context);
1168
1169 if (!s)
1170 return -1;
1171
1172 Stream_AddRef(s);
1173
1174 rdpRdp* rdp = context->rdp;
1175 if (!rdp)
1176 goto fail;
1177
1178 EnterCriticalSection(&(transport->WriteLock));
1179 if (!transport->frontBio)
1180 goto out_cleanup;
1181
1182 size_t length = Stream_GetPosition(s);
1183 size_t writtenlength = length;
1184 Stream_SetPosition(s, 0);
1185
1186 if (length > 0)
1187 {
1188 rdp->outBytes += length;
1189 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
1190 }
1191
1192 while (length > 0)
1193 {
1194 ERR_clear_error();
1195 const int towrite = (length > INT32_MAX) ? INT32_MAX : (int)length;
1196 status = BIO_write(transport->frontBio, Stream_ConstPointer(s), towrite);
1197
1198 if (status <= 0)
1199 {
1200 /* the buffered BIO that is at the end of the chain always says OK for writing,
1201 * so a retry means that for any reason we need to read. The most probable
1202 * is a SSL or TSG BIO in the chain.
1203 */
1204 if (!BIO_should_retry(transport->frontBio))
1205 {
1206 WLog_ERR_BIO(transport, "BIO_should_retry", transport->frontBio);
1207 goto out_cleanup;
1208 }
1209
1210 /* non-blocking can live with blocked IOs */
1211 if (!transport->blocking)
1212 {
1213 WLog_ERR_BIO(transport, "BIO_write", transport->frontBio);
1214 goto out_cleanup;
1215 }
1216
1217 if (BIO_wait_write(transport->frontBio, 100) < 0)
1218 {
1219 WLog_ERR_BIO(transport, "BIO_wait_write", transport->frontBio);
1220 status = -1;
1221 goto out_cleanup;
1222 }
1223
1224 continue;
1225 }
1226
1227 WINPR_ASSERT(context->settings);
1228 if (transport->blocking || context->settings->WaitForOutputBufferFlush)
1229 {
1230 while (BIO_write_blocked(transport->frontBio))
1231 {
1232 if (BIO_wait_write(transport->frontBio, 100) < 0)
1233 {
1234 WLog_Print(transport->log, WLOG_ERROR, "error when selecting for write");
1235 status = -1;
1236 goto out_cleanup;
1237 }
1238
1239 if (BIO_flush(transport->frontBio) < 1)
1240 {
1241 WLog_Print(transport->log, WLOG_ERROR, "error when flushing outputBuffer");
1242 status = -1;
1243 goto out_cleanup;
1244 }
1245 }
1246 }
1247
1248 const size_t ustatus = (size_t)status;
1249 if (ustatus > length)
1250 {
1251 status = -1;
1252 goto out_cleanup;
1253 }
1254
1255 length -= ustatus;
1256 Stream_Seek(s, ustatus);
1257 }
1258
1259 transport->written += writtenlength;
1260out_cleanup:
1261
1262 if (status < 0)
1263 {
1264 /* A write error indicates that the peer has dropped the connection */
1265 transport->layer = TRANSPORT_LAYER_CLOSED;
1266 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1267 }
1268
1269 LeaveCriticalSection(&(transport->WriteLock));
1270fail:
1271 Stream_Release(s);
1272 return status;
1273}
1274
1275BOOL transport_get_public_key(rdpTransport* transport, const BYTE** data, DWORD* length)
1276{
1277 return IFCALLRESULT(FALSE, transport->io.GetPublicKey, transport, data, length);
1278}
1279
1280static BOOL transport_default_get_public_key(rdpTransport* transport, const BYTE** data,
1281 DWORD* length)
1282{
1283 rdpTls* tls = transport_get_tls(transport);
1284 if (!tls)
1285 return FALSE;
1286
1287 *data = tls->PublicKey;
1288 *length = tls->PublicKeyLength;
1289
1290 return TRUE;
1291}
1292
1293DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count)
1294{
1295 DWORD nCount = 0; /* always the reread Event */
1296
1297 WINPR_ASSERT(transport);
1298 WINPR_ASSERT(events);
1299 WINPR_ASSERT(count > 0);
1300
1301 if (events)
1302 {
1303 if (count < 1)
1304 {
1305 WLog_Print(transport->log, WLOG_ERROR, "provided handles array is too small");
1306 return 0;
1307 }
1308
1309 events[nCount++] = transport->rereadEvent;
1310
1311 if (transport->useIoEvent)
1312 {
1313 if (count < 2)
1314 return 0;
1315 events[nCount++] = transport->ioEvent;
1316 }
1317 }
1318
1319 if (!transport->GatewayEnabled)
1320 {
1321 if (events)
1322 {
1323 if (nCount >= count)
1324 {
1325 WLog_Print(transport->log, WLOG_ERROR,
1326 "provided handles array is too small (count=%" PRIu32 " nCount=%" PRIu32
1327 ")",
1328 count, nCount);
1329 return 0;
1330 }
1331
1332 if (transport->frontBio)
1333 {
1334 if (BIO_get_event(transport->frontBio, &events[nCount]) != 1)
1335 {
1336 WLog_Print(transport->log, WLOG_ERROR, "error getting the frontBio handle");
1337 return 0;
1338 }
1339 nCount++;
1340 }
1341 }
1342 }
1343 else
1344 {
1345 if (transport->rdg)
1346 {
1347 const DWORD tmp =
1348 rdg_get_event_handles(transport->rdg, &events[nCount], count - nCount);
1349
1350 if (tmp == 0)
1351 return 0;
1352
1353 nCount += tmp;
1354 }
1355 else if (transport->tsg)
1356 {
1357 const DWORD tmp =
1358 tsg_get_event_handles(transport->tsg, &events[nCount], count - nCount);
1359
1360 if (tmp == 0)
1361 return 0;
1362
1363 nCount += tmp;
1364 }
1365 else if (transport->wst)
1366 {
1367 const DWORD tmp =
1368 wst_get_event_handles(transport->wst, &events[nCount], count - nCount);
1369
1370 if (tmp == 0)
1371 return 0;
1372
1373 nCount += tmp;
1374 }
1375 }
1376
1377 return nCount;
1378}
1379
1380#if defined(WITH_FREERDP_DEPRECATED)
1381void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
1382{
1383 DWORD nCount = 0;
1384 HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
1385
1386 WINPR_ASSERT(transport);
1387 WINPR_ASSERT(rfds);
1388 WINPR_ASSERT(rcount);
1389
1390 nCount = transport_get_event_handles(transport, events, ARRAYSIZE(events));
1391 *rcount = nCount + 1;
1392
1393 for (DWORD index = 0; index < nCount; index++)
1394 {
1395 rfds[index] = GetEventWaitObject(events[index]);
1396 }
1397
1398 rfds[nCount] = GetEventWaitObject(transport->rereadEvent);
1399}
1400#endif
1401
1402BOOL transport_is_write_blocked(rdpTransport* transport)
1403{
1404 WINPR_ASSERT(transport);
1405 WINPR_ASSERT(transport->frontBio);
1406 return BIO_write_blocked(transport->frontBio) != 0;
1407}
1408
1409int transport_drain_output_buffer(rdpTransport* transport)
1410{
1411 BOOL status = FALSE;
1412
1413 WINPR_ASSERT(transport);
1414 WINPR_ASSERT(transport->frontBio);
1415 if (BIO_write_blocked(transport->frontBio))
1416 {
1417 if (BIO_flush(transport->frontBio) < 1)
1418 return -1;
1419
1420 const long rc = BIO_write_blocked(transport->frontBio);
1421 status = (rc != 0);
1422 }
1423
1424 return status;
1425}
1426
1427int transport_check_fds(rdpTransport* transport)
1428{
1429 int status = 0;
1430 state_run_t recv_status = STATE_RUN_FAILED;
1431 wStream* received = NULL;
1432 rdpContext* context = transport_get_context(transport);
1433
1434 WINPR_ASSERT(context);
1435
1436 if (transport->layer == TRANSPORT_LAYER_CLOSED)
1437 {
1438 WLog_Print(transport->log, WLOG_DEBUG, "transport_check_fds: transport layer closed");
1439 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1440 return -1;
1441 }
1442
1452 if ((status = transport_read_pdu(transport, transport->ReceiveBuffer)) <= 0)
1453 {
1454 if (status < 0)
1455 WLog_Print(transport->log, WLOG_DEBUG, "transport_check_fds: transport_read_pdu() - %i",
1456 status);
1457 if (transport->haveMoreBytesToRead)
1458 {
1459 transport->haveMoreBytesToRead = FALSE;
1460 (void)ResetEvent(transport->rereadEvent);
1461 }
1462 return status;
1463 }
1464
1465 received = transport->ReceiveBuffer;
1466 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1467 if (!transport->ReceiveBuffer)
1468 {
1469 Stream_Release(received);
1470 return -1;
1471 }
1472
1479 WINPR_ASSERT(transport->ReceiveCallback);
1480 recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
1481 Stream_Release(received);
1482
1483 if (state_run_failed(recv_status))
1484 {
1485 char buffer[64] = { 0 };
1486 WLog_Print(transport->log, WLOG_ERROR,
1487 "transport_check_fds: transport->ReceiveCallback() - %s",
1488 state_run_result_string(recv_status, buffer, ARRAYSIZE(buffer)));
1489 return -1;
1490 }
1491
1492 /* Run this again to be sure we consumed all input data.
1493 * This will be repeated until a (not fully) received packet is in buffer
1494 */
1495 if (!transport->haveMoreBytesToRead)
1496 {
1497 transport->haveMoreBytesToRead = TRUE;
1498 (void)SetEvent(transport->rereadEvent);
1499 }
1500 return recv_status;
1501}
1502
1503BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1504{
1505 WINPR_ASSERT(transport);
1506
1507 return IFCALLRESULT(FALSE, transport->io.SetBlockingMode, transport, blocking);
1508}
1509
1510static BOOL transport_default_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1511{
1512 WINPR_ASSERT(transport);
1513
1514 transport->blocking = blocking;
1515
1516 if (transport->frontBio)
1517 {
1518 if (!BIO_set_nonblock(transport->frontBio, blocking ? FALSE : TRUE))
1519 return FALSE;
1520 }
1521
1522 return TRUE;
1523}
1524
1525rdpTransportLayer* transport_connect_layer(rdpTransport* transport, const char* hostname, int port,
1526 DWORD timeout)
1527{
1528 WINPR_ASSERT(transport);
1529
1530 return IFCALLRESULT(NULL, transport->io.ConnectLayer, transport, hostname, port, timeout);
1531}
1532
1533static rdpTransportLayer* transport_default_connect_layer(rdpTransport* transport,
1534 const char* hostname, int port,
1535 DWORD timeout)
1536{
1537 rdpContext* context = transport_get_context(transport);
1538 WINPR_ASSERT(context);
1539
1540 return freerdp_tcp_connect_layer(context, hostname, port, timeout);
1541}
1542
1543BOOL transport_attach_layer(rdpTransport* transport, rdpTransportLayer* layer)
1544{
1545 WINPR_ASSERT(transport);
1546 WINPR_ASSERT(layer);
1547
1548 return IFCALLRESULT(FALSE, transport->io.AttachLayer, transport, layer);
1549}
1550
1551static BOOL transport_default_attach_layer(rdpTransport* transport, rdpTransportLayer* layer)
1552{
1553 BIO* layerBio = BIO_new(BIO_s_transport_layer());
1554 if (!layerBio)
1555 goto fail;
1556
1557 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
1558 if (!bufferedBio)
1559 goto fail;
1560
1561 bufferedBio = BIO_push(bufferedBio, layerBio);
1562 if (!bufferedBio)
1563 goto fail;
1564
1565 /* BIO takes over the layer reference at this point. */
1566 BIO_set_data(layerBio, layer);
1567
1568 transport->frontBio = bufferedBio;
1569
1570 return TRUE;
1571
1572fail:
1573 if (layerBio)
1574 BIO_free_all(layerBio);
1575
1576 return FALSE;
1577}
1578
1579void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled)
1580{
1581 WINPR_ASSERT(transport);
1582 transport->GatewayEnabled = GatewayEnabled;
1583}
1584
1585void transport_set_nla_mode(rdpTransport* transport, BOOL NlaMode)
1586{
1587 WINPR_ASSERT(transport);
1588 transport->NlaMode = NlaMode;
1589}
1590
1591void transport_set_rdstls_mode(rdpTransport* transport, BOOL RdstlsMode)
1592{
1593 WINPR_ASSERT(transport);
1594 transport->RdstlsMode = RdstlsMode;
1595}
1596
1597void transport_set_aad_mode(rdpTransport* transport, BOOL AadMode)
1598{
1599 WINPR_ASSERT(transport);
1600 transport->AadMode = AadMode;
1601}
1602
1603BOOL transport_disconnect(rdpTransport* transport)
1604{
1605 if (!transport)
1606 return FALSE;
1607 return IFCALLRESULT(FALSE, transport->io.TransportDisconnect, transport);
1608}
1609
1610static BOOL transport_default_disconnect(rdpTransport* transport)
1611{
1612 BOOL status = TRUE;
1613
1614 if (!transport)
1615 return FALSE;
1616
1617 EnterCriticalSection(&(transport->ReadLock));
1618 EnterCriticalSection(&(transport->WriteLock));
1619 if (transport->tls)
1620 {
1621 freerdp_tls_free(transport->tls);
1622 transport->tls = NULL;
1623 }
1624 else
1625 {
1626 if (transport->frontBio)
1627 BIO_free_all(transport->frontBio);
1628 }
1629
1630 if (transport->tsg)
1631 {
1632 tsg_free(transport->tsg);
1633 transport->tsg = NULL;
1634 }
1635
1636 if (transport->rdg)
1637 {
1638 rdg_free(transport->rdg);
1639 transport->rdg = NULL;
1640 }
1641
1642 if (transport->wst)
1643 {
1644 wst_free(transport->wst);
1645 transport->wst = NULL;
1646 }
1647
1648 transport->frontBio = NULL;
1649 transport->layer = TRANSPORT_LAYER_TCP;
1650 transport->earlyUserAuth = FALSE;
1651 LeaveCriticalSection(&(transport->WriteLock));
1652 LeaveCriticalSection(&(transport->ReadLock));
1653 return status;
1654}
1655
1656rdpTransport* transport_new(rdpContext* context)
1657{
1658 rdpTransport* transport = (rdpTransport*)calloc(1, sizeof(rdpTransport));
1659
1660 WINPR_ASSERT(context);
1661 if (!transport)
1662 return NULL;
1663
1664 transport->log = WLog_Get(TAG);
1665
1666 if (!transport->log)
1667 goto fail;
1668
1669 transport->context = context;
1670 transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
1671
1672 if (!transport->ReceivePool)
1673 goto fail;
1674
1675 /* receive buffer for non-blocking read. */
1676 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1677
1678 if (!transport->ReceiveBuffer)
1679 goto fail;
1680
1681 transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1682
1683 if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
1684 goto fail;
1685
1686 transport->rereadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1687
1688 if (!transport->rereadEvent || transport->rereadEvent == INVALID_HANDLE_VALUE)
1689 goto fail;
1690
1691 transport->ioEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1692
1693 if (!transport->ioEvent || transport->ioEvent == INVALID_HANDLE_VALUE)
1694 goto fail;
1695
1696 transport->haveMoreBytesToRead = FALSE;
1697 transport->blocking = TRUE;
1698 transport->GatewayEnabled = FALSE;
1699 transport->layer = TRANSPORT_LAYER_TCP;
1700
1701 if (!InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000))
1702 goto fail;
1703
1704 if (!InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000))
1705 goto fail;
1706
1707 // transport->io.DataHandler = transport_data_handler;
1708 transport->io.TCPConnect = freerdp_tcp_default_connect;
1709 transport->io.TLSConnect = transport_default_connect_tls;
1710 transport->io.TLSAccept = transport_default_accept_tls;
1711 transport->io.TransportAttach = transport_default_attach;
1712 transport->io.TransportDisconnect = transport_default_disconnect;
1713 transport->io.ReadPdu = transport_default_read_pdu;
1714 transport->io.WritePdu = transport_default_write;
1715 transport->io.ReadBytes = transport_read_layer;
1716 transport->io.GetPublicKey = transport_default_get_public_key;
1717 transport->io.SetBlockingMode = transport_default_set_blocking_mode;
1718 transport->io.ConnectLayer = transport_default_connect_layer;
1719 transport->io.AttachLayer = transport_default_attach_layer;
1720
1721 return transport;
1722fail:
1723 WINPR_PRAGMA_DIAG_PUSH
1724 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1725 transport_free(transport);
1726 WINPR_PRAGMA_DIAG_POP
1727 return NULL;
1728}
1729
1730void transport_free(rdpTransport* transport)
1731{
1732 if (!transport)
1733 return;
1734
1735 transport_disconnect(transport);
1736
1737 EnterCriticalSection(&(transport->ReadLock));
1738 if (transport->ReceiveBuffer)
1739 Stream_Release(transport->ReceiveBuffer);
1740 LeaveCriticalSection(&(transport->ReadLock));
1741
1742 (void)StreamPool_WaitForReturn(transport->ReceivePool, INFINITE);
1743
1744 EnterCriticalSection(&(transport->ReadLock));
1745 EnterCriticalSection(&(transport->WriteLock));
1746
1747 nla_free(transport->nla);
1748 StreamPool_Free(transport->ReceivePool);
1749 (void)CloseHandle(transport->connectedEvent);
1750 (void)CloseHandle(transport->rereadEvent);
1751 (void)CloseHandle(transport->ioEvent);
1752
1753 LeaveCriticalSection(&(transport->ReadLock));
1754 DeleteCriticalSection(&(transport->ReadLock));
1755
1756 LeaveCriticalSection(&(transport->WriteLock));
1757 DeleteCriticalSection(&(transport->WriteLock));
1758 free(transport);
1759}
1760
1761BOOL transport_set_io_callbacks(rdpTransport* transport, const rdpTransportIo* io_callbacks)
1762{
1763 if (!transport || !io_callbacks)
1764 return FALSE;
1765
1766 transport->io = *io_callbacks;
1767 return TRUE;
1768}
1769
1770const rdpTransportIo* transport_get_io_callbacks(const rdpTransport* transport)
1771{
1772 if (!transport)
1773 return NULL;
1774 return &transport->io;
1775}
1776
1777rdpContext* transport_get_context(rdpTransport* transport)
1778{
1779 WINPR_ASSERT(transport);
1780 return transport->context;
1781}
1782
1783rdpTransport* freerdp_get_transport(rdpContext* context)
1784{
1785 WINPR_ASSERT(context);
1786 WINPR_ASSERT(context->rdp);
1787 return context->rdp->transport;
1788}
1789
1790BOOL transport_set_nla(rdpTransport* transport, rdpNla* nla)
1791{
1792 WINPR_ASSERT(transport);
1793 nla_free(transport->nla);
1794 transport->nla = nla;
1795 return TRUE;
1796}
1797
1798rdpNla* transport_get_nla(rdpTransport* transport)
1799{
1800 WINPR_ASSERT(transport);
1801 return transport->nla;
1802}
1803
1804BOOL transport_set_tls(rdpTransport* transport, rdpTls* tls)
1805{
1806 WINPR_ASSERT(transport);
1807 freerdp_tls_free(transport->tls);
1808 transport->tls = tls;
1809 return TRUE;
1810}
1811
1812rdpTls* transport_get_tls(rdpTransport* transport)
1813{
1814 WINPR_ASSERT(transport);
1815 return transport->tls;
1816}
1817
1818BOOL transport_set_tsg(rdpTransport* transport, rdpTsg* tsg)
1819{
1820 WINPR_ASSERT(transport);
1821 tsg_free(transport->tsg);
1822 transport->tsg = tsg;
1823 return TRUE;
1824}
1825
1826rdpTsg* transport_get_tsg(rdpTransport* transport)
1827{
1828 WINPR_ASSERT(transport);
1829 return transport->tsg;
1830}
1831
1832wStream* transport_take_from_pool(rdpTransport* transport, size_t size)
1833{
1834 WINPR_ASSERT(transport);
1835 if (!transport->frontBio)
1836 return NULL;
1837 return StreamPool_Take(transport->ReceivePool, size);
1838}
1839
1840UINT64 transport_get_bytes_sent(rdpTransport* transport, BOOL resetCount)
1841{
1842 UINT64 rc = 0;
1843 WINPR_ASSERT(transport);
1844 rc = transport->written;
1845 if (resetCount)
1846 transport->written = 0;
1847 return rc;
1848}
1849
1850TRANSPORT_LAYER transport_get_layer(rdpTransport* transport)
1851{
1852 WINPR_ASSERT(transport);
1853 return transport->layer;
1854}
1855
1856BOOL transport_set_layer(rdpTransport* transport, TRANSPORT_LAYER layer)
1857{
1858 WINPR_ASSERT(transport);
1859 transport->layer = layer;
1860 return TRUE;
1861}
1862
1863BOOL transport_set_connected_event(rdpTransport* transport)
1864{
1865 WINPR_ASSERT(transport);
1866 return SetEvent(transport->connectedEvent);
1867}
1868
1869BOOL transport_set_recv_callbacks(rdpTransport* transport, TransportRecv recv, void* extra)
1870{
1871 WINPR_ASSERT(transport);
1872 transport->ReceiveCallback = recv;
1873 transport->ReceiveExtra = extra;
1874 return TRUE;
1875}
1876
1877BOOL transport_get_blocking(const rdpTransport* transport)
1878{
1879 WINPR_ASSERT(transport);
1880 return transport->blocking;
1881}
1882
1883BOOL transport_set_blocking(rdpTransport* transport, BOOL blocking)
1884{
1885 WINPR_ASSERT(transport);
1886 transport->blocking = blocking;
1887 return TRUE;
1888}
1889
1890BOOL transport_have_more_bytes_to_read(rdpTransport* transport)
1891{
1892 WINPR_ASSERT(transport);
1893 return transport->haveMoreBytesToRead;
1894}
1895
1896int transport_tcp_connect(rdpTransport* transport, const char* hostname, int port, DWORD timeout)
1897{
1898 rdpContext* context = transport_get_context(transport);
1899 WINPR_ASSERT(context);
1900 WINPR_ASSERT(context->settings);
1901 return IFCALLRESULT(-1, transport->io.TCPConnect, context, context->settings, hostname, port,
1902 timeout);
1903}
1904
1905HANDLE transport_get_front_bio(rdpTransport* transport)
1906{
1907 HANDLE hEvent = NULL;
1908 WINPR_ASSERT(transport);
1909 WINPR_ASSERT(transport->frontBio);
1910
1911 BIO_get_event(transport->frontBio, &hEvent);
1912 return hEvent;
1913}
1914
1915BOOL transport_io_callback_set_event(rdpTransport* transport, BOOL set)
1916{
1917 WINPR_ASSERT(transport);
1918 transport->useIoEvent = TRUE;
1919 if (!set)
1920 return ResetEvent(transport->ioEvent);
1921 return SetEvent(transport->ioEvent);
1922}
1923
1924void transport_set_early_user_auth_mode(rdpTransport* transport, BOOL EUAMode)
1925{
1926 WINPR_ASSERT(transport);
1927 transport->earlyUserAuth = EUAMode;
1928 WLog_Print(transport->log, WLOG_DEBUG, "Early User Auth Mode: %s", EUAMode ? "on" : "off");
1929}
1930
1931rdpTransportLayer* transport_layer_new(WINPR_ATTR_UNUSED rdpTransport* transport,
1932 size_t contextSize)
1933{
1934 rdpTransportLayerInt* layer = (rdpTransportLayerInt*)calloc(1, sizeof(rdpTransportLayerInt));
1935 if (!layer)
1936 return NULL;
1937
1938 if (contextSize)
1939 {
1940 layer->userContextShadowPtr = calloc(1, contextSize);
1941 if (!layer->userContextShadowPtr)
1942 {
1943 free(layer);
1944 return NULL;
1945 }
1946 }
1947 layer->pub.userContext = layer->userContextShadowPtr;
1948
1949 return &layer->pub;
1950}
1951
1952void transport_layer_free(rdpTransportLayer* layer)
1953{
1954 rdpTransportLayerInt* intern = (rdpTransportLayerInt*)layer;
1955 if (!layer)
1956 return;
1957
1958 IFCALL(intern->pub.Close, intern->pub.userContext);
1959 free(intern->userContextShadowPtr);
1960 free(intern);
1961}
1962
1963static int transport_layer_bio_write(BIO* bio, const char* buf, int size)
1964{
1965 if (!buf || !size)
1966 return 0;
1967 if (size < 0)
1968 return -1;
1969
1970 WINPR_ASSERT(bio);
1971
1972 rdpTransportLayer* layer = (rdpTransportLayer*)BIO_get_data(bio);
1973 if (!layer)
1974 return -1;
1975
1976 BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
1977
1978 errno = 0;
1979 const int status = IFCALLRESULT(-1, layer->Write, layer->userContext, buf, size);
1980
1981 if (status >= 0 && status < size)
1982 BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
1983
1984 switch (errno)
1985 {
1986 case EAGAIN:
1987 BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
1988 break;
1989 default:
1990 break;
1991 }
1992
1993 return status;
1994}
1995
1996static int transport_layer_bio_read(BIO* bio, char* buf, int size)
1997{
1998 if (!buf || !size)
1999 return 0;
2000 if (size < 0)
2001 return -1;
2002
2003 WINPR_ASSERT(bio);
2004
2005 rdpTransportLayer* layer = (rdpTransportLayer*)BIO_get_data(bio);
2006 if (!layer)
2007 return -1;
2008
2009 BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
2010 errno = 0;
2011 const int status = IFCALLRESULT(-1, layer->Read, layer->userContext, buf, size);
2012
2013 switch (errno)
2014 {
2015 case EAGAIN:
2016 BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
2017 break;
2018 default:
2019 break;
2020 }
2021
2022 return status;
2023}
2024
2025static int transport_layer_bio_puts(WINPR_ATTR_UNUSED BIO* bio, WINPR_ATTR_UNUSED const char* str)
2026{
2027 return -2;
2028}
2029
2030static int transport_layer_bio_gets(WINPR_ATTR_UNUSED BIO* bio, WINPR_ATTR_UNUSED char* str,
2031 WINPR_ATTR_UNUSED int size)
2032{
2033 return 1;
2034}
2035
2036static long transport_layer_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
2037{
2038 WINPR_ASSERT(bio);
2039
2040 rdpTransportLayer* layer = (rdpTransportLayer*)BIO_get_data(bio);
2041 if (!layer)
2042 return -1;
2043
2044 int status = -1;
2045 switch (cmd)
2046 {
2047 case BIO_C_GET_EVENT:
2048 *((HANDLE*)arg2) = IFCALLRESULT(NULL, layer->GetEvent, layer->userContext);
2049 status = 1;
2050 break;
2051
2052 case BIO_C_SET_NONBLOCK:
2053 status = 1;
2054 break;
2055
2056 case BIO_C_WAIT_READ:
2057 {
2058 int timeout = (int)arg1;
2059 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, FALSE,
2060 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2061 /* Convert timeout to error return */
2062 if (!r)
2063 {
2064 errno = ETIMEDOUT;
2065 status = 0;
2066 }
2067 else
2068 status = 1;
2069 break;
2070 }
2071
2072 case BIO_C_WAIT_WRITE:
2073 {
2074 int timeout = (int)arg1;
2075 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, TRUE,
2076 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2077 /* Convert timeout to error return */
2078 if (!r)
2079 {
2080 errno = ETIMEDOUT;
2081 status = 0;
2082 }
2083 else
2084 status = 1;
2085 break;
2086 }
2087
2088 case BIO_CTRL_GET_CLOSE:
2089 status = BIO_get_shutdown(bio);
2090 break;
2091
2092 case BIO_CTRL_SET_CLOSE:
2093 BIO_set_shutdown(bio, (int)arg1);
2094 status = 1;
2095 break;
2096
2097 case BIO_CTRL_FLUSH:
2098 case BIO_CTRL_DUP:
2099 status = 1;
2100 break;
2101
2102 default:
2103 status = 0;
2104 break;
2105 }
2106
2107 return status;
2108}
2109
2110static int transport_layer_bio_new(BIO* bio)
2111{
2112 WINPR_ASSERT(bio);
2113
2114 BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
2115 BIO_set_init(bio, 1);
2116 return 1;
2117}
2118
2119static int transport_layer_bio_free(BIO* bio)
2120{
2121 if (!bio)
2122 return 0;
2123
2124 rdpTransportLayer* layer = (rdpTransportLayer*)BIO_get_data(bio);
2125 if (layer)
2126 transport_layer_free(layer);
2127
2128 BIO_set_data(bio, NULL);
2129 BIO_set_init(bio, 0);
2130 BIO_set_flags(bio, 0);
2131
2132 return 1;
2133}
2134
2135BIO_METHOD* BIO_s_transport_layer(void)
2136{
2137 static BIO_METHOD* bio_methods = NULL;
2138
2139 if (bio_methods == NULL)
2140 {
2141 if (!(bio_methods = BIO_meth_new(BIO_TYPE_SIMPLE, "TransportLayer")))
2142 return NULL;
2143
2144 BIO_meth_set_write(bio_methods, transport_layer_bio_write);
2145 BIO_meth_set_read(bio_methods, transport_layer_bio_read);
2146 BIO_meth_set_puts(bio_methods, transport_layer_bio_puts);
2147 BIO_meth_set_gets(bio_methods, transport_layer_bio_gets);
2148 BIO_meth_set_ctrl(bio_methods, transport_layer_bio_ctrl);
2149 BIO_meth_set_create(bio_methods, transport_layer_bio_new);
2150 BIO_meth_set_destroy(bio_methods, transport_layer_bio_free);
2151 }
2152
2153 return bio_methods;
2154}
FREERDP_API const char * freerdp_settings_get_server_name(const rdpSettings *settings)
A helper function to return the correct server name.