Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/libfreerdp/core/tcp.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Transmission Control Protocol (TCP)
4
 *
5
 * Copyright 2011 Vic Lee
6
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
#include <freerdp/config.h>
22
23
#include "settings.h"
24
25
#include <time.h>
26
#include <errno.h>
27
#include <fcntl.h>
28
29
#include <winpr/crt.h>
30
#include <winpr/platform.h>
31
#include <winpr/winsock.h>
32
33
#include "rdp.h"
34
#include "utils.h"
35
36
#if !defined(_WIN32)
37
38
#include <netdb.h>
39
#include <unistd.h>
40
#include <sys/ioctl.h>
41
#include <sys/socket.h>
42
#include <netinet/in.h>
43
#include <netinet/tcp.h>
44
#include <net/if.h>
45
#include <sys/types.h>
46
#include <arpa/inet.h>
47
48
#ifdef WINPR_HAVE_POLL_H
49
#include <poll.h>
50
#else
51
#include <time.h>
52
#include <sys/select.h>
53
#endif
54
55
#if defined(__FreeBSD__) || defined(__OpenBSD__)
56
#ifndef SOL_TCP
57
#define SOL_TCP IPPROTO_TCP
58
#endif
59
#endif
60
61
#ifdef __APPLE__
62
#ifndef SOL_TCP
63
#define SOL_TCP IPPROTO_TCP
64
#endif
65
#ifndef TCP_KEEPIDLE
66
#define TCP_KEEPIDLE TCP_KEEPALIVE
67
#endif
68
#endif
69
70
#else
71
72
#include <winpr/windows.h>
73
74
#include <winpr/crt.h>
75
76
#define SHUT_RDWR SD_BOTH
77
#define close(_fd) closesocket(_fd)
78
79
#endif
80
81
#include <freerdp/log.h>
82
83
#include <winpr/stream.h>
84
85
#include "tcp.h"
86
#include "../crypto/opensslcompat.h"
87
88
#if defined(HAVE_AF_VSOCK_H)
89
#include <ctype.h>
90
#include <linux/vm_sockets.h>
91
#endif
92
93
#define TAG FREERDP_TAG("core")
94
95
/* Simple Socket BIO */
96
97
typedef struct
98
{
99
  SOCKET socket;
100
  HANDLE hEvent;
101
} WINPR_BIO_SIMPLE_SOCKET;
102
103
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown);
104
static int transport_bio_simple_uninit(BIO* bio);
105
106
static long transport_bio_simple_callback(BIO* bio, int mode, const char* argp, int argi, long argl,
107
                                          long ret)
108
0
{
109
0
  return 1;
110
0
}
111
112
static int transport_bio_simple_write(BIO* bio, const char* buf, int size)
113
337
{
114
337
  int error = 0;
115
337
  int status = 0;
116
337
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
117
118
337
  if (!buf)
119
0
    return 0;
120
121
337
  BIO_clear_flags(bio, BIO_FLAGS_WRITE);
122
337
  status = _send(ptr->socket, buf, size, 0);
123
124
337
  if (status <= 0)
125
337
  {
126
337
    error = WSAGetLastError();
127
128
337
    if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
129
337
        (error == WSAEALREADY))
130
0
    {
131
0
      BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
132
0
    }
133
337
    else
134
337
    {
135
337
      BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
136
337
    }
137
337
  }
138
139
337
  return status;
140
337
}
141
142
static int transport_bio_simple_read(BIO* bio, char* buf, int size)
143
0
{
144
0
  int error = 0;
145
0
  int status = 0;
146
0
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
147
148
0
  if (!buf)
149
0
    return 0;
150
151
0
  BIO_clear_flags(bio, BIO_FLAGS_READ);
152
0
  WSAResetEvent(ptr->hEvent);
153
0
  status = _recv(ptr->socket, buf, size, 0);
154
155
0
  if (status > 0)
156
0
  {
157
0
    return status;
158
0
  }
159
160
0
  if (status == 0)
161
0
  {
162
0
    BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
163
0
    return 0;
164
0
  }
165
166
0
  error = WSAGetLastError();
167
168
0
  if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
169
0
      (error == WSAEALREADY))
170
0
  {
171
0
    BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
172
0
  }
173
0
  else
174
0
  {
175
0
    BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
176
0
  }
177
178
0
  return -1;
