Coverage Report

Created: 2023-11-27 07:17

/src/FreeRDP/libfreerdp/core/transport.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Network Transport Layer
4
 *
5
 * Copyright 2011 Vic Lee
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
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
#include "settings.h"
60
61
#include "gateway/rdg.h"
62
#include "gateway/wst.h"
63
#include "gateway/arm.h"
64
65
0
#define TAG FREERDP_TAG("core.transport")
66
67
0
#define BUFFER_SIZE 16384
68
69
struct rdp_transport
70
{
71
  TRANSPORT_LAYER layer;
72
  BIO* frontBio;
73
  rdpRdg* rdg;
74
  rdpTsg* tsg;
75
  rdpWst* wst;
76
  rdpTls* tls;
77
  rdpContext* context;
78
  rdpNla* nla;
79
  void* ReceiveExtra;
80
  wStream* ReceiveBuffer;
81
  TransportRecv ReceiveCallback;
82
  wStreamPool* ReceivePool;
83
  HANDLE connectedEvent;
84
  BOOL NlaMode;
85
  BOOL RdstlsMode;
86
  BOOL AadMode;
87
  BOOL blocking;
88
  BOOL GatewayEnabled;
89
  CRITICAL_SECTION ReadLock;
90
  CRITICAL_SECTION WriteLock;
91
  ULONG written;
92
  HANDLE rereadEvent;
93
  BOOL haveMoreBytesToRead;
94
  wLog* log;
95
  rdpTransportIo io;
96
  HANDLE ioEvent;
97
  BOOL useIoEvent;
98
  BOOL earlyUserAuth;
99
};
100
101
static void transport_ssl_cb(SSL* ssl, int where, int ret)
102
0
{
103
0
  if (where & SSL_CB_ALERT)
104
0
  {
105
0
    rdpTransport* transport = (rdpTransport*)SSL_get_app_data(ssl);
106
0
    WINPR_ASSERT(transport);
107
108
0
    switch (ret)
109
0
    {
110
0
      case (SSL3_AL_FATAL << 8) | SSL_AD_ACCESS_DENIED:
111
0
      {
112
0
        if (!freerdp_get_last_error(transport_get_context(transport)))
113
0
        {
114
0
          WLog_Print(transport->log, WLOG_ERROR, "ACCESS DENIED");
115
0
          freerdp_set_last_error_log(transport_get_context(transport),
116
0
                                     FREERDP_ERROR_AUTHENTICATION_FAILED);
117
0
        }
118
0
      }
119
0
      break;
120
121
0
      case (SSL3_AL_FATAL << 8) | SSL_AD_INTERNAL_ERROR:
122
0
      {
123
0
        if (transport->NlaMode)
124
0
        {
125
0
          if (!freerdp_get_last_error(transport_get_context(transport)))
126
0
          {
127
0
            UINT32 kret = 0;
128
0
            if (transport->nla)
129
0
              kret = nla_get_error(transport->nla);
130
0
            if (kret == 0)
131
0
              kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
132
0
            freerdp_set_last_error_log(transport_get_context(transport), kret);
133
0
          }
134
0
        }
135
136
0
        break;
137
138
0
        case (SSL3_AL_WARNING << 8) | SSL3_AD_CLOSE_NOTIFY:
139
0
          break;
140
141
0
        default:
142
0
          WLog_Print(transport->log, WLOG_WARN,
143
0
                     "Unhandled SSL error (where=%d, ret=%d [%s, %s])", where, ret,
144
0
                     SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
145
0
          break;
146
0
      }
147
0
    }
148
0
  }
149
0
}
150
151
wStream* transport_send_stream_init(rdpTransport* transport, size_t size)
152
0
{
153
0
  wStream* s;
154
0
  WINPR_ASSERT(transport);
155
156
0
  if (!(s = StreamPool_Take(transport->ReceivePool, size)))
157
0
    return NULL;
158
159
0
  if (!Stream_EnsureCapacity(s, size))
160
0
  {
161
0
    Stream_Release(s);
162
0
    return NULL;
163
0
  }
164
165
0
  Stream_SetPosition(s, 0);
166
0
  return s;
167
0
}
168
169
BOOL transport_attach(rdpTransport* transport, int sockfd)
170
0
{
171
0
  if (!transport)
172
0
    return FALSE;
173
0
  return IFCALLRESULT(FALSE, transport->io.TransportAttach, transport, sockfd);
174
0
}
175
176
static BOOL transport_default_attach(rdpTransport* transport, int sockfd)
177
0
{
178
0
  BIO* socketBio = NULL;
179
0
  BIO* bufferedBio;
180
0
  const rdpSettings* settings;
181
0
  rdpContext* context = transport_get_context(transport);
182
183
0
  if (sockfd < 0)
184
0
  {
185
0
    WLog_WARN(TAG, "Running peer without socket (sockfd=%d)", sockfd);
186
0
    return TRUE;
187
0
  }
188
189
0
  settings = context->settings;
190
0
  WINPR_ASSERT(settings);
191
192
0
  if (sockfd >= 0)
193
0
  {
194
0
    if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
195
0
      goto fail;
196
197
0
    socketBio = BIO_new(BIO_s_simple_socket());
198
199
0
    if (!socketBio)
200
0
      goto fail;
201
202
0
    BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
203
0
  }
204
205
0
  bufferedBio = BIO_new(BIO_s_buffered_socket());
206
0
  if (!bufferedBio)
207
0
    goto fail;
208
209
0
  if (socketBio)
210
0
    bufferedBio = BIO_push(bufferedBio, socketBio);
211
0
  WINPR_ASSERT(bufferedBio);
212
0
  transport->frontBio = bufferedBio;
213
0
  return TRUE;
214
0
fail:
215
216
0
  if (socketBio)
217
0
    BIO_free_all(socketBio);
218
0
  else
219
0
    closesocket(sockfd);
220
221
0
  return FALSE;
222
0
}
223
224
BOOL transport_connect_rdp(rdpTransport* transport)
225
0
{
226
0
  if (!transport)
227
0
    return FALSE;
228
229
0
  switch (utils_authenticate(transport_get_context(transport)->instance, AUTH_RDP, FALSE))
230
0
  {
231
0
    case AUTH_SKIP:
232
0
    case AUTH_SUCCESS:
233
0
    case AUTH_NO_CREDENTIALS:
234
0
      return TRUE;
235
0
    case AUTH_CANCELLED:
236
0
      freerdp_set_last_error_if_not(transport_get_context(transport),
237
0
                                    FREERDP_ERROR_CONNECT_CANCELLED);
238
0
      return FALSE;
239
0
    default:
240
0
      return FALSE;
241
0
  }
242
0
}
243
244
BOOL transport_connect_tls(rdpTransport* transport)
245
0
{
246
0
  const rdpSettings* settings;
247
0
  rdpContext* context = transport_get_context(transport);
248
249
0
  settings = context->settings;
250
0
  WINPR_ASSERT(settings);
251
252
  /* Only prompt for password if we use TLS (NLA also calls this function) */
253
0
  if (settings->SelectedProtocol == PROTOCOL_SSL)
254
0
  {
255
0
    switch (utils_authenticate(context->instance, AUTH_TLS, FALSE))
256
0
    {
257
0
      case AUTH_SKIP:
258
0
      case AUTH_SUCCESS:
259
0
      case AUTH_NO_CREDENTIALS:
260
0
        break;
261
0
      case AUTH_CANCELLED:
262
0
        freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
263
0
        return FALSE;
264
0
      default:
265
0
        return FALSE;
266
0
    }
267
0
  }
268
269
0
  return IFCALLRESULT(FALSE, transport->io.TLSConnect, transport);
270
0
}
271
272
static BOOL transport_default_connect_tls(rdpTransport* transport)
273
0
{
274
0
  int tlsStatus;
275
0
  rdpTls* tls = NULL;
276
0
  rdpContext* context;
277
0
  rdpSettings* settings;
278
279
0
  WINPR_ASSERT(transport);
280
281
0
  context = transport_get_context(transport);
282
0
  WINPR_ASSERT(context);
283
284
0
  settings = context->settings;
285
0
  WINPR_ASSERT(settings);
286
287
0
  if (!(tls = freerdp_tls_new(settings)))
288
0
    return FALSE;
289
290
0
  transport->tls = tls;
291
292
0
  if (transport->GatewayEnabled)
293
0
    transport->layer = TRANSPORT_LAYER_TSG_TLS;
294
0
  else
295
0
    transport->layer = TRANSPORT_LAYER_TLS;
296
297
0
  tls->hostname = settings->ServerHostname;
298
0
  tls->serverName = settings->UserSpecifiedServerName;
299
0
  tls->port = settings->ServerPort;
300
301
0
  if (tls->port == 0)
302
0
    tls->port = 3389;
303
304
0
  tls->isGatewayTransport = FALSE;
305
0
  tlsStatus = freerdp_tls_connect(tls, transport->frontBio);
306
307
0
  if (tlsStatus < 1)
308
0
  {
309
0
    if (tlsStatus < 0)
310
0
    {
311
0
      freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
312
0
    }
313
0
    else
314
0
    {
315
0
      freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
316
0
    }
317
318
0
    return FALSE;
319
0
  }
320
321
0
  transport->frontBio = tls->bio;
322
0
  BIO_callback_ctrl(tls->bio, BIO_CTRL_SET_CALLBACK, (bio_info_cb*)(void*)transport_ssl_cb);
323
0
  SSL_set_app_data(tls->ssl, transport);
324
325
0
  if (!transport->frontBio)
326
0
  {
327
0
    WLog_Print(transport->log, WLOG_ERROR, "unable to prepend a filtering TLS bio");
328
0
    return FALSE;
329
0
  }
330
331
0
  return TRUE;
332
0
}
333
334
BOOL transport_connect_nla(rdpTransport* transport, BOOL earlyUserAuth)
335
0
{
336
0
  rdpContext* context = NULL;
337
0
  rdpSettings* settings = NULL;
338
0
  rdpRdp* rdp = NULL;
339
0
  if (!transport)
340
0
    return FALSE;
341
342
0
  context = transport_get_context(transport);
343
0
  WINPR_ASSERT(context);
344
345
0
  settings = context->settings;
346
0
  WINPR_ASSERT(settings);
347
348
0
  rdp = context->rdp;
349
0
  WINPR_ASSERT(rdp);
350
351
0
  if (!transport_connect_tls(transport))
352
0
    return FALSE;
353
354
0
  if (!settings->Authentication)
355
0
    return TRUE;
356
357
0
  nla_free(rdp->nla);
358
0
  rdp->nla = nla_new(context, transport);
359
360
0
  if (!rdp->nla)
361
0
    return FALSE;
362
363
0
  nla_set_early_user_auth(rdp->nla, earlyUserAuth);
364
365
0
  transport_set_nla_mode(transport, TRUE);
366
367
0
  if (settings->AuthenticationServiceClass)
368
0
  {
369
0
    if (!nla_set_service_principal(rdp->nla, settings->AuthenticationServiceClass,
370
0
                                   freerdp_settings_get_server_name(settings)))
371
0
      return FALSE;
372
0
  }
373
374
0
  if (nla_client_begin(rdp->nla) < 0)
375
0
  {
376
0
    WLog_Print(transport->log, WLOG_ERROR, "NLA begin failed");
377
378
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
379
380
0
    transport_set_nla_mode(transport, FALSE);
381
0
    return FALSE;
382
0
  }
383
384
0
  return rdp_client_transition_to_state(rdp, CONNECTION_STATE_NLA);
385
0
}
386
387
BOOL transport_connect_rdstls(rdpTransport* transport)
388
0
{
389
0
  BOOL rc = FALSE;
390
0
  rdpRdstls* rdstls = NULL;
391
0
  rdpContext* context = NULL;
392
393
0
  WINPR_ASSERT(transport);
394
395
0
  context = transport_get_context(transport);
396
0
  WINPR_ASSERT(context);
397
398
0
  if (!transport_connect_tls(transport))
399
0
    goto fail;
400
401
0
  rdstls = rdstls_new(context, transport);
402
0
  if (!rdstls)
403
0
    goto fail;
404
405
0
  transport_set_rdstls_mode(transport, TRUE);
406
407
0
  if (rdstls_authenticate(rdstls) < 0)
408
0
  {
409
0
    WLog_Print(transport->log, WLOG_ERROR, "RDSTLS authentication failed");
410
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
411
0
    goto fail;
412
0
  }
413
414
0
  transport_set_rdstls_mode(transport, FALSE);
415
0
  rc = TRUE;
416
0
fail:
417
0
  rdstls_free(rdstls);
418
0
  return rc;
419
0
}
420
421
BOOL transport_connect_aad(rdpTransport* transport)
422
0
{
423
0
  rdpContext* context = NULL;
424
0
  rdpSettings* settings = NULL;
425
0
  rdpRdp* rdp = NULL;
426
0
  if (!transport)
427
0
    return FALSE;
428
429
0
  context = transport_get_context(transport);
430
0
  WINPR_ASSERT(context);
431
432
0
  settings = context->settings;
433
0
  WINPR_ASSERT(settings);
434
435
0
  rdp = context->rdp;
436
0
  WINPR_ASSERT(rdp);
437
438
0
  if (!transport_connect_tls(transport))
439
0
    return FALSE;
440
441
0
  if (!settings->Authentication)
442
0
    return TRUE;
443
444
0
  if (!rdp->aad)
445
0
    return FALSE;
446
447
0
  transport_set_aad_mode(transport, TRUE);
448
449
0
  if (aad_client_begin(rdp->aad) < 0)
450
0
  {
451
0
    WLog_Print(transport->log, WLOG_ERROR, "AAD begin failed");
452
453
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
454
455
0
    transport_set_aad_mode(transport, FALSE);
456
0
    return FALSE;
457
0
  }
458
459
0
  return rdp_client_transition_to_state(rdp, CONNECTION_STATE_AAD);
460
0
}
461
462
BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, DWORD timeout)
463
0
{
464
0
  int sockfd;
465
0
  BOOL status = FALSE;
466
0
  rdpSettings* settings;
467
0
  rdpContext* context = transport_get_context(transport);
468
0
  BOOL rpcFallback;
469
470
0
  WINPR_ASSERT(context);
471
0
  WINPR_ASSERT(hostname);
472
473
0
  settings = context->settings;
474
0
  WINPR_ASSERT(settings);
475
476
0
  rpcFallback = !settings->GatewayHttpTransport;
477
478
0
  if (transport->GatewayEnabled)
479
0
  {
480
0
    if (settings->GatewayUrl)
481
0
    {
482
0
      WINPR_ASSERT(!transport->wst);
483
0
      transport->wst = wst_new(context);
484
485
0
      if (!transport->wst)
486
0
        return FALSE;
487
488
0
      status = wst_connect(transport->wst, timeout);
489
490
0
      if (status)
491
0
      {
492
0
        transport->frontBio = wst_get_front_bio_and_take_ownership(transport->wst);
493
0
        WINPR_ASSERT(transport->frontBio);
494
0
        BIO_set_nonblock(transport->frontBio, 0);
495
0
        transport->layer = TRANSPORT_LAYER_TSG;
496
0
        status = TRUE;
497
0
      }
498
0
      else
499
0
      {
500
0
        wst_free(transport->wst);
501
0
        transport->wst = NULL;
502
0
      }
503
0
    }
504
0
    if (!status && settings->GatewayHttpTransport)
505
0
    {
506
0
      WINPR_ASSERT(!transport->rdg);
507
0
      transport->rdg = rdg_new(context);
508
509
0
      if (!transport->rdg)
510
0
        return FALSE;
511
512
0
      status = rdg_connect(transport->rdg, timeout, &rpcFallback);
513
514
0
      if (status)
515
0
      {
516
0
        transport->frontBio = rdg_get_front_bio_and_take_ownership(transport->rdg);
517
0
        WINPR_ASSERT(transport->frontBio);
518
0
        BIO_set_nonblock(transport->frontBio, 0);
519
0
        transport->layer = TRANSPORT_LAYER_TSG;
520
0
        status = TRUE;
521
0
      }
522
0
      else
523
0
      {
524
0
        rdg_free(transport->rdg);
525
0
        transport->rdg = NULL;
526
0
      }
527
0
    }
528
529
0
    if (!status && settings->GatewayRpcTransport && rpcFallback)
530
0
    {
531
0
      WINPR_ASSERT(!transport->tsg);
532
0
      transport->tsg = tsg_new(transport);
533
534
0
      if (!transport->tsg)
535
0
        return FALSE;
536
537
      /* Reset error condition from RDG */
538
0
      freerdp_set_last_error_log(context, FREERDP_ERROR_SUCCESS);
539
0
      status = tsg_connect(transport->tsg, hostname, port, timeout);
540
541
0
      if (status)
542
0
      {
543
0
        transport->frontBio = tsg_get_bio(transport->tsg);
544
0
        transport->layer = TRANSPORT_LAYER_TSG;
545
0
        status = TRUE;
546
0
      }
547
0
      else
548
0
      {
549
0
        tsg_free(transport->tsg);
550
0
        transport->tsg = NULL;
551
0
      }
552
0
    }
553
0
  }
554
0
  else
555
0
  {
556
0
    UINT16 peerPort;
557
0
    const char *proxyHostname, *proxyUsername, *proxyPassword;
558
0
    BOOL isProxyConnection =
559
0
        proxy_prepare(settings, &proxyHostname, &peerPort, &proxyUsername, &proxyPassword);
560
561
0
    if (isProxyConnection)
562
0
      sockfd = transport_tcp_connect(transport, proxyHostname, peerPort, timeout);
563
0
    else
564
0
      sockfd = transport_tcp_connect(transport, hostname, port, timeout);
565
566
0
    if (sockfd < 0)
567
0
      return FALSE;
568
569
0
    if (!transport_attach(transport, sockfd))
570
0
      return FALSE;
571
572
0
    if (isProxyConnection)
573
0
    {
574
0
      if (!proxy_connect(settings, transport->frontBio, proxyUsername, proxyPassword,
575
0
                         hostname, port))
576
0
        return FALSE;
577
0
    }
578
579
0
    status = TRUE;
580
0
  }
581
582
0
  return status;
583
0
}
584
585
BOOL transport_connect_childsession(rdpTransport* transport)
586
0
{
587
0
  WINPR_ASSERT(transport);
588
589
0
  transport->frontBio = createChildSessionBio();
590
0
  if (!transport->frontBio)
591
0
    return FALSE;
592
593
0
  transport->layer = TRANSPORT_LAYER_TSG;
594
0
  return TRUE;
595
0
}
596
597
BOOL transport_accept_rdp(rdpTransport* transport)
598
0
{
599
0
  if (!transport)
600
0
    return FALSE;
601
  /* RDP encryption */
602
0
  return TRUE;
603
0
}
604
605
BOOL transport_accept_tls(rdpTransport* transport)
606
0
{
607
0
  if (!transport)
608
0
    return FALSE;
609
0
  return IFCALLRESULT(FALSE, transport->io.TLSAccept, transport);
610
0
}
611
612
static BOOL transport_default_accept_tls(rdpTransport* transport)
613
0
{
614
0
  rdpContext* context = transport_get_context(transport);
615
0
  rdpSettings* settings;
616
617
0
  WINPR_ASSERT(context);
618
619
0
  settings = context->settings;
620
0
  WINPR_ASSERT(settings);
621
622
0
  if (!transport->tls)
623
0
    transport->tls = freerdp_tls_new(settings);
624
625
0
  transport->layer = TRANSPORT_LAYER_TLS;
626
627
0
  if (!freerdp_tls_accept(transport->tls, transport->frontBio, settings))
628
0
    return FALSE;
629
630
0
  transport->frontBio = transport->tls->bio;
631
0
  return TRUE;
632
0
}
633
634
BOOL transport_accept_nla(rdpTransport* transport)
635
0
{
636
0
  rdpContext* context = transport_get_context(transport);
637
0
  rdpSettings* settings;
638
639
0
  WINPR_ASSERT(context);
640
641
0
  settings = context->settings;
642
0
  WINPR_ASSERT(settings);
643
644
0
  if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
645
0
    return FALSE;
646
647
  /* Network Level Authentication */
648
649
0
  if (!settings->Authentication)
650
0
    return TRUE;
651
652
0
  if (!transport->nla)
653
0
  {
654
0
    transport->nla = nla_new(context, transport);
655
0
    transport_set_nla_mode(transport, TRUE);
656
0
  }
657
658
0
  if (nla_authenticate(transport->nla) < 0)
659
0
  {
660
0
    WLog_Print(transport->log, WLOG_ERROR, "client authentication failure");
661
0
    transport_set_nla_mode(transport, FALSE);
662
0
    nla_free(transport->nla);
663
0
    transport->nla = NULL;
664
0
    freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
665
0
                               TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
666
0
    freerdp_tls_send_alert(transport->tls);
667
0
    return FALSE;
668
0
  }
669
670
  /* don't free nla module yet, we need to copy the credentials from it first */
671
0
  transport_set_nla_mode(transport, FALSE);
672
0
  return TRUE;
673
0
}
674
675
BOOL transport_accept_rdstls(rdpTransport* transport)
676
0
{
677
0
  BOOL rc = FALSE;
678
0
  rdpRdstls* rdstls = NULL;
679
0
  rdpContext* context = NULL;
680
681
0
  WINPR_ASSERT(transport);
682
683
0
  context = transport_get_context(transport);
684
0
  WINPR_ASSERT(context);
685
686
0
  if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
687
0
    goto fail;
688
689
0
  rdstls = rdstls_new(context, transport);
690
0
  if (!rdstls)
691
0
    goto fail;
692
693
0
  transport_set_rdstls_mode(transport, TRUE);
694
695
0
  if (rdstls_authenticate(rdstls) < 0)
696
0
  {
697
0
    WLog_Print(transport->log, WLOG_ERROR, "client authentication failure");
698
0
    freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
699
0
                               TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
700
0
    freerdp_tls_send_alert(transport->tls);
701
0
    goto fail;
702
0
  }
703
704
0
  transport_set_rdstls_mode(transport, FALSE);
705
0
  rc = TRUE;
706
0
fail:
707
0
  rdstls_free(rdstls);
708
0
  return rc;
709
0
}
710
711
#define WLog_ERR_BIO(transport, biofunc, bio) \
712
0
  transport_bio_error_log(transport, biofunc, bio, __FILE__, __func__, __LINE__)
