Coverage Report

Created: 2023-11-19 06:16

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