179
0
}
180
181
static int transport_bio_simple_puts(BIO* bio, const char* str)
182
0
{
183
0
  return 1;
184
0
}
185
186
static int transport_bio_simple_gets(BIO* bio, char* str, int size)
187
0
{
188
0
  return 1;
189
0
}
190
191
static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
192
20.9k
{
193
20.9k
  int status = -1;
194
20.9k
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
195
196
20.9k
  switch (cmd)
197
20.9k
  {
198
0
    case BIO_C_SET_SOCKET:
199
0
      transport_bio_simple_uninit(bio);
200
0
      transport_bio_simple_init(bio, (SOCKET)arg2, (int)arg1);
201
0
      return 1;
202
0
    case BIO_C_GET_SOCKET:
203
0
      if (!BIO_get_init(bio) || !arg2)
204
0
        return 0;
205
206
0
      *((SOCKET*)arg2) = ptr->socket;
207
0
      return 1;
208
0
    case BIO_C_GET_EVENT:
209
0
      if (!BIO_get_init(bio) || !arg2)
210
0
        return 0;
211
212
0
      *((HANDLE*)arg2) = ptr->hEvent;
213
0
      return 1;
214
6.97k
    case BIO_C_SET_NONBLOCK:
215
6.97k
    {
216
6.97k
#ifndef _WIN32
217
6.97k
      int flags = 0;
218
6.97k
      flags = fcntl((int)ptr->socket, F_GETFL);
219
220
6.97k
      if (flags == -1)
221
0
        return 0;
222
223
6.97k
      if (arg1)
224
6.97k
        fcntl((int)ptr->socket, F_SETFL, flags | O_NONBLOCK);
225
0
      else
226
0
        fcntl((int)ptr->socket, F_SETFL, flags & ~(O_NONBLOCK));
227
228
#else
229
      /* the internal socket is always non-blocking */
230
#endif
231
6.97k
      return 1;
232
6.97k
    }
233
0
    case BIO_C_WAIT_READ:
234
0
    {
235
0
      int timeout = (int)arg1;
236
0
      int sockfd = (int)ptr->socket;
237
0
#ifdef WINPR_HAVE_POLL_H
238
0
      struct pollfd pollset;
239
0
      pollset.fd = sockfd;
240
0
      pollset.events = POLLIN;
241
0
      pollset.revents = 0;
242
243
0
      do
244
0
      {
245
0
        status = poll(&pollset, 1, timeout);
246
0
      } while ((status < 0) && (errno == EINTR));
247
248
#else
249
      fd_set rset;
250
      struct timeval tv;
251
      FD_ZERO(&rset);
252
      FD_SET(sockfd, &rset);
253
254
      if (timeout)
255
      {
256
        tv.tv_sec = timeout / 1000;
257
        tv.tv_usec = (timeout % 1000) * 1000;
258
      }
259
260
      do
261
      {
262
        status = select(sockfd + 1, &rset, NULL, NULL, timeout ? &tv : NULL);
263
      } while ((status < 0) && (errno == EINTR));
264
265
#endif
266
0
    }
267
0
    break;
268
0
    case BIO_C_WAIT_WRITE:
269
0
    {
270
0
      int timeout = (int)arg1;
271
0
      int sockfd = (int)ptr->socket;
272
0
#ifdef WINPR_HAVE_POLL_H
273
0
      struct pollfd pollset;
274
0
      pollset.fd = sockfd;
275
0
      pollset.events = POLLOUT;
276
0
      pollset.revents = 0;
277
278
0
      do
279
0
      {
280
0
        status = poll(&pollset, 1, timeout);
281
0
      } while ((status < 0) && (errno == EINTR));
282
283
#else
284
      fd_set rset;
285
      struct timeval tv;
286
      FD_ZERO(&rset);
287
      FD_SET(sockfd, &rset);
288
289
      if (timeout)
290
      {
291
        tv.tv_sec = timeout / 1000;
292
        tv.tv_usec = (timeout % 1000) * 1000;
293
      }
294
295
      do
296
      {
297
        status = select(sockfd + 1, NULL, &rset, NULL, timeout ? &tv : NULL);
298
      } while ((status < 0) && (errno == EINTR));
299
300
#endif
301
0
    }
302
0
    break;
303
13.9k
    default:
304
13.9k
      break;
305
20.9k
  }
306
307
13.9k
  switch (cmd)
308
13.9k
  {
309
6.97k
    case BIO_C_SET_FD:
310
6.97k
      if (arg2)
311
6.97k
      {
312
6.97k
        transport_bio_simple_uninit(bio);
313
6.97k
        transport_bio_simple_init(bio, (SOCKET) * ((int*)arg2), (int)arg1);
314
6.97k
        status = 1;
315
6.97k
      }
316
317
6.97k
      break;
318
319
0
    case BIO_C_GET_FD:
320
0
      if (BIO_get_init(bio))
321
0
      {
322
0
        if (arg2)
323
0
          *((int*)arg2) = (int)ptr->socket;
324
325
0
        status = (int)ptr->socket;
326
0
      }
327
328
0
      break;
329
330
0
    case BIO_CTRL_GET_CLOSE:
331
0
      status = BIO_get_shutdown(bio);
332
0
      break;
333
334
0
    case BIO_CTRL_SET_CLOSE:
335
0
      BIO_set_shutdown(bio, (int)arg1);
336
0
      status = 1;
337
0
      break;
338
339
0
    case BIO_CTRL_DUP:
340
0
      status = 1;
341
0
      break;
342
343
0
    case BIO_CTRL_FLUSH:
344
0
      status = 1;
345
0
      break;
346
347
6.97k
    default:
348
6.97k
      status = 0;
349
6.97k
      break;
350
13.9k
  }
351
352
13.9k
  return status;
353
13.9k
}
354
355
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
356
6.97k
{
357
6.97k
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
358
6.97k
  ptr->socket = socket;
359
6.97k
  BIO_set_shutdown(bio, shutdown);
360
6.97k
  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
361
6.97k
  BIO_set_init(bio, 1);
362
6.97k
  ptr->hEvent = WSACreateEvent();
363
364
6.97k
  if (!ptr->hEvent)
365
0
    return 0;
366
367
  /* WSAEventSelect automatically sets the socket in non-blocking mode */
368
6.97k
  if (WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_ACCEPT | FD_CLOSE))
369
0
  {
370
0
    WLog_ERR(TAG, "WSAEventSelect returned 0x%08X", WSAGetLastError());
371
0
    return 0;
372
0
  }