713
714
static void transport_bio_error_log(rdpTransport* transport, LPCSTR biofunc, BIO* bio, LPCSTR file,
715
                                    LPCSTR func, DWORD line)
716
0
{
717
0
  unsigned long sslerr;
718
0
  int saveerrno;
719
0
  DWORD level;
720
721
0
  WINPR_ASSERT(transport);
722
723
0
  saveerrno = errno;
724
0
  level = WLOG_ERROR;
725
726
0
  if (level < WLog_GetLogLevel(transport->log))
727
0
    return;
728
729
0
  if (ERR_peek_error() == 0)
730
0
  {
731
0
    const char* fmt = "%s returned a system error %d: %s";
732
0
    if (saveerrno == 0)
733
0
      fmt = "%s retries exceeded";
734
0
    WLog_PrintMessage(transport->log, WLOG_MESSAGE_TEXT, level, line, file, func, fmt, biofunc,
735
0
                      saveerrno, strerror(saveerrno));
736
0
    return;
737
0
  }
738
739
0
  while ((sslerr = ERR_get_error()))
740
0
  {
741
0
    char buf[120] = { 0 };
742
0
    const char* fmt = "%s returned an error: %s";
743
744
0
    ERR_error_string_n(sslerr, buf, 120);
745
0
    WLog_PrintMessage(transport->log, WLOG_MESSAGE_TEXT, level, line, file, func, fmt, biofunc,
746
0
                      buf);
747
0
  }
748
0
}
749
750
static SSIZE_T transport_read_layer(rdpTransport* transport, BYTE* data, size_t bytes)
751
0
{
752
0
  SSIZE_T read = 0;
753
0
  rdpRdp* rdp;
754
0
  rdpContext* context;
755
756
0
  WINPR_ASSERT(transport);
757
758
0
  context = transport_get_context(transport);
759
0
  WINPR_ASSERT(context);
760
761
0
  rdp = context->rdp;
762
0
  WINPR_ASSERT(rdp);
763
764
0
  if (!transport->frontBio || (bytes > SSIZE_MAX))
765
0
  {
766
0
    transport->layer = TRANSPORT_LAYER_CLOSED;
767
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
768
0
    return -1;
769
0
  }
770
771
0
  while (read < (SSIZE_T)bytes)
772
0
  {
773
0
    const SSIZE_T tr = (SSIZE_T)bytes - read;
774
0
    int r = (int)((tr > INT_MAX) ? INT_MAX : tr);
775
0
    ERR_clear_error();
776
0
    int status = BIO_read(transport->frontBio, data + read, r);
777
778
0
    if (freerdp_shall_disconnect_context(context))
779
0
      return -1;
780
781
0
    if (status <= 0)
782
0
    {
783
0
      if (!transport->frontBio || !BIO_should_retry(transport->frontBio))
784
0
      {
785
        /* something unexpected happened, let's close */
786
0
        if (!transport->frontBio)
787
0
        {
788
0
          WLog_Print(transport->log, WLOG_ERROR, "BIO_read: transport->frontBio null");
789
0
          return -1;
790
0
        }
791
792
0
        WLog_ERR_BIO(transport, "BIO_read", transport->frontBio);
793
0
        transport->layer = TRANSPORT_LAYER_CLOSED;
794
0
        freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
795
0
        return -1;
796
0
      }
797
798
      /* non blocking will survive a partial read */
799
0
      if (!transport->blocking)
800
0
        return read;
801
802
      /* blocking means that we can't continue until we have read the number of requested
803
       * bytes */
804
0
      if (BIO_wait_read(transport->frontBio, 100) < 0)
805
0
      {
806
0
        WLog_ERR_BIO(transport, "BIO_wait_read", transport->frontBio);
807
0
        return -1;
808
0
      }
809
810
0
      continue;
811
0
    }
812
813
#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
814
    VALGRIND_MAKE_MEM_DEFINED(data + read, bytes - read);
815
#endif
816
0
    read += status;
817
0
    rdp->inBytes += status;
818
0
  }
819
820
0
  return read;
821
0
}
822
823
/**
824
 * @brief Tries to read toRead bytes from the specified transport
825
 *
826
 * Try to read toRead bytes from the transport to the stream.
827
 * In case it was not possible to read toRead bytes 0 is returned. The stream is always advanced by
828
 * the number of bytes read.
829
 *
830
 * The function assumes that the stream has enough capacity to hold the data.
831
 *
832
 * @param[in] transport rdpTransport
833
 * @param[in] s wStream
834
 * @param[in] toRead number of bytes to read
835
 * @return < 0 on error; 0 if not enough data is available (non blocking mode); 1 toRead bytes read
836
 */
