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