373
374
6.97k
  return 1;
375
6.97k
}
376
377
static int transport_bio_simple_uninit(BIO* bio)
378
13.9k
{
379
13.9k
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
380
381
13.9k
  if (BIO_get_shutdown(bio))
382
13.9k
  {
383
13.9k
    if (BIO_get_init(bio) && ptr)
384
6.97k
    {
385
6.97k
      _shutdown(ptr->socket, SD_BOTH);
386
6.97k
      closesocket(ptr->socket);
387
6.97k
      ptr->socket = 0;
388
6.97k
    }
389
13.9k
  }
390
391
13.9k
  if (ptr && ptr->hEvent)
392
6.97k
  {
393
6.97k
    CloseHandle(ptr->hEvent);
394
6.97k
    ptr->hEvent = NULL;
395
6.97k
  }
396
397
13.9k
  BIO_set_init(bio, 0);
398
13.9k
  BIO_set_flags(bio, 0);
399
13.9k
  return 1;
400
13.9k
}
401
402
static int transport_bio_simple_new(BIO* bio)
403
6.97k
{
404
6.97k
  WINPR_BIO_SIMPLE_SOCKET* ptr = NULL;
405
6.97k
  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
406
6.97k
  ptr = (WINPR_BIO_SIMPLE_SOCKET*)calloc(1, sizeof(WINPR_BIO_SIMPLE_SOCKET));
407
408
6.97k
  if (!ptr)
409
0
    return 0;
410
411
6.97k
  BIO_set_data(bio, ptr);
412
6.97k
  return 1;
413
6.97k
}
414
415
static int transport_bio_simple_free(BIO* bio)
416
6.97k
{
417
6.97k
  WINPR_BIO_SIMPLE_SOCKET* ptr = NULL;
418
419
6.97k
  if (!bio)
420
0
    return 0;
421
422
6.97k
  transport_bio_simple_uninit(bio);
423
6.97k
  ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
424
425
6.97k
  if (ptr)
426
6.97k
  {
427
6.97k
    BIO_set_data(bio, NULL);
428
6.97k
    free(ptr);
429
6.97k
  }
430
431
6.97k
  return 1;
432
6.97k
}
433
434
BIO_METHOD* BIO_s_simple_socket(void)
435
6.97k
{
436
6.97k
  static BIO_METHOD* bio_methods = NULL;
437
438
6.97k
  if (bio_methods == NULL)
439
1
  {
440
1
    if (!(bio_methods = BIO_meth_new(BIO_TYPE_SIMPLE, "SimpleSocket")))
441
0
      return NULL;
442
443
1
    BIO_meth_set_write(bio_methods, transport_bio_simple_write);
444
1
    BIO_meth_set_read(bio_methods, transport_bio_simple_read);
445
1
    BIO_meth_set_puts(bio_methods, transport_bio_simple_puts);
446
1
    BIO_meth_set_gets(bio_methods, transport_bio_simple_gets);
447
1
    BIO_meth_set_ctrl(bio_methods, transport_bio_simple_ctrl);
448
1
    BIO_meth_set_create(bio_methods, transport_bio_simple_new);
449
1
    BIO_meth_set_destroy(bio_methods, transport_bio_simple_free);
450
1
  }
451
452
6.97k
  return bio_methods;
453
6.97k
}
454
455
/* Buffered Socket BIO */
456
457
typedef struct
458
{
459
  BIO* bufferedBio;
460
  BOOL readBlocked;
461
  BOOL writeBlocked;
462
  RingBuffer xmitBuffer;
463
} WINPR_BIO_BUFFERED_SOCKET;
464
465
static long transport_bio_buffered_callback(BIO* bio, int mode, const char* argp, int argi,
466
                                            long argl, long ret)
467
0
{
468
0
  return 1;
469
0
}
470
471
static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
472
337
{
473
337
  int ret = num;
474
337
  int nchunks = 0;
475
337
  size_t committedBytes = 0;
476
337
  DataChunk chunks[2] = { 0 };
477
337
  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
478
337
  BIO* next_bio = NULL;
479
480
337
  WINPR_ASSERT(bio);
481
337
  WINPR_ASSERT(ptr);
482
483
337
  ptr->writeBlocked = FALSE;
484
337
  BIO_clear_flags(bio, BIO_FLAGS_WRITE);
485
486
  /* we directly append extra bytes in the xmit buffer, this could be prevented
487
   * but for now it makes the code more simple.
488
   */
489
337
  if (buf && num && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*)buf, num))
490
0
  {
491
0
    WLog_ERR(TAG, "an error occurred when writing (num: %d)", num);
492
0
    return -1;
493
0
  }
494
495
337
  nchunks = ringbuffer_peek(&ptr->xmitBuffer, chunks, ringbuffer_used(&ptr->xmitBuffer));
496
337
  next_bio = BIO_next(bio);
497
498
337
  for (int i = 0; i < nchunks; i++)
499
337
  {
500
337
    while (chunks[i].size)
501
337
    {
502
337
      ERR_clear_error();
503
337
      const int status = BIO_write(next_bio, chunks[i].data, chunks[i].size);
504
505
337
      if (status <= 0)
506
337
      {
507
337
        if (!BIO_should_retry(next_bio))
508
337
        {
509
337
          BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
510
337
          ret = -1; /* fatal error */
511
337
          goto out;
512
337
        }
513
514
0
        if (BIO_should_write(next_bio))
515
0
        {
516
0
          BIO_set_flags(bio, BIO_FLAGS_WRITE);
517
0
          ptr->writeBlocked = TRUE;
518
0
          goto out; /* EWOULDBLOCK */
519
0
        }
520
0
      }
521
0
      else
522
0
      {
523
0
        committedBytes += (size_t)status;
524
0
        chunks[i].size -= (size_t)status;
525
0
        chunks[i].data += status;
526
0
      }
527
337
    }
528
337
  }