837
static SSIZE_T transport_read_layer_bytes(rdpTransport* transport, wStream* s, size_t toRead)
838
0
{
839
0
  SSIZE_T status;
840
0
  if (!transport)
841
0
    return -1;
842
843
0
  if (toRead > SSIZE_MAX)
844
0
    return 0;
845
846
0
  status = IFCALLRESULT(-1, transport->io.ReadBytes, transport, Stream_Pointer(s), toRead);
847
848
0
  if (status <= 0)
849
0
    return status;
850
851
0
  Stream_Seek(s, (size_t)status);
852
0
  return status == (SSIZE_T)toRead ? 1 : 0;
853
0
}
854
855
/**
856
 * @brief Try to read a complete PDU (NLA, fast-path or tpkt) from the underlying transport.
857
 *
858
 * If possible a complete PDU is read, in case of non blocking transport this might not succeed.
859
 * Except in case of an error the passed stream will point to the last byte read (correct
860
 * position). When the pdu read is completed the stream is sealed and the pointer set to 0
861
 *
862
 * @param[in] transport rdpTransport
863
 * @param[in] s wStream
864
 * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 number of
865
 * bytes of the *complete* pdu read
866
 */
867
int transport_read_pdu(rdpTransport* transport, wStream* s)
868
0
{
869
0
  if (!transport)
870
0
    return -1;
871
0
  return IFCALLRESULT(-1, transport->io.ReadPdu, transport, s);
872
0
}
873
874
static SSIZE_T parse_nla_mode_pdu(rdpTransport* transport, wStream* stream)
875
0
{
876
0
  SSIZE_T pduLength = 0;
877
0
  wStream sbuffer = { 0 };
878
0
  wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
879
  /*
880
   * In case NlaMode is set TSRequest package(s) are expected
881
   * 0x30 = DER encoded data with these bits set:
882
   * bit 6 P/C constructed
883
   * bit 5 tag number - sequence
884
   */
885
0
  UINT8 typeEncoding;
886
0
  if (Stream_GetRemainingLength(s) < 1)
887
0
    return 0;
888
0
  Stream_Read_UINT8(s, typeEncoding);
889
0
  if (typeEncoding == 0x30)
890
0
  {
891
    /* TSRequest (NLA) */
892
0
    UINT8 lengthEncoding;
893
0
    if (Stream_GetRemainingLength(s) < 1)
894
0
      return 0;
895
0
    Stream_Read_UINT8(s, lengthEncoding);
896
0
    if (lengthEncoding & 0x80)
897
0
    {
898
0
      if ((lengthEncoding & ~(0x80)) == 1)
899
0
      {
900
0
        UINT8 length;
901
0
        if (Stream_GetRemainingLength(s) < 1)
902
0
          return 0;
903
0
        Stream_Read_UINT8(s, length);
904
0
        pduLength = length;
905
0
        pduLength += 3;
906
0
      }
907
0
      else if ((lengthEncoding & ~(0x80)) == 2)
908
0
      {
909
        /* check for header bytes already was readed in previous calls */
910
0
        UINT16 length;
911
0
        if (Stream_GetRemainingLength(s) < 2)
912
0
          return 0;
913
0
        Stream_Read_UINT16_BE(s, length);
914
0
        pduLength = length;
915
0
        pduLength += 4;
916
0
      }
917
0
      else
918
0
      {
919
0
        WLog_Print(transport->log, WLOG_ERROR, "Error reading TSRequest!");
920
0
        return -1;
921
0
      }
922
0
    }
923
0
    else
924
0
    {
925
0
      pduLength = lengthEncoding;
926
0
      pduLength += 2;
927
0
    }
928
0
  }
929
930
0
  return pduLength;
931
0
}
932
933
static SSIZE_T parse_default_mode_pdu(rdpTransport* transport, wStream* stream)
934
0
{
935
0
  SSIZE_T pduLength = 0;
936
0
  wStream sbuffer = { 0 };
937
0
  wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
938
939
0
  UINT8 version;
940
0
  if (Stream_GetRemainingLength(s) < 1)
941
0
    return 0;
942
0
  Stream_Read_UINT8(s, version);
943
0
  if (version == 0x03)
944
0
  {
945
    /* TPKT header */
946
0
    UINT16 length;
947
0
    if (Stream_GetRemainingLength(s) < 3)
948
0
      return 0;
949
0
    Stream_Seek(s, 1);
950
0
    Stream_Read_UINT16_BE(s, length);
951
0
    pduLength = length;
952
953
    /* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */
954
0
    if ((pduLength < 7) || (pduLength > 0xFFFF))
955
0
    {
956
0
      WLog_Print(transport->log, WLOG_ERROR, "tpkt - invalid pduLength: %" PRIdz, pduLength);
957
0
      return -1;
958
0
    }
959
0
  }
960
0
  else
961
0
  {
962
    /* Fast-Path Header */
963
0
    UINT8 length1;
964
0
    if (Stream_GetRemainingLength(s) < 1)
965
0
      return 0;
966
0
    Stream_Read_UINT8(s, length1);
967
0
    if (length1 & 0x80)
968
0
    {
969
0
      UINT8 length2;
970
0
      if (Stream_GetRemainingLength(s) < 1)
971
0
        return 0;
972
0
      Stream_Read_UINT8(s, length2);
973
0
      pduLength = ((length1 & 0x7F) << 8) | length2;
974
0
    }
975
0
    else
976
0
      pduLength = length1;
977
978
    /*
979
     * fast-path has 7 bits for length so the maximum size, including headers is 0x8000
980
     * The theoretical minimum fast-path PDU consists only of two header bytes plus one
981
     * byte for data (e.g. fast-path input synchronize pdu)
982
     */
983
0
    if (pduLength < 3 || pduLength > 0x8000)
984
0
    {
985
0
      WLog_Print(transport->log, WLOG_ERROR, "fast path - invalid pduLength: %" PRIdz,
986
0
                 pduLength);
987
0
      return -1;
988
0
    }
989
0
  }
990
991
0
  return pduLength;
992
0
}
993
994
SSIZE_T transport_parse_pdu(rdpTransport* transport, wStream* s, BOOL* incomplete)
995
0
{
996
0
  size_t pduLength = 0;
997
998
0
  if (!transport)
999
0
    return -1;
1000
1001
0
  if (!s)
1002
0
    return -1;
1003
1004
0
  if (incomplete)
1005
0
    *incomplete = TRUE;
1006
1007
0
  Stream_SealLength(s);
1008
0
  if (transport->NlaMode)
1009
0
    pduLength = parse_nla_mode_pdu(transport, s);
1010
0
  else if (transport->RdstlsMode)
1011
0
    pduLength = rdstls_parse_pdu(transport->log, s);
1012
0
  else
1013
0
    pduLength = parse_default_mode_pdu(transport, s);
1014
1015
0
  if (pduLength == 0)
1016
0
    return pduLength;
1017
1018
0
  const size_t len = Stream_Length(s);
1019
0
  if (len > pduLength)
1020
0
    return -1;
1021
1022
0
  if (incomplete)
1023
0
    *incomplete = len < pduLength;
1024
1025
0
  return pduLength;
1026
0
}
1027
1028
static int transport_default_read_pdu(rdpTransport* transport, wStream* s)
1029
0
{
1030
0
  BOOL incomplete;
1031
0
  SSIZE_T status;
1032
0
  size_t pduLength;
1033
0
  size_t position;
1034
1035
0
  WINPR_ASSERT(transport);
1036
0
  WINPR_ASSERT(s);
1037
1038
  /* RDS AAD Auth PDUs have no length indicator. We need to determine the end of the PDU by
1039
   * reading in one byte at a time until we encounter the terminating null byte */
1040
0
  if (transport->AadMode)
1041
0
  {
1042
0
    BYTE c = '\0';
1043
0
    do
1044
0
    {
1045
0
      const int rc = transport_read_layer(transport, &c, 1);
1046
0
      if (rc != 1)
1047
0
        return rc;
1048
0
      if (!Stream_EnsureRemainingCapacity(s, 1))
1049
0
        return -1;
1050
0
      Stream_Write_UINT8(s, c);
1051
0
    } while (c != '\0');
1052
0
  }
1053
0
  else if (transport->earlyUserAuth)
1054
0
  {
1055
0
    if (!Stream_EnsureCapacity(s, 4))
1056
0
      return -1;
1057
0
    const int rc = transport_read_layer_bytes(transport, s, 4);
1058
0
    if (rc != 1)
1059
0
      return rc;
1060
0
  }
1061
0
  else
1062
0
  {
1063
    /* Read in pdu length */
1064
0
    status = transport_parse_pdu(transport, s, &incomplete);
1065
0
    while ((status == 0) && incomplete)
1066
0
    {
1067
0
      int rc;
1068
0
      if (!Stream_EnsureRemainingCapacity(s, 1))
1069
0
        return -1;
1070
0
      rc = transport_read_layer_bytes(transport, s, 1);
1071
0
      if (rc != 1)
1072
0
        return rc;
1073
0
      status = transport_parse_pdu(transport, s, &incomplete);
1074
0
    }
1075
1076
0
    if (status < 0)
1077
0
      return -1;
1078
1079
0
    pduLength = (size_t)status;
1080
1081
    /* Read in rest of the PDU */
1082
0
    if (!Stream_EnsureCapacity(s, pduLength))
1083
0
      return -1;
1084
1085
0
    position = Stream_GetPosition(s);
1086
0
    if (position > pduLength)
1087
0
      return -1;
1088
1089
0
    status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s));