529
530
337
out:
531
337
  ringbuffer_commit_read_bytes(&ptr->xmitBuffer, committedBytes);
532
337
  return ret;
533
337
}
534
535
static int transport_bio_buffered_read(BIO* bio, char* buf, int size)
536
0
{
537
0
  int status = 0;
538
0
  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
539
0
  BIO* next_bio = BIO_next(bio);
540
0
  ptr->readBlocked = FALSE;
541
0
  BIO_clear_flags(bio, BIO_FLAGS_READ);
542
0
  ERR_clear_error();
543
0
  status = BIO_read(next_bio, buf, size);
544
545
0
  if (status <= 0)
546
0
  {
547
0
    if (!BIO_should_retry(next_bio))
548
0
    {
549
0
      BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
550
0
      goto out;
551
0
    }
552
553
0
    BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
554
555
0
    if (BIO_should_read(next_bio))
556
0
    {
557
0
      BIO_set_flags(bio, BIO_FLAGS_READ);
558
0
      ptr->readBlocked = TRUE;
559
0
      goto out;
560
0
    }
561
0
  }
562
563
0
out:
564
0
  return status;
565
0
}
566
567
static int transport_bio_buffered_puts(BIO* bio, const char* str)
568
0
{
569
0
  return 1;
570
0
}
571
572
static int transport_bio_buffered_gets(BIO* bio, char* str, int size)
573
0
{
574
0
  return 1;
575
0
}
576
577
static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
578
13.9k
{
579
13.9k
  long status = -1;
580
13.9k
  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
581
582
13.9k
  switch (cmd)
583
13.9k
  {
584
0
    case BIO_CTRL_FLUSH:
585
0
      if (!ringbuffer_used(&ptr->xmitBuffer))
586
0
        status = 1;
587
0
      else
588
0
        status = (transport_bio_buffered_write(bio, NULL, 0) >= 0) ? 1 : -1;
589
590
0
      break;
591
592
0
    case BIO_CTRL_WPENDING:
593
0
      status = ringbuffer_used(&ptr->xmitBuffer);
594
0
      break;
595
596
0
    case BIO_CTRL_PENDING:
597
0
      status = 0;
598
0
      break;
599
600
0
    case BIO_C_READ_BLOCKED:
601
0
      status = (int)ptr->readBlocked;
602
0
      break;
603
604
0
    case BIO_C_WRITE_BLOCKED:
605
0
      status = (int)ptr->writeBlocked;
606
0
      break;
607
608
13.9k
    default:
609
13.9k
      status = BIO_ctrl(BIO_next(bio), cmd, arg1, arg2);
610
13.9k
      break;
611
13.9k
  }
612
613
13.9k
  return status;
614
13.9k
}
615
616
static int transport_bio_buffered_new(BIO* bio)
617
6.97k
{
618
6.97k
  WINPR_BIO_BUFFERED_SOCKET* ptr = NULL;
619
6.97k
  BIO_set_init(bio, 1);
620
6.97k
  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
621
6.97k
  ptr = (WINPR_BIO_BUFFERED_SOCKET*)calloc(1, sizeof(WINPR_BIO_BUFFERED_SOCKET));
622
623
6.97k
  if (!ptr)
624
0
    return -1;
625
626
6.97k
  BIO_set_data(bio, (void*)ptr);
627
628
6.97k
  if (!ringbuffer_init(&ptr->xmitBuffer, 0x10000))
629
0
    return -1;
630
631
6.97k
  return 1;
632
6.97k
}
633
634
/* Free the buffered BIO.
635
 * Do not free other elements in the BIO stack,
636
 * let BIO_free_all handle that. */
637
static int transport_bio_buffered_free(BIO* bio)
638
6.97k
{
639
6.97k
  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
640
641
6.97k
  if (!ptr)
642
0
    return 0;
643
644
6.97k
  ringbuffer_destroy(&ptr->xmitBuffer);
645
6.97k
  free(ptr);
646
6.97k
  return 1;
647
6.97k
}
648
649
BIO_METHOD* BIO_s_buffered_socket(void)
650
6.97k
{
651
6.97k
  static BIO_METHOD* bio_methods = NULL;
652
653
6.97k
  if (bio_methods == NULL)
654
1
  {
655
1
    if (!(bio_methods = BIO_meth_new(BIO_TYPE_BUFFERED, "BufferedSocket")))
656
0
      return NULL;
657
658
1
    BIO_meth_set_write(bio_methods, transport_bio_buffered_write);
659
1
    BIO_meth_set_read(bio_methods, transport_bio_buffered_read);
660
1
    BIO_meth_set_puts(bio_methods, transport_bio_buffered_puts);
661
1
    BIO_meth_set_gets(bio_methods, transport_bio_buffered_gets);
662
1
    BIO_meth_set_ctrl(bio_methods, transport_bio_buffered_ctrl);
663
1
    BIO_meth_set_create(bio_methods, transport_bio_buffered_new);
664
1
    BIO_meth_set_destroy(bio_methods, transport_bio_buffered_free);
665
1
  }
666
667
6.97k
  return bio_methods;
668
6.97k
}
669
670
char* freerdp_tcp_address_to_string(const struct sockaddr_storage* addr, BOOL* pIPv6)
671
0
{
672
0
  char ipAddress[INET6_ADDRSTRLEN + 1] = { 0 };
673
0
  const struct sockaddr_in6* sockaddr_ipv6 = (const struct sockaddr_in6*)addr;
674
0
  const struct sockaddr_in* sockaddr_ipv4 = (const struct sockaddr_in*)addr;
675
676
0
  if (addr == NULL)
677
0
  {
678
0
    return NULL;
679
0
  }
680
681
0
  switch (sockaddr_ipv4->sin_family)
682
0
  {
683
0
    case AF_INET:
684
0
      if (!inet_ntop(sockaddr_ipv4->sin_family, &sockaddr_ipv4->sin_addr, ipAddress,
685
0
                     sizeof(ipAddress)))
686
0
        return NULL;
687
688
0
      break;
689
690
0
    case AF_INET6:
691
0
      if (!inet_ntop(sockaddr_ipv6->sin6_family, &sockaddr_ipv6->sin6_addr, ipAddress,
692
0
                     sizeof(ipAddress)))
693
0
        return NULL;
694
695
0
      break;
696
697
0
    case AF_UNIX:
698
0
      sprintf_s(ipAddress, ARRAYSIZE(ipAddress), "127.0.0.1");
699
0
      break;
700
701
0
    default:
702
0
      return NULL;
703
0
  }
704
705
0
  if (pIPv6 != NULL)
706
0
  {
707
0
    *pIPv6 = (sockaddr_ipv4->sin_family == AF_INET6);
708
0
  }
709
710
0
  return _strdup(ipAddress);
711
0
}
712
713
static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
714
0
{
715
0
  struct sockaddr_storage saddr = { 0 };
716
0
  socklen_t length = sizeof(struct sockaddr_storage);
717
718
0
  if (getsockname(sockfd, (struct sockaddr*)&saddr, &length) != 0)
719
0
  {
720
0
    return NULL;
721
0
  }
722
723
0
  return freerdp_tcp_address_to_string(&saddr, pIPv6);
724
0
}
725
726
char* freerdp_tcp_get_peer_address(SOCKET sockfd)
727
0
{
728
0
  struct sockaddr_storage saddr = { 0 };
729
0
  socklen_t length = sizeof(struct sockaddr_storage);
730
731
0
  if (getpeername(sockfd, (struct sockaddr*)&saddr, &length) != 0)
732
0
  {
733
0
    return NULL;
734
0
  }
735
736
0
  return freerdp_tcp_address_to_string(&saddr, NULL);
737
0
}
738
739
static int freerdp_uds_connect(const char* path)
740
0
{
741
0
#ifndef _WIN32
742
0
  int status = 0;
743
0
  int sockfd = 0;
744
0
  struct sockaddr_un addr = { 0 };
745
0
  sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
746
747
0
  if (sockfd == -1)
748
0
  {
749
0
    WLog_ERR(TAG, "socket");
750
0
    return -1;
751
0
  }
752
753
0
  addr.sun_family = AF_UNIX;
754
0
  strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
755
0
  status = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
756
757
0
  if (status < 0)
758
0
  {
759
0
    WLog_ERR(TAG, "connect");
760
0
    close(sockfd);
761
0
    return -1;
762
0
  }
763
764
0
  return sockfd;
765
#else /* ifndef _WIN32 */
766
  return -1;
767
#endif
768
0
}
769
770
struct addrinfo* freerdp_tcp_resolve_host(const char* hostname, int port, int ai_flags)
771
0
{
772
0
  char* service = NULL;
773
0
  char port_str[16];
774
0
  int status = 0;
775
0
  struct addrinfo hints = { 0 };
776
0
  struct addrinfo* result = NULL;
777
0
  hints.ai_family = AF_UNSPEC;
778
0
  hints.ai_socktype = SOCK_STREAM;
779
0
  hints.ai_flags = ai_flags;
780
781
0
  if (port >= 0)
782
0
  {
783
0
    sprintf_s(port_str, sizeof(port_str) - 1, "%d", port);
784
0
    service = port_str;
785
0
  }
786
787
0
  status = getaddrinfo(hostname, service, &hints, &result);
788
789
0
  if (status)
790
0
    return NULL;
791
792
0
  return result;
793
0
}
794
795
static BOOL freerdp_tcp_is_hostname_resolvable(rdpContext* context, const char* hostname)
796
0
{
797
0
  struct addrinfo* result = freerdp_tcp_resolve_host(hostname, -1, 0);
798
799
0
  if (!result)
800
0
  {
801
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
802
803
0
    return FALSE;
804
0
  }
805
806
0
  freerdp_set_last_error_log(context, 0);
807
0
  freeaddrinfo(result);
808
0
  return TRUE;
809
0
}
810
811
static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, struct sockaddr* addr,
812
                                        socklen_t addrlen, UINT32 timeout)