1090
1091
0
    if (status != 1)
1092
0
      return status;
1093
1094
0
    if (Stream_GetPosition(s) >= pduLength)
1095
0
      WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength,
1096
0
                  WLOG_PACKET_INBOUND);
1097
0
  }
1098
1099
0
  Stream_SealLength(s);
1100
0
  Stream_SetPosition(s, 0);
1101
0
  return Stream_Length(s);
1102
0
}
1103
1104
int transport_write(rdpTransport* transport, wStream* s)
1105
0
{
1106
0
  if (!transport)
1107
0
    return -1;
1108
1109
0
  return IFCALLRESULT(-1, transport->io.WritePdu, transport, s);
1110
0
}
1111
1112
static int transport_default_write(rdpTransport* transport, wStream* s)
1113
0
{
1114
0
  size_t length;
1115
0
  int status = -1;
1116
0
  int writtenlength = 0;
1117
0
  rdpRdp* rdp;
1118
0
  rdpContext* context = transport_get_context(transport);
1119
1120
0
  WINPR_ASSERT(transport);
1121
0
  WINPR_ASSERT(context);
1122
1123
0
  if (!s)
1124
0
    return -1;
1125
1126
0
  Stream_AddRef(s);
1127
1128
0
  rdp = context->rdp;
1129
0
  if (!rdp)
1130
0
    goto fail;
1131
1132
0
  EnterCriticalSection(&(transport->WriteLock));
1133
0
  if (!transport->frontBio)
1134
0
    goto out_cleanup;
1135
1136
0
  length = Stream_GetPosition(s);
1137
0
  writtenlength = length;
1138
0
  Stream_SetPosition(s, 0);
1139
1140
0
  if (length > 0)
1141
0
  {
1142
0
    rdp->outBytes += length;
1143
0
    WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
1144
0
  }
1145
1146
0
  while (length > 0)
1147
0
  {
1148
0
    ERR_clear_error();
1149
0
    status = BIO_write(transport->frontBio, Stream_ConstPointer(s), length);
1150
1151
0
    if (status <= 0)
1152
0
    {
1153
      /* the buffered BIO that is at the end of the chain always says OK for writing,
1154
       * so a retry means that for any reason we need to read. The most probable
1155
       * is a SSL or TSG BIO in the chain.
1156
       */
1157
0
      if (!BIO_should_retry(transport->frontBio))
1158
0
      {
1159
0
        WLog_ERR_BIO(transport, "BIO_should_retry", transport->frontBio);
1160
0
        goto out_cleanup;
1161
0
      }
1162
1163
      /* non-blocking can live with blocked IOs */
1164
0
      if (!transport->blocking)
1165
0
      {
1166
0
        WLog_ERR_BIO(transport, "BIO_write", transport->frontBio);
1167
0
        goto out_cleanup;
1168
0
      }
1169
1170
0
      if (BIO_wait_write(transport->frontBio, 100) < 0)
1171
0
      {
1172
0
        WLog_ERR_BIO(transport, "BIO_wait_write", transport->frontBio);
1173
0
        status = -1;
1174
0
        goto out_cleanup;
1175
0
      }
1176
1177
0
      continue;
1178
0
    }
1179
1180
0
    WINPR_ASSERT(context->settings);
1181
0
    if (transport->blocking || context->settings->WaitForOutputBufferFlush)
1182
0
    {
1183
0
      while (BIO_write_blocked(transport->frontBio))
1184
0
      {
1185
0
        if (BIO_wait_write(transport->frontBio, 100) < 0)
1186
0
        {
1187
0
          WLog_Print(transport->log, WLOG_ERROR, "error when selecting for write");
1188
0
          status = -1;
1189
0
          goto out_cleanup;
1190
0
        }
1191
1192
0
        if (BIO_flush(transport->frontBio) < 1)
1193
0
        {
1194
0
          WLog_Print(transport->log, WLOG_ERROR, "error when flushing outputBuffer");
1195
0
          status = -1;
1196
0
          goto out_cleanup;
1197
0
        }
1198
0
      }
1199
0
    }
1200
1201
0
    length -= status;
1202
0
    Stream_Seek(s, status);
1203
0
  }
1204
1205
0
  transport->written += writtenlength;
1206
0
out_cleanup:
1207
1208
0
  if (status < 0)
1209
0
  {
1210
    /* A write error indicates that the peer has dropped the connection */
1211
0
    transport->layer = TRANSPORT_LAYER_CLOSED;
1212
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1213
0
  }
1214
1215
0
  LeaveCriticalSection(&(transport->WriteLock));
1216
0
fail:
1217
0
  Stream_Release(s);
1218
0
  return status;
1219
0
}
1220
1221
DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count)
1222
0
{
1223
0
  DWORD nCount = 0; /* always the reread Event */
1224
1225
0
  WINPR_ASSERT(transport);
1226
0
  WINPR_ASSERT(events);
1227
0
  WINPR_ASSERT(count > 0);
1228
1229
0
  if (events)
1230
0
  {
1231
0
    if (count < 1)
1232
0
    {
1233
0
      WLog_Print(transport->log, WLOG_ERROR, "provided handles array is too small");
1234
0
      return 0;
1235
0
    }
1236
1237
0
    events[nCount++] = transport->rereadEvent;
1238
1239
0
    if (transport->useIoEvent)
1240
0
    {
1241
0
      if (count < 2)
1242
0
        return 0;
1243
0
      events[nCount++] = transport->ioEvent;
1244
0
    }
1245
0
  }
1246
1247
0
  if (!transport->GatewayEnabled)
1248
0
  {
1249
0
    if (events)
1250
0
    {
1251
0
      if (nCount >= count)
1252
0
      {
1253
0
        WLog_Print(transport->log, WLOG_ERROR,
1254
0
                   "provided handles array is too small (count=%" PRIu32 " nCount=%" PRIu32
1255
0
                   ")",
1256
0
                   count, nCount);
1257
0
        return 0;
1258
0
      }
1259
1260
0
      if (transport->frontBio)
1261
0
      {
1262
0
        if (BIO_get_event(transport->frontBio, &events[nCount]) != 1)
1263
0
        {
1264
0
          WLog_Print(transport->log, WLOG_ERROR, "error getting the frontBio handle");
1265
0
          return 0;
1266
0
        }
1267
0
        nCount++;
1268
0
      }
1269
0
    }
1270
0
  }
1271
0
  else
1272
0
  {
1273
0
    if (transport->rdg)
1274
0
    {
1275
0
      const DWORD tmp =
1276
0
          rdg_get_event_handles(transport->rdg, &events[nCount], count - nCount);
1277
1278
0
      if (tmp == 0)
1279
0
        return 0;
1280
1281
0
      nCount += tmp;
1282
0
    }
1283
0
    else if (transport->tsg)
1284
0
    {
1285
0
      const DWORD tmp =
1286
0
          tsg_get_event_handles(transport->tsg, &events[nCount], count - nCount);
1287
1288
0
      if (tmp == 0)
1289
0
        return 0;
1290
1291
0
      nCount += tmp;
1292
0
    }
1293
0
    else if (transport->wst)
1294
0
    {
1295
0
      const DWORD tmp =
1296
0
          wst_get_event_handles(transport->wst, &events[nCount], count - nCount);
1297
1298
0
      if (tmp == 0)
1299
0
        return 0;
1300
1301
0
      nCount += tmp;
1302
0
    }
1303
0
  }
1304
1305
0
  return nCount;
1306
0
}
1307
1308
#if defined(WITH_FREERDP_DEPRECATED)
1309
void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
1310
{
1311
  DWORD index;
1312
  DWORD nCount;
1313
  HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
1314
1315
  WINPR_ASSERT(transport);
1316
  WINPR_ASSERT(rfds);
1317
  WINPR_ASSERT(rcount);
1318
1319
  nCount = transport_get_event_handles(transport, events, ARRAYSIZE(events));
1320
  *rcount = nCount + 1;
1321
1322
  for (index = 0; index < nCount; index++)
1323
  {
1324
    rfds[index] = GetEventWaitObject(events[index]);
1325
  }
1326
1327
  rfds[nCount] = GetEventWaitObject(transport->rereadEvent);
1328
}
1329
#endif
1330
1331
BOOL transport_is_write_blocked(rdpTransport* transport)
1332
0
{
1333
0
  WINPR_ASSERT(transport);
1334
0
  WINPR_ASSERT(transport->frontBio);
1335
0
  return BIO_write_blocked(transport->frontBio);
1336
0
}
1337
1338
int transport_drain_output_buffer(rdpTransport* transport)
1339
0
{
1340
0
  BOOL status = FALSE;
1341
1342
0
  WINPR_ASSERT(transport);
1343
0
  WINPR_ASSERT(transport->frontBio);
1344
0
  if (BIO_write_blocked(transport->frontBio))
1345
0
  {
1346
0
    if (BIO_flush(transport->frontBio) < 1)
1347
0
      return -1;
1348
1349
0
    status |= BIO_write_blocked(transport->frontBio);
1350
0
  }
1351
1352
0
  return status;
1353
0
}
1354
1355
int transport_check_fds(rdpTransport* transport)
1356
0
{
1357
0
  int status;
1358
0
  state_run_t recv_status;
1359
0
  wStream* received;
1360
0
  rdpContext* context = transport_get_context(transport);
1361
1362
0
  WINPR_ASSERT(context);
1363
1364
0
  if (transport->layer == TRANSPORT_LAYER_CLOSED)
1365
0
  {
1366
0
    WLog_Print(transport->log, WLOG_DEBUG, "transport_check_fds: transport layer closed");
1367
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1368
0
    return -1;
1369
0
  }
1370
1371
  /**
1372
   * Note: transport_read_pdu tries to read one PDU from
1373
   * the transport layer.
1374
   * The ReceiveBuffer might have a position > 0 in case of a non blocking
1375
   * transport. If transport_read_pdu returns 0 the pdu couldn't be read at
1376
   * this point.
1377
   * Note that transport->ReceiveBuffer is replaced after each iteration
1378
   * of this loop with a fresh stream instance from a pool.
1379
   */
1380
0
  if ((status = transport_read_pdu(transport, transport->ReceiveBuffer)) <= 0)
1381
0
  {
1382
0
    if (status < 0)
1383
0
      WLog_Print(transport->log, WLOG_DEBUG, "transport_check_fds: transport_read_pdu() - %i",
1384
0
                 status);
1385
0
    if (transport->haveMoreBytesToRead)
1386
0
    {
1387
0
      transport->haveMoreBytesToRead = FALSE;
1388
0
      ResetEvent(transport->rereadEvent);
1389
0
    }
1390
0
    return status;
1391
0
  }
1392
1393
0
  received = transport->ReceiveBuffer;
1394
1395
0
  if (!(transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0)))