813
0
{
814
0
  BOOL rc = FALSE;
815
0
  HANDLE handles[2];
816
0
  int status = 0;
817
0
  int count = 0;
818
0
  u_long arg = 0;
819
0
  DWORD tout = (timeout > 0) ? timeout : INFINITE;
820
821
0
  handles[count] = CreateEvent(NULL, TRUE, FALSE, NULL);
822
823
0
  if (!handles[count])
824
0
    return FALSE;
825
826
0
  status = WSAEventSelect(sockfd, handles[count++], FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
827
828
0
  if (status < 0)
829
0
  {
830
0
    WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError());
831
0
    goto fail;
832
0
  }
833
834
0
  handles[count++] = utils_get_abort_event(context->rdp);
835
0
  status = _connect(sockfd, addr, addrlen);
836
837
0
  if (status < 0)
838
0
  {
839
0
    status = WSAGetLastError();
840
841
0
    switch (status)
842
0
    {
843
0
      case WSAEINPROGRESS:
844
0
      case WSAEWOULDBLOCK:
845
0
        break;
846
847
0
      default:
848
0
        goto fail;
849
0
    }
850
0
  }
851
852
0
  status = WaitForMultipleObjects(count, handles, FALSE, tout);
853
854
0
  if (WAIT_OBJECT_0 != status)
855
0
    goto fail;
856
857
0
  status = recv(sockfd, NULL, 0, 0);
858
859
0
  if (status == SOCKET_ERROR)
860
0
  {
861
0
    if (WSAGetLastError() == WSAECONNRESET)
862
0
      goto fail;
863
0
  }
864
865
0
  status = WSAEventSelect(sockfd, handles[0], 0);
866
867
0
  if (status < 0)
868
0
  {
869
0
    WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError());
870
0
    goto fail;
871
0
  }
872
873
0
  if (_ioctlsocket(sockfd, FIONBIO, &arg) != 0)
874
0
    goto fail;
875
876
0
  rc = TRUE;
877
0
fail:
878
0
  CloseHandle(handles[0]);
879
0
  return rc;
880
0
}
881
882
typedef struct
883
{
884
  SOCKET s;
885
  struct addrinfo* addr;
886
  struct addrinfo* result;
887
} t_peer;
888
889
static void peer_free(t_peer* peer)
890
0
{
891
0
  if (peer->s != INVALID_SOCKET)
892
0
    closesocket(peer->s);
893
894
0
  freeaddrinfo(peer->addr);
895
0
  memset(peer, 0, sizeof(t_peer));
896
0
  peer->s = INVALID_SOCKET;
897
0
}
898
899
static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames, UINT32* ports,
900
                                     UINT32 count, UINT16 port, UINT32 timeout)
901
0
{
902
0
  UINT32 sindex = count;
903
0
  int status = -1;
904
0
  SOCKET sockfd = INVALID_SOCKET;
905
0
  HANDLE* events = NULL;
906
0
  struct addrinfo* addr = NULL;
907
0
  struct addrinfo* result = NULL;
908
0
  t_peer* peers = NULL;
909
0
  events = (HANDLE*)calloc(count + 1, sizeof(HANDLE));
910
0
  peers = (t_peer*)calloc(count, sizeof(t_peer));
911
912
0
  if (!peers || !events || (count < 1))
913
0
  {
914
0
    free(peers);
915
0
    free(events);
916
0
    return -1;
917
0
  }
918
919
0
  for (UINT32 index = 0; index < count; index++)
920
0
  {
921
0
    int curPort = port;
922
923
0
    if (ports)
924
0
      curPort = ports[index];
925
926
0
    result = freerdp_tcp_resolve_host(hostnames[index], curPort, 0);
927
928
0
    if (!result)
929
0
      continue;
930
931
0
    addr = result;
932
933
0
    if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0))
934
0
    {
935
0
      while ((addr = addr->ai_next))
936
0
      {
937
0
        if (addr->ai_family == AF_INET)
938
0
          break;
939
0
      }
940
941
0
      if (!addr)
942
0
        addr = result;
943
0
    }
944
945
0
    peers[index].s = _socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
946
947
0
    if (peers[index].s == INVALID_SOCKET)
948
0
    {
949
0
      freeaddrinfo(result);
950
0
      continue;
951
0
    }
952
953
0
    peers[index].addr = addr;
954
0
    peers[index].result = result;
955
0
  }
956
957
0
  for (UINT32 index = 0; index < count; index++)
958
0
  {
959
0
    sockfd = peers[index].s;
960
0
    addr = peers[index].addr;
961
962
0
    if ((sockfd == INVALID_SOCKET) || (!addr))
963
0
      continue;
964
965
    /* blocking tcp connect */
966
0
    status = _connect(sockfd, addr->ai_addr, addr->ai_addrlen);
967
968
0
    if (status >= 0)
969
0
    {
970
      /* connection success */
971
0
      sindex = index;
972
0
      break;
973
0
    }
974
0
  }
975
976
0
  if (sindex < count)
977
0
  {
978
0
    sockfd = peers[sindex].s;
979
0
    peers[sindex].s = INVALID_SOCKET;
980
0
  }
981
0
  else
982
0
    freerdp_set_last_error_log(context, FREERDP_ERROR_CONNECT_CANCELLED);
983
984
0
  for (UINT32 index = 0; index < count; index++)
985
0
    peer_free(&peers[index]);
986
987
0
  free(peers);
988
0
  free(events);
989
0
  return sockfd;
990
0
}
991
992
BOOL freerdp_tcp_set_keep_alive_mode(const rdpSettings* settings, int sockfd)
993
6.97k
{
994
6.97k
  const BOOL keepalive = (freerdp_settings_get_bool(settings, FreeRDP_TcpKeepAlive));
995
6.97k
  UINT32 optval = 0;
996
6.97k
  socklen_t optlen = 0;
997
6.97k
  optval = keepalive ? 1 : 0;
998
6.97k
  optlen = sizeof(optval);
999
1000
6.97k
  if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, optlen) < 0)
1001
6.97k
  {
1002
6.97k
    WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_KEEPALIVE");
1003
6.97k
  }
1004
1005
6.97k
#ifndef _WIN32
1006
6.97k
#ifdef TCP_KEEPIDLE
1007
6.97k
  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveDelay) : 0;
1008
6.97k
  optlen = sizeof(optval);
1009
1010
6.97k
  if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void*)&optval, optlen) < 0)
1011
6.97k
  {
1012
6.97k
    WLog_WARN(TAG, "setsockopt() IPPROTO_TCP, TCP_KEEPIDLE");
1013
6.97k
  }
1014
1015
6.97k
#endif
1016
#ifndef SOL_TCP
1017
  /* "tcp" from /etc/protocols as getprotobyname(3C) */
1018
#define SOL_TCP 6
1019
#endif
1020
6.97k
#ifdef TCP_KEEPCNT
1021
6.97k
  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveRetries) : 0;
1022
6.97k
  optlen = sizeof(optval);
1023
1024
6.97k
  if (setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void*)&optval, optlen) < 0)
1025
6.97k
  {
1026
6.97k
    WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPCNT");
1027
6.97k
  }
1028
1029
6.97k
#endif
1030
6.97k
#ifdef TCP_KEEPINTVL
1031
6.97k
  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveInterval) : 0;
1032
6.97k
  optlen = sizeof(optval);
1033
1034
6.97k
  if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void*)&optval, optlen) < 0)
1035
6.97k
  {
1036
6.97k
    WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPINTVL");
1037
6.97k
  }
1038
1039
6.97k
#endif
1040
6.97k
#endif
1041
#if defined(__MACOSX__) || defined(__IOS__)
1042
  optval = 1;
1043
  optlen = sizeof(optval);
1044
1045
  if (setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&optval, optlen) < 0)
1046
  {
1047
    WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_NOSIGPIPE");
1048
  }
1049
1050
#endif
1051
6.97k
#ifdef TCP_USER_TIMEOUT
1052
6.97k
  optval = freerdp_settings_get_uint32(settings, FreeRDP_TcpAckTimeout);
1053
6.97k
  optlen = sizeof(optval);
1054
1055
6.97k
  if (setsockopt(sockfd, SOL_TCP, TCP_USER_TIMEOUT, (void*)&optval, optlen) < 0)
1056
6.97k
  {
1057
6.97k
    WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_USER_TIMEOUT");
1058
6.97k
  }
1059
1060
6.97k
#endif
1061
6.97k
  return TRUE;
1062
6.97k
}
1063
1064
int freerdp_tcp_connect(rdpContext* context, const char* hostname, int port, DWORD timeout)
1065
0
{
1066
0
  rdpTransport* transport = NULL;
1067
0
  if (!context || !context->rdp)
1068
0
    return -1;
1069
0
  transport = context->rdp->transport;
1070
0
  if (!transport)
1071
0
    return -1;
1072
0
  return transport_tcp_connect(context->rdp->transport, hostname, port, timeout);
1073
0
}
1074
1075
int freerdp_tcp_default_connect(rdpContext* context, rdpSettings* settings, const char* hostname,
1076
                                int port, DWORD timeout)