1396
0
    return -1;
1397
1398
  /**
1399
   * status:
1400
   *  -1: error
1401
   *   0: success
1402
   *   1: redirection
1403
   */
1404
0
  WINPR_ASSERT(transport->ReceiveCallback);
1405
0
  recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
1406
0
  Stream_Release(received);
1407
1408
0
  if (state_run_failed(recv_status))
1409
0
  {
1410
0
    char buffer[64] = { 0 };
1411
0
    WLog_Print(transport->log, WLOG_ERROR,
1412
0
               "transport_check_fds: transport->ReceiveCallback() - %s",
1413
0
               state_run_result_string(recv_status, buffer, ARRAYSIZE(buffer)));
1414
0
    return -1;
1415
0
  }
1416
1417
  /* Run this again to be sure we consumed all input data.
1418
   * This will be repeated until a (not fully) received packet is in buffer
1419
   */
1420
0
  if (!transport->haveMoreBytesToRead)
1421
0
  {
1422
0
    transport->haveMoreBytesToRead = TRUE;
1423
0
    SetEvent(transport->rereadEvent);
1424
0
  }
1425
0
  return recv_status;
1426
0
}
1427
1428
BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1429
0
{
1430
0
  WINPR_ASSERT(transport);
1431
1432
0
  transport->blocking = blocking;
1433
1434
0
  if (transport->frontBio)
1435
0
  {
1436
0
    if (!BIO_set_nonblock(transport->frontBio, blocking ? FALSE : TRUE))
1437
0
      return FALSE;
1438
0
  }
1439
1440
0
  return TRUE;
1441
0
}
1442
1443
void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled)
1444
0
{
1445
0
  WINPR_ASSERT(transport);
1446
0
  transport->GatewayEnabled = GatewayEnabled;
1447
0
}
1448
1449
void transport_set_nla_mode(rdpTransport* transport, BOOL NlaMode)
1450
0
{
1451
0
  WINPR_ASSERT(transport);
1452
0
  transport->NlaMode = NlaMode;
1453
0
}
1454
1455
void transport_set_rdstls_mode(rdpTransport* transport, BOOL RdstlsMode)
1456
0
{
1457
0
  WINPR_ASSERT(transport);
1458
0
  transport->RdstlsMode = RdstlsMode;
1459
0
}
1460
1461
void transport_set_aad_mode(rdpTransport* transport, BOOL AadMode)
1462
0
{
1463
0
  WINPR_ASSERT(transport);
1464
0
  transport->AadMode = AadMode;
1465
0
}
1466
1467
BOOL transport_disconnect(rdpTransport* transport)
1468
0
{
1469
0
  if (!transport)
1470
0
    return FALSE;
1471
0
  return IFCALLRESULT(FALSE, transport->io.TransportDisconnect, transport);
1472
0
}
1473
1474
static BOOL transport_default_disconnect(rdpTransport* transport)
1475
0
{
1476
0
  BOOL status = TRUE;
1477
1478
0
  if (!transport)
1479
0
    return FALSE;
1480
1481
0
  if (transport->tls)
1482
0
  {
1483
0
    freerdp_tls_free(transport->tls);
1484
0
    transport->tls = NULL;
1485
0
  }
1486
0
  else
1487
0
  {
1488
0
    if (transport->frontBio)
1489
0
      BIO_free_all(transport->frontBio);
1490
0
  }
1491
1492
0
  if (transport->tsg)
1493
0
  {
1494
0
    tsg_free(transport->tsg);
1495
0
    transport->tsg = NULL;
1496
0
  }
1497
1498
0
  if (transport->rdg)
1499
0
  {
1500
0
    rdg_free(transport->rdg);
1501
0
    transport->rdg = NULL;
1502
0
  }
1503
1504
0
  if (transport->wst)
1505
0
  {
1506
0
    wst_free(transport->wst);
1507
0
    transport->wst = NULL;
1508
0
  }
1509
1510
0
  transport->frontBio = NULL;
1511
0
  transport->layer = TRANSPORT_LAYER_TCP;
1512
0
  transport->earlyUserAuth = FALSE;
1513
0
  return status;
1514
0
}
1515
1516
rdpTransport* transport_new(rdpContext* context)
1517
0
{
1518
0
  rdpTransport* transport = (rdpTransport*)calloc(1, sizeof(rdpTransport));
1519
1520
0
  WINPR_ASSERT(context);
1521
0
  if (!transport)
1522
0
    return NULL;
1523
1524
0
  transport->log = WLog_Get(TAG);
1525
1526
0
  if (!transport->log)
1527
0
    goto fail;
1528
1529
  // transport->io.DataHandler = transport_data_handler;
1530
0
  transport->io.TCPConnect = freerdp_tcp_default_connect;
1531
0
  transport->io.TLSConnect = transport_default_connect_tls;
1532
0
  transport->io.TLSAccept = transport_default_accept_tls;
1533
0
  transport->io.TransportAttach = transport_default_attach;
1534
0
  transport->io.TransportDisconnect = transport_default_disconnect;
1535
0
  transport->io.ReadPdu = transport_default_read_pdu;
1536
0
  transport->io.WritePdu = transport_default_write;
1537
0
  transport->io.ReadBytes = transport_read_layer;
1538
1539
0
  transport->context = context;
1540
0
  transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
1541
1542
0
  if (!transport->ReceivePool)
1543
0
    goto fail;
1544
1545
  /* receive buffer for non-blocking read. */
1546
0
  transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1547
1548
0
  if (!transport->ReceiveBuffer)
1549
0
    goto fail;
1550
1551
0
  transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1552
1553
0
  if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
1554
0
    goto fail;
1555
1556
0
  transport->rereadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1557
1558
0
  if (!transport->rereadEvent || transport->rereadEvent == INVALID_HANDLE_VALUE)
1559
0
    goto fail;
1560
1561
0
  transport->ioEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1562
1563
0
  if (!transport->ioEvent || transport->ioEvent == INVALID_HANDLE_VALUE)
1564
0
    goto fail;
1565
1566
0
  transport->haveMoreBytesToRead = FALSE;
1567
0
  transport->blocking = TRUE;
1568
0
  transport->GatewayEnabled = FALSE;
1569
0
  transport->layer = TRANSPORT_LAYER_TCP;
1570
1571
0
  if (!InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000))
1572
0
    goto fail;
1573
1574
0
  if (!InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000))
1575
0
    goto fail;
1576
1577
0
  return transport;
1578
0
fail:
1579
0
  transport_free(transport);
1580
0
  return NULL;
1581
0
}
1582
1583
void transport_free(rdpTransport* transport)
1584
0
{
1585
0
  if (!transport)
1586
0
    return;
1587
1588
0
  transport_disconnect(transport);
1589
1590
0
  if (transport->ReceiveBuffer)
1591
0
    Stream_Release(transport->ReceiveBuffer);
1592
1593
0
  nla_free(transport->nla);
1594
0
  StreamPool_Free(transport->ReceivePool);
1595
0
  CloseHandle(transport->connectedEvent);
1596
0
  CloseHandle(transport->rereadEvent);
1597
0
  CloseHandle(transport->ioEvent);
1598
0
  DeleteCriticalSection(&(transport->ReadLock));
1599
0
  DeleteCriticalSection(&(transport->WriteLock));
1600
0
  free(transport);
1601
0
}
1602
1603
BOOL transport_set_io_callbacks(rdpTransport* transport, const rdpTransportIo* io_callbacks)
1604
0
{
1605
0
  if (!transport || !io_callbacks)
1606
0
    return FALSE;
1607
1608
0
  transport->io = *io_callbacks;
1609
0
  return TRUE;
1610
0
}
1611
1612
const rdpTransportIo* transport_get_io_callbacks(rdpTransport* transport)
1613
0
{
1614
0
  if (!transport)
1615
0
    return NULL;
1616
0
  return &transport->io;
1617
0
}
1618
1619
rdpContext* transport_get_context(rdpTransport* transport)
1620
0
{
1621
0
  WINPR_ASSERT(transport);
1622
0
  return transport->context;
1623
0
}
1624
1625
rdpTransport* freerdp_get_transport(rdpContext* context)
1626
0
{
1627
0
  WINPR_ASSERT(context);
1628
0
  WINPR_ASSERT(context->rdp);
1629
0
  return context->rdp->transport;
1630
0
}
1631
1632
BOOL transport_set_nla(rdpTransport* transport, rdpNla* nla)
1633
0
{
1634
0
  WINPR_ASSERT(transport);
1635
0
  nla_free(transport->nla);
1636
0
  transport->nla = nla;
1637
0
  return TRUE;
1638
0
}
1639
1640
rdpNla* transport_get_nla(rdpTransport* transport)
1641
0
{
1642
0
  WINPR_ASSERT(transport);
1643
0
  return transport->nla;
1644
0
}
1645
1646
BOOL transport_set_tls(rdpTransport* transport, rdpTls* tls)
1647
0
{
1648
0
  WINPR_ASSERT(transport);
1649
0
  freerdp_tls_free(transport->tls);
1650
0
  transport->tls = tls;
1651
0
  return TRUE;
1652
0
}
1653
1654
rdpTls* transport_get_tls(rdpTransport* transport)
1655
0
{
1656
0
  WINPR_ASSERT(transport);
1657
0
  return transport->tls;
1658
0
}
1659
1660
BOOL transport_set_tsg(rdpTransport* transport, rdpTsg* tsg)
1661
0
{
1662
0
  WINPR_ASSERT(transport);
1663
0
  tsg_free(transport->tsg);
1664
0
  transport->tsg = tsg;
1665
0
  return TRUE;
1666
0
}
1667
1668
rdpTsg* transport_get_tsg(rdpTransport* transport)
1669
0
{
1670
0
  WINPR_ASSERT(transport);
1671
0
  return transport->tsg;
1672
0
}
1673
1674
wStream* transport_take_from_pool(rdpTransport* transport, size_t size)
1675
0
{
1676
0
  WINPR_ASSERT(transport);
1677
0
  return StreamPool_Take(transport->ReceivePool, size);
1678
0
}
1679
1680
ULONG transport_get_bytes_sent(rdpTransport* transport, BOOL resetCount)
1681
0
{
1682
0
  ULONG rc;
1683
0
  WINPR_ASSERT(transport);
1684
0
  rc = transport->written;
1685
0
  if (resetCount)
1686
0
    transport->written = 0;
1687
0
  return rc;
1688
0
}
1689
1690
TRANSPORT_LAYER transport_get_layer(rdpTransport* transport)
1691
0
{
1692
0
  WINPR_ASSERT(transport);
1693
0
  return transport->layer;
1694
0
}
1695
1696
BOOL transport_set_layer(rdpTransport* transport, TRANSPORT_LAYER layer)
1697
0
{
1698
0
  WINPR_ASSERT(transport);
1699
0
  transport->layer = layer;
1700
0
  return TRUE;
1701
0
}
1702
1703
BOOL transport_set_connected_event(rdpTransport* transport)
1704
0
{
1705
0
  WINPR_ASSERT(transport);
1706
0
  return SetEvent(transport->connectedEvent);
1707
0
}
1708
1709
BOOL transport_set_recv_callbacks(rdpTransport* transport, TransportRecv recv, void* extra)
1710
0
{
1711
0
  WINPR_ASSERT(transport);
1712
0
  transport->ReceiveCallback = recv;
1713
0
  transport->ReceiveExtra = extra;
1714
0
  return TRUE;
1715
0
}
1716
1717
BOOL transport_get_blocking(rdpTransport* transport)
1718
0
{
1719
0
  WINPR_ASSERT(transport);
1720
0
  return transport->blocking;
1721
0
}
1722
1723
BOOL transport_set_blocking(rdpTransport* transport, BOOL blocking)
1724
0
{
1725
0
  WINPR_ASSERT(transport);
1726
0
  transport->blocking = blocking;
1727
0
  return TRUE;
1728
0
}
1729
1730
BOOL transport_have_more_bytes_to_read(rdpTransport* transport)
1731
0
{
1732
0
  WINPR_ASSERT(transport);
1733
0
  return transport->haveMoreBytesToRead;
1734
0
}
1735
1736
int transport_tcp_connect(rdpTransport* transport, const char* hostname, int port, DWORD timeout)
1737
0
{
1738
0
  rdpContext* context = transport_get_context(transport);
1739
0
  WINPR_ASSERT(context);
1740
0
  WINPR_ASSERT(context->settings);
1741
0
  return IFCALLRESULT(-1, transport->io.TCPConnect, context, context->settings, hostname, port,
1742
0
                      timeout);
1743
0
}
1744
1745
HANDLE transport_get_front_bio(rdpTransport* transport)
1746
0
{
1747
0
  HANDLE hEvent = NULL;
1748
0
  WINPR_ASSERT(transport);
1749
0
  WINPR_ASSERT(transport->frontBio);
1750
1751
0
  BIO_get_event(transport->frontBio, &hEvent);
1752
0
  return hEvent;
1753
0
}
1754
1755
BOOL transport_io_callback_set_event(rdpTransport* transport, BOOL set)
1756
0
{
1757
0
  WINPR_ASSERT(transport);
1758
0
  transport->useIoEvent = TRUE;
1759
0
  if (!set)
1760
0
    return ResetEvent(transport->ioEvent);
1761
0
  return SetEvent(transport->ioEvent);
1762
0
}
1763
1764
void transport_set_early_user_auth_mode(rdpTransport* transport, BOOL EUAMode)
1765
0
{
1766
0
  WINPR_ASSERT(transport);
1767
0
  transport->earlyUserAuth = EUAMode;
1768
0
  WLog_Print(transport->log, WLOG_DEBUG, "Early User Auth Mode: %s", EUAMode ? "on" : "off");
1769
0
}