1077
0
{
1078
0
  int sockfd = 0;
1079
0
  UINT32 optval = 0;
1080
0
  socklen_t optlen = 0;
1081
0
  BOOL ipcSocket = FALSE;
1082
0
  BOOL useExternalDefinedSocket = FALSE;
1083
1084
0
  if (!hostname)
1085
0
  {
1086
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1087
1088
0
    return -1;
1089
0
  }
1090
1091
0
  if (hostname[0] == '/')
1092
0
    ipcSocket = TRUE;
1093
1094
0
  if (hostname[0] == '|')
1095
0
    useExternalDefinedSocket = TRUE;
1096
1097
0
  const char* vsock = utils_is_vsock(hostname);
1098
0
  if (ipcSocket)
1099
0
  {
1100
0
    sockfd = freerdp_uds_connect(hostname);
1101
1102
0
    if (sockfd < 0)
1103
0
    {
1104
0
      freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1105
1106
0
      return -1;
1107
0
    }
1108
0
  }
1109
0
  else if (useExternalDefinedSocket)
1110
0
    sockfd = port;
1111
0
  else if (vsock)
1112
0
  {
1113
#if defined(HAVE_AF_VSOCK_H)
1114
    hostname = vsock;
1115
    sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
1116
    struct sockaddr_vm addr = { 0 };
1117
1118
    addr.svm_family = AF_VSOCK;
1119
    addr.svm_port = port;
1120
1121
    errno = 0;
1122
    char* ptr = NULL;
1123
    unsigned long val = strtoul(hostname, &ptr, 10);
1124
    if (errno || (val > UINT32_MAX))
1125
    {
1126
      char ebuffer[256] = { 0 };
1127
      WLog_ERR(TAG, "could not extract port from '%s', value=%ul, error=%s", hostname, val,
1128
               winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
1129
      return -1;
1130
    }
1131
    addr.svm_cid = val;
1132
    if (addr.svm_cid == 2)
1133
    {
1134
      addr.svm_flags = VMADDR_FLAG_TO_HOST;
1135
    }
1136
    if ((connect(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_vm))) == -1)
1137
    {
1138
      WLog_ERR(TAG, "failed to connect to %s", hostname);
1139
      return -1;
1140
    }
1141
#else
1142
0
    WLog_ERR(TAG, "Compiled without AF_VSOCK, '%s' not supported", hostname);
1143
0
    return -1;
1144
0
#endif
1145
0
  }
1146
0
  else
1147
0
  {
1148
0
    sockfd = -1;
1149
1150
0
    if (!settings->GatewayEnabled)
1151
0
    {
1152
0
      if (!freerdp_tcp_is_hostname_resolvable(context, hostname) ||
1153
0
          settings->RemoteAssistanceMode)
1154
0
      {
1155
0
        if (settings->TargetNetAddressCount > 0)
1156
0
        {
1157
0
          sockfd = freerdp_tcp_connect_multi(
1158
0
              context, settings->TargetNetAddresses, settings->TargetNetPorts,
1159
0
              settings->TargetNetAddressCount, port, timeout);
1160
0
        }
1161
0
      }
1162
0
    }
1163
1164
0
    if (sockfd <= 0)
1165
0
    {
1166
0
      char* peerAddress = NULL;
1167
0
      struct addrinfo* addr = NULL;
1168
0
      struct addrinfo* result = NULL;
1169
1170
0
      result = freerdp_tcp_resolve_host(hostname, port, 0);
1171
1172
0
      if (!result)
1173
0
      {
1174
0
        freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
1175
1176
0
        return -1;
1177
0
      }
1178
0
      freerdp_set_last_error_log(context, 0);
1179
1180
0
      addr = result;
1181
1182
0
      if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0) &&
1183
0
          !settings->PreferIPv6OverIPv4)
1184
0
      {
1185
0
        while ((addr = addr->ai_next))
1186
0
        {
1187
0
          if (addr->ai_family == AF_INET)
1188
0
            break;
1189
0
        }
1190
1191
0
        if (!addr)
1192
0
          addr = result;
1193
0
      }
1194
1195
0
      sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
1196
1197
0
      if (sockfd < 0)
1198
0
      {
1199
0
        freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1200
1201
0
        freeaddrinfo(result);
1202
0
        return -1;
1203
0
      }
1204
1205
0
      if ((peerAddress = freerdp_tcp_address_to_string(
1206
0
               (const struct sockaddr_storage*)addr->ai_addr, NULL)) != NULL)
1207
0
      {
1208
0
        WLog_DBG(TAG, "connecting to peer %s", peerAddress);
1209
0
        free(peerAddress);
1210
0
      }
1211
1212
0
      if (!freerdp_tcp_connect_timeout(context, sockfd, addr->ai_addr, addr->ai_addrlen,
1213
0
                                       timeout))
1214
0
      {
1215
0
        freeaddrinfo(result);
1216
0
        close(sockfd);
1217
1218
0
        freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1219
1220
0
        WLog_ERR(TAG, "failed to connect to %s", hostname);
1221
0
        return -1;
1222
0
      }
1223
1224
0
      freeaddrinfo(result);
1225
0
    }
1226
0
  }
1227
1228
0
  if (!vsock)
1229
0
  {
1230
0
    free(settings->ClientAddress);
1231
0
    settings->ClientAddress = freerdp_tcp_get_ip_address(sockfd, &settings->IPv6Enabled);
1232
1233
0
    if (!settings->ClientAddress)
1234
0
    {
1235
0
      if (!useExternalDefinedSocket)
1236
0
        close(sockfd);
1237
1238
0
      freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1239
1240
0
      WLog_ERR(TAG, "Couldn't get socket ip address");
1241
0
      return -1;
1242
0
    }
1243
0
  }
1244
1245
0
  optval = 1;
1246
0
  optlen = sizeof(optval);
1247
1248
0
  if (!ipcSocket && !useExternalDefinedSocket)
1249
0
  {
1250
0
    if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void*)&optval, optlen) < 0)
1251
0
      WLog_ERR(TAG, "unable to set TCP_NODELAY");
1252
0
  }
1253
1254
  /* receive buffer must be a least 32 K */
1255
0
  if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&optval, &optlen) == 0)
1256
0
  {
1257
0
    if (optval < (1024 * 32))
1258
0
    {
1259
0
      optval = 1024 * 32;
1260
0
      optlen = sizeof(optval);
1261
1262
0
      if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&optval, optlen) < 0)
1263
0
      {
1264
0
        close(sockfd);
1265
1266
0
        freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1267
1268
0
        WLog_ERR(TAG, "unable to set receive buffer len");
1269
0
        return -1;
1270
0
      }
1271
0
    }
1272
0
  }
1273
1274
0
  if (!ipcSocket && !useExternalDefinedSocket)
1275
0
  {
1276
0
    if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
1277
0
    {
1278
0
      close(sockfd);
1279
1280
0
      freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1281
1282
0
      WLog_ERR(TAG, "Couldn't set keep alive mode.");
1283
0
      return -1;
1284
0
    }
1285
0
  }
1286
1287
0
  if (WaitForSingleObject(utils_get_abort_event(context->rdp), 0) == WAIT_OBJECT_0)
1288
0
  {
1289
0
    close(sockfd);
1290
0
    return -1;
1291
0
  }
1292
1293
0
  return sockfd;
1294
0
}