Coverage Report

Created: 2023-09-25 06:56

/src/FreeRDP/libfreerdp/crypto/tls.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Transport Layer Security
4
 *
5
 * Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2023 Armin Novak <anovak@thincast.com>
7
 * Copyright 2023 Thincast Technologies GmbH
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 *     http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21
22
#include <freerdp/config.h>
23
24
#include <winpr/assert.h>
25
#include <string.h>
26
#include <errno.h>
27
28
#include <winpr/crt.h>
29
#include <winpr/string.h>
30
#include <winpr/sspi.h>
31
#include <winpr/ssl.h>
32
33
#include <winpr/stream.h>
34
#include <freerdp/utils/ringbuffer.h>
35
36
#include <freerdp/crypto/certificate.h>
37
#include <freerdp/crypto/certificate_data.h>
38
39
#include <freerdp/log.h>
40
#include "../crypto/tls.h"
41
#include "../core/tcp.h"
42
43
#include "opensslcompat.h"
44
#include "certificate.h"
45
#include "privatekey.h"
46
47
#ifdef WINPR_HAVE_POLL_H
48
#include <poll.h>
49
#endif
50
51
#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
52
#include <valgrind/memcheck.h>
53
#endif
54
55
#define TAG FREERDP_TAG("crypto")
56
57
/**
58
 * Earlier Microsoft iOS RDP clients have sent a null or even double null
59
 * terminated hostname in the SNI TLS extension.
60
 * If the length indicator does not equal the hostname strlen OpenSSL
61
 * will abort (see openssl:ssl/t1_lib.c).
62
 * Here is a tcpdump segment of Microsoft Remote Desktop Client Version
63
 * 8.1.7 running on an iPhone 4 with iOS 7.1.2 showing the transmitted
64
 * SNI hostname TLV blob when connection to server "abcd":
65
 * 00                  name_type 0x00 (host_name)
66
 * 00 06               length_in_bytes 0x0006
67
 * 61 62 63 64 00 00   host_name "abcd\0\0"
68
 *
69
 * Currently the only (runtime) workaround is setting an openssl tls
70
 * extension debug callback that sets the SSL context's servername_done
71
 * to 1 which effectively disables the parsing of that extension type.
72
 *
73
 * Nowadays this workaround is not required anymore but still can be
74
 * activated by adding the following define:
75
 *
76
 * #define MICROSOFT_IOS_SNI_BUG
77
 */
78
79
typedef struct
80
{
81
  SSL* ssl;
82
  CRITICAL_SECTION lock;
83
} BIO_RDP_TLS;
84
85
static int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char* hostname,
86
                                  UINT16 port);
87
static void tls_print_certificate_name_mismatch_error(const char* hostname, UINT16 port,
88
                                                      const char* common_name, char** alt_names,
89
                                                      size_t alt_names_count);
90
static void tls_print_new_certificate_warn(rdpCertificateStore* store, const char* hostname,
91
                                           UINT16 port, const char* fingerprint);
92
static void tls_print_certificate_error(rdpCertificateStore* store, rdpCertificateData* stored_data,
93
                                        const char* hostname, UINT16 port, const char* fingerprint);
94
95
static void free_tls_public_key(rdpTls* tls)
96
0
{
97
0
  WINPR_ASSERT(tls);
98
0
  free(tls->PublicKey);
99
0
  tls->PublicKey = NULL;
100
0
  tls->PublicKeyLength = 0;
101
0
}
102
103
static void free_tls_bindings(rdpTls* tls)
104
0
{
105
0
  WINPR_ASSERT(tls);
106
107
0
  if (tls->Bindings)
108
0
    free(tls->Bindings->Bindings);
109
110
0
  free(tls->Bindings);
111
0
  tls->Bindings = NULL;
112
0
}
113
114
static int bio_rdp_tls_write(BIO* bio, const char* buf, int size)
115
0
{
116
0
  int error;
117
0
  int status;
118
0
  BIO_RDP_TLS* tls = (BIO_RDP_TLS*)BIO_get_data(bio);
119
120
0
  if (!buf || !tls)
121
0
    return 0;
122
123
0
  BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
124
0
  EnterCriticalSection(&tls->lock);
125
0
  status = SSL_write(tls->ssl, buf, size);
126
0
  error = SSL_get_error(tls->ssl, status);
127
0
  LeaveCriticalSection(&tls->lock);
128
129
0
  if (status <= 0)
130
0
  {
131
0
    switch (error)
132
0
    {
133
0
      case SSL_ERROR_NONE:
134
0
        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
135
0
        break;
136
137
0
      case SSL_ERROR_WANT_WRITE:
138
0
        BIO_set_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
139
0
        break;
140
141
0
      case SSL_ERROR_WANT_READ:
142
0
        BIO_set_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
143
0
        break;
144
145
0
      case SSL_ERROR_WANT_X509_LOOKUP:
146
0
        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
147
0
        BIO_set_retry_reason(bio, BIO_RR_SSL_X509_LOOKUP);
148
0
        break;
149
150
0
      case SSL_ERROR_WANT_CONNECT:
151
0
        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
152
0
        BIO_set_retry_reason(bio, BIO_RR_CONNECT);
153
0
        break;
154
155
0
      case SSL_ERROR_SYSCALL:
156
0
        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
157
0
        break;
158
159
0
      case SSL_ERROR_SSL:
160
0
        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
161
0
        break;
162
0
    }
163
0
  }
164
165
0
  return status;
166
0
}
167
168
static int bio_rdp_tls_read(BIO* bio, char* buf, int size)
169
0
{
170
0
  int error;
171
0
  int status;
172
0
  BIO_RDP_TLS* tls = (BIO_RDP_TLS*)BIO_get_data(bio);
173
174
0
  if (!buf || !tls)
175
0
    return 0;
176
177
0
  BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
178
0
  EnterCriticalSection(&tls->lock);
179
0
  status = SSL_read(tls->ssl, buf, size);
180
0
  error = SSL_get_error(tls->ssl, status);
181
0
  LeaveCriticalSection(&tls->lock);
182
183
0
  if (status <= 0)
184
0
  {
185
0
    switch (error)
186
0
    {
187
0
      case SSL_ERROR_NONE:
188
0
        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
189
0
        break;
190
191
0
      case SSL_ERROR_WANT_READ:
192
0
        BIO_set_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
193
0
        break;
194
195
0
      case SSL_ERROR_WANT_WRITE:
196
0
        BIO_set_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
197
0
        break;
198
199
0
      case SSL_ERROR_WANT_X509_LOOKUP:
200
0
        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
201
0
        BIO_set_retry_reason(bio, BIO_RR_SSL_X509_LOOKUP);
202
0
        break;
203
204
0
      case SSL_ERROR_WANT_ACCEPT:
205
0
        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
206
0
        BIO_set_retry_reason(bio, BIO_RR_ACCEPT);
207
0
        break;
208
209
0
      case SSL_ERROR_WANT_CONNECT:
210
0
        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
211
0
        BIO_set_retry_reason(bio, BIO_RR_CONNECT);
212
0
        break;
213
214
0
      case SSL_ERROR_SSL:
215
0
        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
216
0
        break;
217
218
0
      case SSL_ERROR_ZERO_RETURN:
219
0
        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
220
0
        break;
221
222
0
      case SSL_ERROR_SYSCALL:
223
0
        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
224
0
        break;
225
0
    }
226
0
  }
227
228
#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
229
230
  if (status > 0)
231
  {
232
    VALGRIND_MAKE_MEM_DEFINED(buf, status);
233
  }
234
235
#endif
236
0
  return status;
237
0
}
238
239
static int bio_rdp_tls_puts(BIO* bio, const char* str)
240
0
{
241
0
  size_t size;
242
0
  int status;
243
244
0
  if (!str)
245
0
    return 0;
246
247
0
  size = strlen(str);
248
0
  ERR_clear_error();
249
0
  status = BIO_write(bio, str, size);
250
0
  return status;
251
0
}
252
253
static int bio_rdp_tls_gets(BIO* bio, char* str, int size)
254
0
{
255
0
  return 1;
256
0
}
257
258
static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr)
259
0
{
260
0
  BIO* ssl_rbio;
261
0
  BIO* ssl_wbio;
262
0
  BIO* next_bio;
263
0
  int status = -1;
264
0
  BIO_RDP_TLS* tls = (BIO_RDP_TLS*)BIO_get_data(bio);
265
266
0
  if (!tls)
267
0
    return 0;
268
269
0
  if (!tls->ssl && (cmd != BIO_C_SET_SSL))
270
0
    return 0;
271
272
0
  next_bio = BIO_next(bio);
273
0
  ssl_rbio = tls->ssl ? SSL_get_rbio(tls->ssl) : NULL;
274
0
  ssl_wbio = tls->ssl ? SSL_get_wbio(tls->ssl) : NULL;
275
276
0
  switch (cmd)
277
0
  {
278
0
    case BIO_CTRL_RESET:
279
0
      SSL_shutdown(tls->ssl);
280
281
0
      if (SSL_in_connect_init(tls->ssl))
282
0
        SSL_set_connect_state(tls->ssl);
283
0
      else if (SSL_in_accept_init(tls->ssl))
284
0
        SSL_set_accept_state(tls->ssl);
285
286
0
      SSL_clear(tls->ssl);
287
288
0
      if (next_bio)
289
0
        status = BIO_ctrl(next_bio, cmd, num, ptr);
290
0
      else if (ssl_rbio)
291
0
        status = BIO_ctrl(ssl_rbio, cmd, num, ptr);
292
0
      else
293
0
        status = 1;
294
295
0
      break;
296
297
0
    case BIO_C_GET_FD:
298
0
      status = BIO_ctrl(ssl_rbio, cmd, num, ptr);
299
0
      break;
300
301
0
    case BIO_CTRL_INFO:
302
0
      status = 0;
303
0
      break;
304
305
0
    case BIO_CTRL_SET_CALLBACK:
306
0
      status = 0;
307
0
      break;
308
309
0
    case BIO_CTRL_GET_CALLBACK:
310
0
      *((ULONG_PTR*)ptr) = (ULONG_PTR)SSL_get_info_callback(tls->ssl);
311
0
      status = 1;
312
0
      break;
313
314
0
    case BIO_C_SSL_MODE:
315
0
      if (num)
316
0
        SSL_set_connect_state(tls->ssl);
317
0
      else
318
0
        SSL_set_accept_state(tls->ssl);
319
320
0
      status = 1;
321
0
      break;
322
323
0
    case BIO_CTRL_GET_CLOSE:
324
0
      status = BIO_get_shutdown(bio);
325
0
      break;
326
327
0
    case BIO_CTRL_SET_CLOSE:
328
0
      BIO_set_shutdown(bio, (int)num);
329
0
      status = 1;
330
0
      break;
331
332
0
    case BIO_CTRL_WPENDING:
333
0
      status = BIO_ctrl(ssl_wbio, cmd, num, ptr);
334
0
      break;
335
336
0
    case BIO_CTRL_PENDING:
337
0
      status = SSL_pending(tls->ssl);
338
339
0
      if (status == 0)
340
0
        status = BIO_pending(ssl_rbio);
341
342
0
      break;
343
344
0
    case BIO_CTRL_FLUSH:
345
0
      BIO_clear_retry_flags(bio);
346
0
      status = BIO_ctrl(ssl_wbio, cmd, num, ptr);
347
0
      if (status != 1)
348
0
        WLog_DBG(TAG, "BIO_ctrl returned %d", status);
349
0
      BIO_copy_next_retry(bio);
350
0
      status = 1;
351
0
      break;
352
353
0
    case BIO_CTRL_PUSH:
354
0
      if (next_bio && (next_bio != ssl_rbio))
355
0
      {
356
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
357
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
358
        SSL_set_bio(tls->ssl, next_bio, next_bio);
359
        CRYPTO_add(&(bio->next_bio->references), 1, CRYPTO_LOCK_BIO);
360
#else
361
        /*
362
         * We are going to pass ownership of next to the SSL object...but
363
         * we don't own a reference to pass yet - so up ref
364
         */
365
0
        BIO_up_ref(next_bio);
366
0
        SSL_set_bio(tls->ssl, next_bio, next_bio);
367
0
#endif
368
0
      }
369
370
0
      status = 1;
371
0
      break;
372
373
0
    case BIO_CTRL_POP:
374
375
      /* Only detach if we are the BIO explicitly being popped */
376
0
      if (bio == ptr)
377
0
      {
378
0
        if (ssl_rbio != ssl_wbio)
379
0
          BIO_free_all(ssl_wbio);
380
381
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
382
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
383
384
        if (next_bio)
385
          CRYPTO_add(&(bio->next_bio->references), -1, CRYPTO_LOCK_BIO);
386
387
        tls->ssl->wbio = tls->ssl->rbio = NULL;
388
#else
389
        /* OpenSSL 1.1: This will also clear the reference we obtained during push */
390
0
        SSL_set_bio(tls->ssl, NULL, NULL);
391
0
#endif
392
0
      }
393
394
0
      status = 1;
395
0
      break;
396
397
0
    case BIO_C_GET_SSL:
398
0
      if (ptr)
399
0
      {
400
0
        *((SSL**)ptr) = tls->ssl;
401
0
        status = 1;
402
0
      }
403
404
0
      break;
405
406
0
    case BIO_C_SET_SSL:
407
0
      BIO_set_shutdown(bio, (int)num);
408
409
0
      if (ptr)
410
0
      {
411
0
        tls->ssl = (SSL*)ptr;
412
0
        ssl_rbio = SSL_get_rbio(tls->ssl);
413
0
      }
414
415
0
      if (ssl_rbio)
416
0
      {
417
0
        if (next_bio)
418
0
          BIO_push(ssl_rbio, next_bio);
419
420
0
        BIO_set_next(bio, ssl_rbio);
421
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
422
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
423
        CRYPTO_add(&(ssl_rbio->references), 1, CRYPTO_LOCK_BIO);
424
#else
425
0
        BIO_up_ref(ssl_rbio);
426
0
#endif
427
0
      }
428
429
0
      BIO_set_init(bio, 1);
430
0
      status = 1;
431
0
      break;
432
433
0
    case BIO_C_DO_STATE_MACHINE:
434
0
      BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL);
435
0
      BIO_set_retry_reason(bio, 0);
436
0
      status = SSL_do_handshake(tls->ssl);
437
438
0
      if (status <= 0)
439
0
      {
440
0
        switch (SSL_get_error(tls->ssl, status))
441
0
        {
442
0
          case SSL_ERROR_WANT_READ:
443
0
            BIO_set_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
444
0
            break;
445
446
0
          case SSL_ERROR_WANT_WRITE:
447
0
            BIO_set_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
448
0
            break;
449
450
0
          case SSL_ERROR_WANT_CONNECT:
451
0
            BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY);
452
0
            BIO_set_retry_reason(bio, BIO_get_retry_reason(next_bio));
453
0
            break;
454
455
0
          default:
456
0
            BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
457
0
            break;
458
0
        }
459
0
      }
460
461
0
      break;
462
463
0
    default:
464
0
      status = BIO_ctrl(ssl_rbio, cmd, num, ptr);
465
0
      break;
466
0
  }
467
468
0
  return status;
469
0
}
470
471
static int bio_rdp_tls_new(BIO* bio)
472
0
{
473
0
  BIO_RDP_TLS* tls;
474
0
  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
475
476
0
  if (!(tls = calloc(1, sizeof(BIO_RDP_TLS))))
477
0
    return 0;
478
479
0
  InitializeCriticalSectionAndSpinCount(&tls->lock, 4000);
480
0
  BIO_set_data(bio, (void*)tls);
481
0
  return 1;
482
0
}
483
484
static int bio_rdp_tls_free(BIO* bio)
485
0
{
486
0
  BIO_RDP_TLS* tls;
487
488
0
  if (!bio)
489
0
    return 0;
490
491
0
  tls = (BIO_RDP_TLS*)BIO_get_data(bio);
492
493
0
  if (!tls)
494
0
    return 0;
495
496
0
  BIO_set_data(bio, NULL);
497
0
  if (BIO_get_shutdown(bio))
498
0
  {
499
0
    if (BIO_get_init(bio) && tls->ssl)
500
0
    {
501
0
      SSL_shutdown(tls->ssl);
502
0
      SSL_free(tls->ssl);
503
0
    }
504
505
0
    BIO_set_init(bio, 0);
506
0
    BIO_set_flags(bio, 0);
507
0
  }
508
509
0
  DeleteCriticalSection(&tls->lock);
510
0
  free(tls);
511
512
0
  return 1;
513
0
}
514
515
static long bio_rdp_tls_callback_ctrl(BIO* bio, int cmd, bio_info_cb* fp)
516
0
{
517
0
  long status = 0;
518
0
  BIO_RDP_TLS* tls;
519
520
0
  if (!bio)
521
0
    return 0;
522
523
0
  tls = (BIO_RDP_TLS*)BIO_get_data(bio);
524
525
0
  if (!tls)
526
0
    return 0;
527
528
0
  switch (cmd)
529
0
  {
530
0
    case BIO_CTRL_SET_CALLBACK:
531
0
    {
532
0
      typedef void (*fkt_t)(const SSL*, int, int);
533
      /* Documented since https://www.openssl.org/docs/man1.1.1/man3/BIO_set_callback.html
534
       * the argument is not really of type bio_info_cb* and must be cast
535
       * to the required type */
536
0
      fkt_t fkt = (fkt_t)(void*)fp;
537
0
      SSL_set_info_callback(tls->ssl, fkt);
538
0
      status = 1;
539
0
    }
540
0
    break;
541
542
0
    default:
543
0
      status = BIO_callback_ctrl(SSL_get_rbio(tls->ssl), cmd, fp);
544
0
      break;
545
0
  }
546
547
0
  return status;
548
0
}
549
550
0
#define BIO_TYPE_RDP_TLS 68
551
552
static BIO_METHOD* BIO_s_rdp_tls(void)
553
0
{
554
0
  static BIO_METHOD* bio_methods = NULL;
555
556
0
  if (bio_methods == NULL)
557
0
  {
558
0
    if (!(bio_methods = BIO_meth_new(BIO_TYPE_RDP_TLS, "RdpTls")))
559
0
      return NULL;
560
561
0
    BIO_meth_set_write(bio_methods, bio_rdp_tls_write);
562
0
    BIO_meth_set_read(bio_methods, bio_rdp_tls_read);
563
0
    BIO_meth_set_puts(bio_methods, bio_rdp_tls_puts);
564
0
    BIO_meth_set_gets(bio_methods, bio_rdp_tls_gets);
565
0
    BIO_meth_set_ctrl(bio_methods, bio_rdp_tls_ctrl);
566
0
    BIO_meth_set_create(bio_methods, bio_rdp_tls_new);
567
0
    BIO_meth_set_destroy(bio_methods, bio_rdp_tls_free);
568
0
    BIO_meth_set_callback_ctrl(bio_methods, bio_rdp_tls_callback_ctrl);
569
0
  }
570
571
0
  return bio_methods;
572
0
}
573
574
static BIO* BIO_new_rdp_tls(SSL_CTX* ctx, int client)
575
0
{
576
0
  BIO* bio;
577
0
  SSL* ssl;
578
0
  bio = BIO_new(BIO_s_rdp_tls());
579
580
0
  if (!bio)
581
0
    return NULL;
582
583
0
  ssl = SSL_new(ctx);
584
585
0
  if (!ssl)
586
0
  {
587
0
    BIO_free_all(bio);
588
0
    return NULL;
589
0
  }
590
591
0
  if (client)
592
0
    SSL_set_connect_state(ssl);
593
0
  else
594
0
    SSL_set_accept_state(ssl);
595
596
0
  BIO_set_ssl(bio, ssl, BIO_CLOSE);
597
0
  return bio;
598
0
}
599
600
static rdpCertificate* tls_get_certificate(rdpTls* tls, BOOL peer)
601
0
{
602
0
  X509* remote_cert;
603
604
0
  if (peer)
605
0
    remote_cert = SSL_get_peer_certificate(tls->ssl);
606
0
  else
607
0
    remote_cert = X509_dup(SSL_get_certificate(tls->ssl));
608
609
0
  if (!remote_cert)
610
0
  {
611
0
    WLog_ERR(TAG, "failed to get the server TLS certificate");
612
0
    return NULL;
613
0
  }
614
615
  /* Get the peer's chain. If it does not exist, we're setting NULL (clean data either way) */
616
0
  STACK_OF(X509)* chain = SSL_get_peer_cert_chain(tls->ssl);
617
0
  rdpCertificate* cert = freerdp_certificate_new_from_x509(remote_cert, chain);
618
0
  X509_free(remote_cert);
619
620
0
  return cert;
621
0
}
622
623
static const char* tls_get_server_name(rdpTls* tls)
624
0
{
625
0
  return tls->serverName ? tls->serverName : tls->hostname;
626
0
}
627
628
0
#define TLS_SERVER_END_POINT "tls-server-end-point:"
629
630
static SecPkgContext_Bindings* tls_get_channel_bindings(const rdpCertificate* cert)
631
0
{
632
0
  size_t CertificateHashLength = 0;
633
0
  BYTE* ChannelBindingToken = NULL;
634
0
  UINT32 ChannelBindingTokenLength = 0;
635
0
  SEC_CHANNEL_BINDINGS* ChannelBindings = NULL;
636
0
  SecPkgContext_Bindings* ContextBindings = NULL;
637
0
  const size_t PrefixLength = strnlen(TLS_SERVER_END_POINT, ARRAYSIZE(TLS_SERVER_END_POINT));
638
639
0
  WINPR_ASSERT(cert);
640
641
  /* See https://www.rfc-editor.org/rfc/rfc5929 for details about hashes */
642
0
  WINPR_MD_TYPE alg = freerdp_certificate_get_signature_alg(cert);
643
0
  const char* hash;
644
0
  switch (alg)
645
0
  {
646
647
0
    case WINPR_MD_MD5:
648
0
    case WINPR_MD_SHA1:
649
0
      hash = winpr_md_type_to_string(WINPR_MD_SHA256);
650
0
      break;
651
0
    default:
652
0
      hash = winpr_md_type_to_string(alg);
653
0
      break;
654
0
  }
655
0
  if (!hash)
656
0
    return NULL;
657
658
0
  char* CertificateHash = freerdp_certificate_get_hash(cert, hash, &CertificateHashLength);
659
0
  if (!CertificateHash)
660
0
    return NULL;
661
662
0
  ChannelBindingTokenLength = PrefixLength + CertificateHashLength;
663
0
  ContextBindings = (SecPkgContext_Bindings*)calloc(1, sizeof(SecPkgContext_Bindings));
664
665
0
  if (!ContextBindings)
666
0
    goto out_free;
667
668
0
  ContextBindings->BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) + ChannelBindingTokenLength;
669
0
  ChannelBindings = (SEC_CHANNEL_BINDINGS*)calloc(1, ContextBindings->BindingsLength);
670
671
0
  if (!ChannelBindings)
672
0
    goto out_free;
673
674
0
  ContextBindings->Bindings = ChannelBindings;
675
0
  ChannelBindings->cbApplicationDataLength = ChannelBindingTokenLength;
676
0
  ChannelBindings->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS);
677
0
  ChannelBindingToken = &((BYTE*)ChannelBindings)[ChannelBindings->dwApplicationDataOffset];
678
0
  memcpy(ChannelBindingToken, TLS_SERVER_END_POINT, PrefixLength);
679
0
  memcpy(ChannelBindingToken + PrefixLength, CertificateHash, CertificateHashLength);
680
0
  free(CertificateHash);
681
0
  return ContextBindings;
682
0
out_free:
683
0
  free(CertificateHash);
684
0
  free(ContextBindings);
685
0
  return NULL;
686
0
}
687
688
static INIT_ONCE secrets_file_idx_once = INIT_ONCE_STATIC_INIT;
689
static int secrets_file_idx = -1;
690
691
static BOOL CALLBACK secrets_file_init_cb(PINIT_ONCE once, PVOID param, PVOID* context)
692
0
{
693
0
  secrets_file_idx = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
694
695
0
  return (secrets_file_idx != -1);
696
0
}
697
698
static void SSLCTX_keylog_cb(const SSL* ssl, const char* line)
699
0
{
700
0
  char* dfile;
701
702
0
  if (secrets_file_idx == -1)
703
0
    return;
704
705
0
  dfile = SSL_get_ex_data(ssl, secrets_file_idx);
706
0
  if (dfile)
707
0
  {
708
0
    FILE* f = winpr_fopen(dfile, "a+");
709
0
    if (f)
710
0
    {
711
0
      fwrite(line, strlen(line), 1, f);
712
0
      fwrite("\n", 1, 1, f);
713
0
      fclose(f);
714
0
    }
715
0
  }
716
0
}
717
718
static void tls_reset(rdpTls* tls)
719
0
{
720
0
  WINPR_ASSERT(tls);
721
722
0
  if (tls->ctx)
723
0
  {
724
0
    SSL_CTX_free(tls->ctx);
725
0
    tls->ctx = NULL;
726
0
  }
727
728
  /* tls->underlying is a stacked BIO under tls->bio.
729
   * BIO_free_all will free recursivly. */
730
0
  if (tls->bio)
731
0
    BIO_free_all(tls->bio);
732
0
  else if (tls->underlying)
733
0
    BIO_free_all(tls->underlying);
734
0
  tls->bio = NULL;
735
0
  tls->underlying = NULL;
736
737
0
  free_tls_public_key(tls);
738
0
  free_tls_bindings(tls);
739
0
}
740
741
#if OPENSSL_VERSION_NUMBER >= 0x010000000L
742
static BOOL tls_prepare(rdpTls* tls, BIO* underlying, const SSL_METHOD* method, int options,
743
                        BOOL clientMode)
744
#else
745
static BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method, int options,
746
                        BOOL clientMode)
747
#endif
748
0
{
749
0
  WINPR_ASSERT(tls);
750
751
0
  rdpSettings* settings = tls->settings;
752
0
  WINPR_ASSERT(settings);
753
754
0
  tls_reset(tls);
755
0
  tls->ctx = SSL_CTX_new(method);
756
757
0
  tls->underlying = underlying;
758
759
0
  if (!tls->ctx)
760
0
  {
761
0
    WLog_ERR(TAG, "SSL_CTX_new failed");
762
0
    return FALSE;
763
0
  }
764
765
0
  SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
766
0
  SSL_CTX_set_options(tls->ctx, options);
767
0
  SSL_CTX_set_read_ahead(tls->ctx, 1);
768
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
769
0
  UINT16 version = freerdp_settings_get_uint16(settings, FreeRDP_TLSMinVersion);
770
0
  if (!SSL_CTX_set_min_proto_version(tls->ctx, version))
771
0
  {
772
0
    WLog_ERR(TAG, "SSL_CTX_set_min_proto_version %s failed", version);
773
0
    return FALSE;
774
0
  }
775
0
  version = freerdp_settings_get_uint16(settings, FreeRDP_TLSMaxVersion);
776
0
  if (!SSL_CTX_set_max_proto_version(tls->ctx, version))
777
0
  {
778
0
    WLog_ERR(TAG, "SSL_CTX_set_max_proto_version %s failed", version);
779
0
    return FALSE;
780
0
  }
781
0
#endif
782
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
783
0
  SSL_CTX_set_security_level(tls->ctx, settings->TlsSecLevel);
784
0
#endif
785
786
0
  if (settings->AllowedTlsCiphers)
787
0
  {
788
0
    if (!SSL_CTX_set_cipher_list(tls->ctx, settings->AllowedTlsCiphers))
789
0
    {
790
0
      WLog_ERR(TAG, "SSL_CTX_set_cipher_list %s failed", settings->AllowedTlsCiphers);
791
0
      return FALSE;
792
0
    }
793
0
  }
794
795
0
  tls->bio = BIO_new_rdp_tls(tls->ctx, clientMode);
796
797
0
  if (BIO_get_ssl(tls->bio, &tls->ssl) < 0)
798
0
  {
799
0
    WLog_ERR(TAG, "unable to retrieve the SSL of the connection");
800
0
    return FALSE;
801
0
  }
802
803
0
  if (settings->TlsSecretsFile)
804
0
  {
805
0
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
806
0
    InitOnceExecuteOnce(&secrets_file_idx_once, secrets_file_init_cb, NULL, NULL);
807
808
0
    if (secrets_file_idx != -1)
809
0
    {
810
0
      SSL_set_ex_data(tls->ssl, secrets_file_idx, settings->TlsSecretsFile);
811
0
      SSL_CTX_set_keylog_callback(tls->ctx, SSLCTX_keylog_cb);
812
0
    }
813
#else
814
    WLog_WARN(TAG, "Key-Logging not available - requires OpenSSL 1.1.1 or higher");
815
#endif
816
0
  }
817
818
0
  BIO_push(tls->bio, underlying);
819
0
  return TRUE;
820
0
}
821
822
static void adjustSslOptions(int* options)
823
0
{
824
0
  WINPR_ASSERT(options);
825
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
826
  *options |= SSL_OP_NO_SSLv2;
827
  *options |= SSL_OP_NO_SSLv3;
828
#endif
829
0
}
830
831
const SSL_METHOD* freerdp_tls_get_ssl_method(BOOL isDtls, BOOL isClient)
832
0
{
833
0
  if (isClient)
834
0
  {
835
0
    if (isDtls)
836
0
      return (const SSL_METHOD*)DTLS_client_method();
837
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
838
    return (const SSL_METHOD*)SSLv23_client_method();
839
#else
840
0
    return (const SSL_METHOD*)TLS_client_method();
841
0
#endif
842
0
  }
843
844
0
  if (isDtls)
845
0
    return (const SSL_METHOD*)DTLS_server_method();
846
847
0
  return (const SSL_METHOD*)SSLv23_server_method();
848
0
}
849
850
TlsHandshakeResult freerdp_tls_connect_ex(rdpTls* tls, BIO* underlying, const SSL_METHOD* methods)
851
0
{
852
0
  WINPR_ASSERT(tls);
853
854
0
  int options = 0;
855
  /**
856
   * SSL_OP_NO_COMPRESSION:
857
   *
858
   * The Microsoft RDP server does not advertise support
859
   * for TLS compression, but alternative servers may support it.
860
   * This was observed between early versions of the FreeRDP server
861
   * and the FreeRDP client, and caused major performance issues,
862
   * which is why we're disabling it.
863
   */
864
0
#ifdef SSL_OP_NO_COMPRESSION
865
0
  options |= SSL_OP_NO_COMPRESSION;
866
0
#endif
867
  /**
868
   * SSL_OP_TLS_BLOCK_PADDING_BUG:
869
   *
870
   * The Microsoft RDP server does *not* support TLS padding.
871
   * It absolutely needs to be disabled otherwise it won't work.
872
   */
873
0
  options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
874
  /**
875
   * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
876
   *
877
   * Just like TLS padding, the Microsoft RDP server does not
878
   * support empty fragments. This needs to be disabled.
879
   */
880
0
  options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
881
882
0
  tls->isClientMode = TRUE;
883
0
  adjustSslOptions(&options);
884
885
0
  if (!tls_prepare(tls, underlying, methods, options, TRUE))
886
0
    return 0;
887
888
0
#if !defined(OPENSSL_NO_TLSEXT) && !defined(LIBRESSL_VERSION_NUMBER)
889
0
  SSL_set_tlsext_host_name(tls->ssl, tls_get_server_name(tls));
890
0
#endif
891
892
0
  return freerdp_tls_handshake(tls);
893
0
}
894
895
TlsHandshakeResult freerdp_tls_handshake(rdpTls* tls)
896
0
{
897
0
  TlsHandshakeResult ret = TLS_HANDSHAKE_ERROR;
898
899
0
  WINPR_ASSERT(tls);
900
0
  int status = BIO_do_handshake(tls->bio);
901
0
  if (status != 1)
902
0
  {
903
0
    if (!BIO_should_retry(tls->bio))
904
0
      return TLS_HANDSHAKE_ERROR;
905
906
0
    return TLS_HANDSHAKE_CONTINUE;
907
0
  }
908
909
0
  int verify_status;
910
0
  rdpCertificate* cert = tls_get_certificate(tls, tls->isClientMode);
911
912
0
  if (!cert)
913
0
  {
914
0
    WLog_ERR(TAG, "tls_get_certificate failed to return the server certificate.");
915
0
    return TLS_HANDSHAKE_ERROR;
916
0
  }
917
918
0
  do
919
0
  {
920
0
    free_tls_bindings(tls);
921
0
    tls->Bindings = tls_get_channel_bindings(cert);
922
0
    if (!tls->Bindings)
923
0
    {
924
0
      WLog_ERR(TAG, "unable to retrieve bindings");
925
0
      break;
926
0
    }
927
928
0
    free_tls_public_key(tls);
929
0
    if (!freerdp_certificate_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
930
0
    {
931
0
      WLog_ERR(TAG,
932
0
               "freerdp_certificate_get_public_key failed to return the server public key.");
933
0
      break;
934
0
    }
935
936
    /* server-side NLA needs public keys (keys from us, the server) but no certificate verify */
937
0
    ret = TLS_HANDSHAKE_SUCCESS;
938
939
0
    if (tls->isClientMode)
940
0
    {
941
0
      verify_status = tls_verify_certificate(tls, cert, tls_get_server_name(tls), tls->port);
942
943
0
      if (verify_status < 1)
944
0
      {
945
0
        WLog_ERR(TAG, "certificate not trusted, aborting.");
946
0
        freerdp_tls_send_alert(tls);
947
0
        ret = TLS_HANDSHAKE_VERIFY_ERROR;
948
0
      }
949
0
    }
950
0
  } while (0);
951
952
0
  freerdp_certificate_free(cert);
953
0
  return ret;
954
0
}
955
956
static int pollAndHandshake(rdpTls* tls)
957
0
{
958
0
  WINPR_ASSERT(tls);
959
960
0
  do
961
0
  {
962
0
    HANDLE event;
963
0
    DWORD status;
964
0
    if (BIO_get_event(tls->bio, &event) < 0)
965
0
    {
966
0
      WLog_ERR(TAG, "unable to retrieve BIO associated event");
967
0
      return -1;
968
0
    }
969
970
0
    if (!event)
971
0
    {
972
0
      WLog_ERR(TAG, "unable to retrieve BIO event");
973
0
      return -1;
974
0
    }
975
976
0
    status = WaitForSingleObjectEx(event, 50, TRUE);
977
0
    switch (status)
978
0
    {
979
0
      case WAIT_OBJECT_0:
980
0
        break;
981
0
      case WAIT_TIMEOUT:
982
0
        continue;
983
0
      default:
984
0
        WLog_ERR(TAG, "error during WaitForSingleObject(): 0x%08" PRIX32 "", status);
985
0
        return -1;
986
0
    }
987
988
0
    TlsHandshakeResult result = freerdp_tls_handshake(tls);
989
0
    switch (result)
990
0
    {
991
0
      case TLS_HANDSHAKE_CONTINUE:
992
0
        break;
993
0
      case TLS_HANDSHAKE_SUCCESS:
994
0
        return 1;
995
0
      case TLS_HANDSHAKE_ERROR:
996
0
      case TLS_HANDSHAKE_VERIFY_ERROR:
997
0
      default:
998
0
        return -1;
999
0
    }
1000
0
  } while (TRUE);
1001
0
}
1002
1003
int freerdp_tls_connect(rdpTls* tls, BIO* underlying)
1004
0
{
1005
0
  const SSL_METHOD* method = freerdp_tls_get_ssl_method(FALSE, TRUE);
1006
1007
0
  WINPR_ASSERT(tls);
1008
0
  TlsHandshakeResult result = freerdp_tls_connect_ex(tls, underlying, method);
1009
0
  switch (result)
1010
0
  {
1011
0
    case TLS_HANDSHAKE_SUCCESS:
1012
0
      return 1;
1013
0
    case TLS_HANDSHAKE_CONTINUE:
1014
0
      break;
1015
0
    case TLS_HANDSHAKE_ERROR:
1016
0
    case TLS_HANDSHAKE_VERIFY_ERROR:
1017
0
      return -1;
1018
0
  }
1019
1020
0
  return pollAndHandshake(tls);
1021
0
}
1022
1023
#if defined(MICROSOFT_IOS_SNI_BUG) && !defined(OPENSSL_NO_TLSEXT) && \
1024
    !defined(LIBRESSL_VERSION_NUMBER)
1025
static void tls_openssl_tlsext_debug_callback(SSL* s, int client_server, int type,
1026
                                              unsigned char* data, int len, void* arg)
1027
{
1028
  if (type == TLSEXT_TYPE_server_name)
1029
  {
1030
    WLog_DBG(TAG, "Client uses SNI (extension disabled)");
1031
    s->servername_done = 2;
1032
  }
1033
}
1034
#endif
1035
1036
BOOL freerdp_tls_accept(rdpTls* tls, BIO* underlying, rdpSettings* settings)
1037
0
{
1038
0
  WINPR_ASSERT(tls);
1039
0
  TlsHandshakeResult res =
1040
0
      freerdp_tls_accept_ex(tls, underlying, settings, freerdp_tls_get_ssl_method(FALSE, FALSE));
1041
0
  switch (res)
1042
0
  {
1043
0
    case TLS_HANDSHAKE_SUCCESS:
1044
0
      return TRUE;
1045
0
    case TLS_HANDSHAKE_CONTINUE:
1046
0
      break;
1047
0
    case TLS_HANDSHAKE_ERROR:
1048
0
    case TLS_HANDSHAKE_VERIFY_ERROR:
1049
0
    default:
1050
0
      return FALSE;
1051
0
  }
1052
1053
0
  return pollAndHandshake(tls) > 0;
1054
0
}
1055
1056
TlsHandshakeResult freerdp_tls_accept_ex(rdpTls* tls, BIO* underlying, rdpSettings* settings,
1057
                                         const SSL_METHOD* methods)
1058
0
{
1059
0
  WINPR_ASSERT(tls);
1060
1061
0
  long options = 0;
1062
0
  int status;
1063
1064
  /**
1065
   * SSL_OP_NO_SSLv2:
1066
   *
1067
   * We only want SSLv3 and TLSv1, so disable SSLv2.
1068
   * SSLv3 is used by, eg. Microsoft RDC for Mac OS X.
1069
   */
1070
0
  options |= SSL_OP_NO_SSLv2;
1071
  /**
1072
   * SSL_OP_NO_COMPRESSION:
1073
   *
1074
   * The Microsoft RDP server does not advertise support
1075
   * for TLS compression, but alternative servers may support it.
1076
   * This was observed between early versions of the FreeRDP server
1077
   * and the FreeRDP client, and caused major performance issues,
1078
   * which is why we're disabling it.
1079
   */
1080
0
#ifdef SSL_OP_NO_COMPRESSION
1081
0
  options |= SSL_OP_NO_COMPRESSION;
1082
0
#endif
1083
  /**
1084
   * SSL_OP_TLS_BLOCK_PADDING_BUG:
1085
   *
1086
   * The Microsoft RDP server does *not* support TLS padding.
1087
   * It absolutely needs to be disabled otherwise it won't work.
1088
   */
1089
0
  options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
1090
  /**
1091
   * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
1092
   *
1093
   * Just like TLS padding, the Microsoft RDP server does not
1094
   * support empty fragments. This needs to be disabled.
1095
   */
1096
0
  options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
1097
1098
  /**
1099
   * SSL_OP_NO_RENEGOTIATION
1100
   *
1101
   * Disable SSL client site renegotiation.
1102
   */
1103
1104
0
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && OPENSSL_VERSION_NUMBER < 0x30000000L) || \
1105
0
    defined(LIBRESSL_VERSION_NUMBER)
1106
0
  options |= SSL_OP_NO_RENEGOTIATION;
1107
0
#endif
1108
1109
0
  if (!tls_prepare(tls, underlying, methods, options, FALSE))
1110
0
    return TLS_HANDSHAKE_ERROR;
1111
1112
0
  const rdpPrivateKey* key = freerdp_settings_get_pointer(settings, FreeRDP_RdpServerRsaKey);
1113
0
  if (!key)
1114
0
  {
1115
0
    WLog_ERR(TAG, "invalid private key");
1116
0
    return TLS_HANDSHAKE_ERROR;
1117
0
  }
1118
1119
0
  EVP_PKEY* privkey = freerdp_key_get_evp_pkey(key);
1120
0
  if (!privkey)
1121
0
  {
1122
0
    WLog_ERR(TAG, "invalid private key");
1123
0
    return TLS_HANDSHAKE_ERROR;
1124
0
  }
1125
1126
0
  status = SSL_use_PrivateKey(tls->ssl, privkey);
1127
  /* The local reference to the private key will anyway go out of
1128
   * scope; so the reference count should be decremented weither
1129
   * SSL_use_PrivateKey succeeds or fails.
1130
   */
1131
0
  EVP_PKEY_free(privkey);
1132
1133
0
  if (status <= 0)
1134
0
  {
1135
0
    WLog_ERR(TAG, "SSL_CTX_use_PrivateKey_file failed");
1136
0
    return TLS_HANDSHAKE_ERROR;
1137
0
  }
1138
1139
0
  rdpCertificate* cert =
1140
0
      freerdp_settings_get_pointer_writable(settings, FreeRDP_RdpServerCertificate);
1141
0
  if (!cert)
1142
0
  {
1143
0
    WLog_ERR(TAG, "invalid certificate");
1144
0
    return TLS_HANDSHAKE_ERROR;
1145
0
  }
1146
1147
0
  status = SSL_use_certificate(tls->ssl, freerdp_certificate_get_x509(cert));
1148
1149
0
  if (status <= 0)
1150
0
  {
1151
0
    WLog_ERR(TAG, "SSL_use_certificate_file failed");
1152
0
    return TLS_HANDSHAKE_ERROR;
1153
0
  }
1154
1155
#if defined(MICROSOFT_IOS_SNI_BUG) && !defined(OPENSSL_NO_TLSEXT) && \
1156
    !defined(LIBRESSL_VERSION_NUMBER)
1157
  SSL_set_tlsext_debug_callback(tls->ssl, tls_openssl_tlsext_debug_callback);
1158
#endif
1159
1160
0
  return freerdp_tls_handshake(tls);
1161
0
}
1162
1163
BOOL freerdp_tls_send_alert(rdpTls* tls)
1164
0
{
1165
0
  WINPR_ASSERT(tls);
1166
1167
0
  if (!tls)
1168
0
    return FALSE;
1169
1170
0
  if (!tls->ssl)
1171
0
    return TRUE;
1172
1173
    /**
1174
     * FIXME: The following code does not work on OpenSSL > 1.1.0 because the
1175
     *        SSL struct is opaqe now
1176
     */
1177
#if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x10100000L)) || \
1178
    (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER <= 0x2080300fL))
1179
1180
  if (tls->alertDescription != TLS_ALERT_DESCRIPTION_CLOSE_NOTIFY)
1181
  {
1182
    /**
1183
     * OpenSSL doesn't really expose an API for sending a TLS alert manually.
1184
     *
1185
     * The following code disables the sending of the default "close notify"
1186
     * and then proceeds to force sending a custom TLS alert before shutting down.
1187
     *
1188
     * Manually sending a TLS alert is necessary in certain cases,
1189
     * like when server-side NLA results in an authentication failure.
1190
     */
1191
    SSL_SESSION* ssl_session = SSL_get_session(tls->ssl);
1192
    SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(tls->ssl);
1193
    SSL_set_quiet_shutdown(tls->ssl, 1);
1194
1195
    if ((tls->alertLevel == TLS_ALERT_LEVEL_FATAL) && (ssl_session))
1196
      SSL_CTX_remove_session(ssl_ctx, ssl_session);
1197
1198
    tls->ssl->s3->alert_dispatch = 1;
1199
    tls->ssl->s3->send_alert[0] = tls->alertLevel;
1200
    tls->ssl->s3->send_alert[1] = tls->alertDescription;
1201
1202
    if (tls->ssl->s3->wbuf.left == 0)
1203
      tls->ssl->method->ssl_dispatch_alert(tls->ssl);
1204
  }
1205
1206
#endif
1207
0
  return TRUE;
1208
0
}
1209
1210
int freerdp_tls_write_all(rdpTls* tls, const BYTE* data, int length)
1211
0
{
1212
0
  WINPR_ASSERT(tls);
1213
0
  int status;
1214
0
  int offset = 0;
1215
0
  BIO* bio = tls->bio;
1216
1217
0
  while (offset < length)
1218
0
  {
1219
0
    ERR_clear_error();
1220
0
    status = BIO_write(bio, &data[offset], length - offset);
1221
1222
0
    if (status > 0)
1223
0
    {
1224
0
      offset += status;
1225
0
    }
1226
0
    else
1227
0
    {
1228
0
      if (!BIO_should_retry(bio))
1229
0
        return -1;
1230
1231
0
      if (BIO_write_blocked(bio))
1232
0
        status = BIO_wait_write(bio, 100);
1233
0
      else if (BIO_read_blocked(bio))
1234
0
        return -2; /* Abort write, there is data that must be read */
1235
0
      else
1236
0
        USleep(100);
1237
1238
0
      if (status < 0)
1239
0
        return -1;
1240
0
    }
1241
0
  }
1242
1243
0
  return length;
1244
0
}
1245
1246
int freerdp_tls_set_alert_code(rdpTls* tls, int level, int description)
1247
0
{
1248
0
  WINPR_ASSERT(tls);
1249
0
  tls->alertLevel = level;
1250
0
  tls->alertDescription = description;
1251
0
  return 0;
1252
0
}
1253
1254
static BOOL tls_match_hostname(const char* pattern, const size_t pattern_length,
1255
                               const char* hostname)
1256
0
{
1257
0
  if (strlen(hostname) == pattern_length)
1258
0
  {
1259
0
    if (_strnicmp(hostname, pattern, pattern_length) == 0)
1260
0
      return TRUE;
1261
0
  }
1262
1263
0
  if ((pattern_length > 2) && (pattern[0] == '*') && (pattern[1] == '.') &&
1264
0
      ((strlen(hostname)) >= pattern_length))
1265
0
  {
1266
0
    const char* check_hostname = &hostname[strlen(hostname) - pattern_length + 1];
1267
1268
0
    if (_strnicmp(check_hostname, &pattern[1], pattern_length - 1) == 0)
1269
0
    {
1270
0
      return TRUE;
1271
0
    }
1272
0
  }
1273
1274
0
  return FALSE;
1275
0
}
1276
1277
static BOOL is_redirected(rdpTls* tls)
1278
0
{
1279
0
  rdpSettings* settings = tls->settings;
1280
1281
0
  if (LB_NOREDIRECT & settings->RedirectionFlags)
1282
0
    return FALSE;
1283
1284
0
  return settings->RedirectionFlags != 0;
1285
0
}
1286
1287
static BOOL is_accepted(rdpTls* tls, const BYTE* pem, size_t length)
1288
0
{
1289
0
  rdpSettings* settings = tls->settings;
1290
0
  char* AccpetedKey;
1291
0
  UINT32 AcceptedKeyLength;
1292
1293
0
  if (tls->isGatewayTransport)
1294
0
  {
1295
0
    AccpetedKey = settings->GatewayAcceptedCert;
1296
0
    AcceptedKeyLength = settings->GatewayAcceptedCertLength;
1297
0
  }
1298
0
  else if (is_redirected(tls))
1299
0
  {
1300
0
    AccpetedKey = settings->RedirectionAcceptedCert;
1301
0
    AcceptedKeyLength = settings->RedirectionAcceptedCertLength;
1302
0
  }
1303
0
  else
1304
0
  {
1305
0
    AccpetedKey = settings->AcceptedCert;
1306
0
    AcceptedKeyLength = settings->AcceptedCertLength;
1307
0
  }
1308
1309
0
  if (AcceptedKeyLength > 0)
1310
0
  {
1311
0
    if (AcceptedKeyLength == length)
1312
0
    {
1313
0
      if (memcmp(AccpetedKey, pem, AcceptedKeyLength) == 0)
1314
0
        return TRUE;
1315
0
    }
1316
0
  }
1317
1318
0
  if (tls->isGatewayTransport)
1319
0
  {
1320
0
    free(settings->GatewayAcceptedCert);
1321
0
    settings->GatewayAcceptedCert = NULL;
1322
0
    settings->GatewayAcceptedCertLength = 0;
1323
0
  }
1324
0
  else if (is_redirected(tls))
1325
0
  {
1326
0
    free(settings->RedirectionAcceptedCert);
1327
0
    settings->RedirectionAcceptedCert = NULL;
1328
0
    settings->RedirectionAcceptedCertLength = 0;
1329
0
  }
1330
0
  else
1331
0
  {
1332
0
    free(settings->AcceptedCert);
1333
0
    settings->AcceptedCert = NULL;
1334
0
    settings->AcceptedCertLength = 0;
1335
0
  }
1336
1337
0
  return FALSE;
1338
0
}
1339
1340
static BOOL compare_fingerprint(const char* fp, const char* hash, const rdpCertificate* cert,
1341
                                BOOL separator)
1342
0
{
1343
0
  BOOL equal;
1344
0
  char* strhash;
1345
1346
0
  WINPR_ASSERT(fp);
1347
0
  WINPR_ASSERT(hash);
1348
0
  WINPR_ASSERT(cert);
1349
1350
0
  strhash = freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, separator);
1351
0
  if (!strhash)
1352
0
    return FALSE;
1353
1354
0
  equal = (_stricmp(strhash, fp) == 0);
1355
0
  free(strhash);
1356
0
  return equal;
1357
0
}
1358
1359
static BOOL compare_fingerprint_all(const char* fp, const char* hash, const rdpCertificate* cert)
1360
0
{
1361
0
  WINPR_ASSERT(fp);
1362
0
  WINPR_ASSERT(hash);
1363
0
  WINPR_ASSERT(cert);
1364
0
  if (compare_fingerprint(fp, hash, cert, FALSE))
1365
0
    return TRUE;
1366
0
  if (compare_fingerprint(fp, hash, cert, TRUE))
1367
0
    return TRUE;
1368
0
  return FALSE;
1369
0
}
1370
1371
static BOOL is_accepted_fingerprint(const rdpCertificate* cert,
1372
                                    const char* CertificateAcceptedFingerprints)
1373
0
{
1374
0
  WINPR_ASSERT(cert);
1375
1376
0
  BOOL rc = FALSE;
1377
0
  if (CertificateAcceptedFingerprints)
1378
0
  {
1379
0
    char* context = NULL;
1380
0
    char* copy = _strdup(CertificateAcceptedFingerprints);
1381
0
    char* cur = strtok_s(copy, ",", &context);
1382
0
    while (cur)
1383
0
    {
1384
0
      char* subcontext = NULL;
1385
0
      const char* h = strtok_s(cur, ":", &subcontext);
1386
0
      const char* fp;
1387
1388
0
      if (!h)
1389
0
        goto next;
1390
1391
0
      fp = h + strlen(h) + 1;
1392
0
      if (!fp)
1393
0
        goto next;
1394
1395
0
      if (compare_fingerprint_all(fp, h, cert))
1396
0
      {
1397
0
        rc = TRUE;
1398
0
        break;
1399
0
      }
1400
0
    next:
1401
0
      cur = strtok_s(NULL, ",", &context);
1402
0
    }
1403
0
    free(copy);
1404
0
  }
1405
1406
0
  return rc;
1407
0
}
1408
1409
static BOOL accept_cert(rdpTls* tls, const BYTE* pem, UINT32 length)
1410
0
{
1411
0
  WINPR_ASSERT(tls);
1412
0
  size_t id = FreeRDP_AcceptedCert;
1413
0
  size_t lid = FreeRDP_AcceptedCertLength;
1414
1415
0
  rdpSettings* settings = tls->settings;
1416
1417
0
  if (tls->isGatewayTransport)
1418
0
  {
1419
0
    id = FreeRDP_GatewayAcceptedCert;
1420
0
    lid = FreeRDP_GatewayAcceptedCertLength;
1421
0
  }
1422
0
  else if (is_redirected(tls))
1423
0
  {
1424
0
    id = FreeRDP_RedirectionAcceptedCert;
1425
0
    lid = FreeRDP_RedirectionAcceptedCertLength;
1426
0
  }
1427
1428
0
  if (!freerdp_settings_set_string_len(settings, id, (const char*)pem, length))
1429
0
    return FALSE;
1430
1431
0
  return freerdp_settings_set_uint32(settings, lid, length);
1432
0
}
1433
1434
static BOOL tls_extract_pem(const rdpCertificate* cert, BYTE** PublicKey, size_t* PublicKeyLength)
1435
0
{
1436
0
  if (!cert || !PublicKey)
1437
0
    return FALSE;
1438
0
  *PublicKey = (BYTE*)freerdp_certificate_get_pem(cert, PublicKeyLength);
1439
0
  return *PublicKey != NULL;
1440
0
}
1441
1442
int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char* hostname,
1443
                           UINT16 port)
1444
0
{
1445
0
  int match;
1446
0
  size_t length;
1447
0
  BOOL certificate_status;
1448
0
  char* common_name = NULL;
1449
0
  size_t common_name_length = 0;
1450
0
  char** dns_names = 0;
1451
0
  size_t dns_names_count = 0;
1452
0
  size_t* dns_names_lengths = NULL;
1453
0
  int verification_status = -1;
1454
0
  BOOL hostname_match = FALSE;
1455
0
  rdpCertificateData* certificate_data = NULL;
1456
0
  BYTE* pemCert = NULL;
1457
0
  DWORD flags = VERIFY_CERT_FLAG_NONE;
1458
0
  freerdp* instance;
1459
1460
0
  WINPR_ASSERT(tls);
1461
0
  WINPR_ASSERT(tls->settings);
1462
1463
0
  instance = (freerdp*)tls->settings->instance;
1464
0
  WINPR_ASSERT(instance);
1465
1466
0
  if (freerdp_shall_disconnect_context(instance->context))
1467
0
    return -1;
1468
1469
0
  if (!tls_extract_pem(cert, &pemCert, &length))
1470
0
    goto end;
1471
1472
  /* Check, if we already accepted this key. */
1473
0
  if (is_accepted(tls, pemCert, length))
1474
0
  {
1475
0
    verification_status = 1;
1476
0
    goto end;
1477
0
  }
1478
1479
0
  if (is_accepted_fingerprint(cert, tls->settings->CertificateAcceptedFingerprints))
1480
0
  {
1481
0
    verification_status = 1;
1482
0
    goto end;
1483
0
  }
1484
1485
0
  if (tls->isGatewayTransport || is_redirected(tls))
1486
0
    flags |= VERIFY_CERT_FLAG_LEGACY;
1487
1488
0
  if (tls->isGatewayTransport)
1489
0
    flags |= VERIFY_CERT_FLAG_GATEWAY;
1490
1491
0
  if (is_redirected(tls))
1492
0
    flags |= VERIFY_CERT_FLAG_REDIRECT;
1493
1494
  /* Certificate management is done by the application */
1495
0
  if (tls->settings->ExternalCertificateManagement)
1496
0
  {
1497
0
    if (instance->VerifyX509Certificate)
1498
0
      verification_status =
1499
0
          instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, flags);
1500
0
    else
1501
0
      WLog_ERR(TAG, "No VerifyX509Certificate callback registered!");
1502
1503
0
    if (verification_status > 0)
1504
0
      accept_cert(tls, pemCert, length);
1505
0
    else if (verification_status < 0)
1506
0
    {
1507
0
      WLog_ERR(TAG, "VerifyX509Certificate failed: (length = %" PRIuz ") status: [%d] %s",
1508
0
               length, verification_status, pemCert);
1509
0
      goto end;
1510
0
    }
1511
0
  }
1512
  /* ignore certificate verification if user explicitly required it (discouraged) */
1513
0
  else if (tls->settings->IgnoreCertificate)
1514
0
    verification_status = 1; /* success! */
1515
0
  else if (!tls->isGatewayTransport && (tls->settings->AuthenticationLevel == 0))
1516
0
    verification_status = 1; /* success! */
1517
0
  else
1518
0
  {
1519
    /* if user explicitly specified a certificate name, use it instead of the hostname */
1520
0
    if (!tls->isGatewayTransport && tls->settings->CertificateName)
1521
0
      hostname = tls->settings->CertificateName;
1522
1523
    /* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */
1524
0
    certificate_status = freerdp_certificate_verify(
1525
0
        cert, freerdp_certificate_store_get_certs_path(tls->certificate_store));
1526
    /* verify certificate name match */
1527
0
    certificate_data = freerdp_certificate_data_new(hostname, port, cert);
1528
0
    if (!certificate_data)
1529
0
      goto end;
1530
    /* extra common name and alternative names */
1531
0
    common_name = freerdp_certificate_get_common_name(cert, &common_name_length);
1532
0
    dns_names = freerdp_certificate_get_dns_names(cert, &dns_names_count, &dns_names_lengths);
1533
1534
    /* compare against common name */
1535
1536
0
    if (common_name)
1537
0
    {
1538
0
      if (tls_match_hostname(common_name, common_name_length, hostname))
1539
0
        hostname_match = TRUE;
1540
0
    }
1541
1542
    /* compare against alternative names */
1543
1544
0
    if (dns_names)
1545
0
    {
1546
0
      for (size_t index = 0; index < dns_names_count; index++)
1547
0
      {
1548
0
        if (tls_match_hostname(dns_names[index], dns_names_lengths[index], hostname))
1549
0
        {
1550
0
          hostname_match = TRUE;
1551
0
          break;
1552
0
        }
1553
0
      }
1554
0
    }
1555
1556
    /* if the certificate is valid and the certificate name matches, verification succeeds
1557
     */
1558
0
    if (certificate_status && hostname_match)
1559
0
      verification_status = 1; /* success! */
1560
1561
0
    if (!hostname_match)
1562
0
      flags |= VERIFY_CERT_FLAG_MISMATCH;
1563
1564
    /* verification could not succeed with OpenSSL, use known_hosts file and prompt user for
1565
     * manual verification */
1566
0
    if (!certificate_status || !hostname_match)
1567
0
    {
1568
0
      DWORD accept_certificate = 0;
1569
0
      size_t pem_length = 0;
1570
0
      char* issuer = freerdp_certificate_get_issuer(cert);
1571
0
      char* subject = freerdp_certificate_get_subject(cert);
1572
0
      char* pem = freerdp_certificate_get_pem(cert, &pem_length);
1573
1574
0
      if (!pem)
1575
0
        goto end;
1576
1577
      /* search for matching entry in known_hosts file */
1578
0
      match =
1579
0
          freerdp_certificate_store_contains_data(tls->certificate_store, certificate_data);
1580
1581
0
      if (match == 1)
1582
0
      {
1583
        /* no entry was found in known_hosts file, prompt user for manual verification
1584
         */
1585
0
        if (!hostname_match)
1586
0
          tls_print_certificate_name_mismatch_error(hostname, port, common_name,
1587
0
                                                    dns_names, dns_names_count);
1588
1589
0
        tls_print_new_certificate_warn(tls->certificate_store, hostname, port, pem);
1590
1591
        /* Automatically accept certificate on first use */
1592
0
        if (tls->settings->AutoAcceptCertificate)
1593
0
        {
1594
0
          WLog_INFO(TAG, "No certificate stored, automatically accepting.");
1595
0
          accept_certificate = 1;
1596
0
        }
1597
0
        else if (tls->settings->AutoDenyCertificate)
1598
0
        {
1599
0
          WLog_INFO(TAG, "No certificate stored, automatically denying.");
1600
0
          accept_certificate = 0;
1601
0
        }
1602
0
        else if (instance->VerifyX509Certificate)
1603
0
        {
1604
0
          int rc = instance->VerifyX509Certificate(instance, pemCert, pem_length,
1605
0
                                                   hostname, port, flags);
1606
1607
0
          if (rc == 1)
1608
0
            accept_certificate = 1;
1609
0
          else if (rc > 1)
1610
0
            accept_certificate = 2;
1611
0
          else
1612
0
            accept_certificate = 0;
1613
0
        }
1614
0
        else if (instance->VerifyCertificateEx)
1615
0
        {
1616
0
          const BOOL use_pem = freerdp_settings_get_bool(
1617
0
              tls->settings, FreeRDP_CertificateCallbackPreferPEM);
1618
0
          char* fp = NULL;
1619
0
          DWORD cflags = flags;
1620
0
          if (use_pem)
1621
0
          {
1622
0
            cflags |= VERIFY_CERT_FLAG_FP_IS_PEM;
1623
0
            fp = pem;
1624
0
          }
1625
0
          else
1626
0
            fp = freerdp_certificate_get_fingerprint(cert);
1627
0
          accept_certificate = instance->VerifyCertificateEx(
1628
0
              instance, hostname, port, common_name, subject, issuer, fp, cflags);
1629
0
          if (!use_pem)
1630
0
            free(fp);
1631
0
        }
1632
#if defined(WITH_FREERDP_DEPRECATED)
1633
        else if (instance->VerifyCertificate)
1634
        {
1635
          char* fp = freerdp_certificate_get_fingerprint(cert);
1636
1637
          WLog_WARN(TAG, "The VerifyCertificate callback is deprecated, migrate your "
1638
                         "application to VerifyCertificateEx");
1639
          accept_certificate = instance->VerifyCertificate(instance, common_name, subject,
1640
                                                           issuer, fp, !hostname_match);
1641
          free(fp);
1642
        }
1643
#endif
1644
0
      }
1645
0
      else if (match == -1)
1646
0
      {
1647
0
        rdpCertificateData* stored_data =
1648
0
            freerdp_certificate_store_load_data(tls->certificate_store, hostname, port);
1649
        /* entry was found in known_hosts file, but fingerprint does not match. ask user
1650
         * to use it */
1651
0
        tls_print_certificate_error(tls->certificate_store, stored_data, hostname, port,
1652
0
                                    pem);
1653
1654
0
        if (!stored_data)
1655
0
          WLog_WARN(TAG, "Failed to get certificate entry for %s:%" PRIu16 "", hostname,
1656
0
                    port);
1657
1658
0
        if (tls->settings->AutoDenyCertificate)
1659
0
        {
1660
0
          WLog_INFO(TAG, "No certificate stored, automatically denying.");
1661
0
          accept_certificate = 0;
1662
0
        }
1663
0
        else if (instance->VerifyX509Certificate)
1664
0
        {
1665
0
          const int rc =
1666
0
              instance->VerifyX509Certificate(instance, pemCert, pem_length, hostname,
1667
0
                                              port, flags | VERIFY_CERT_FLAG_CHANGED);
1668
1669
0
          if (rc == 1)
1670
0
            accept_certificate = 1;
1671
0
          else if (rc > 1)
1672
0
            accept_certificate = 2;
1673
0
          else
1674
0
            accept_certificate = 0;
1675
0
        }
1676
0
        else if (instance->VerifyChangedCertificateEx)
1677
0
        {
1678
0
          DWORD cflags = flags | VERIFY_CERT_FLAG_CHANGED;
1679
0
          const char* old_subject = freerdp_certificate_data_get_subject(stored_data);
1680
0
          const char* old_issuer = freerdp_certificate_data_get_issuer(stored_data);
1681
0
          const char* old_fp = freerdp_certificate_data_get_fingerprint(stored_data);
1682
0
          const char* old_pem = freerdp_certificate_data_get_pem(stored_data);
1683
0
          const BOOL fpIsAllocated =
1684
0
              !old_pem || !freerdp_settings_get_bool(
1685
0
                              tls->settings, FreeRDP_CertificateCallbackPreferPEM);
1686
0
          char* fp;
1687
0
          if (!fpIsAllocated)
1688
0
          {
1689
0
            cflags |= VERIFY_CERT_FLAG_FP_IS_PEM;
1690
0
            fp = pem;
1691
0
            old_fp = old_pem;
1692
0
          }
1693
0
          else
1694
0
          {
1695
0
            fp = freerdp_certificate_get_fingerprint(cert);
1696
0
          }
1697
0
          accept_certificate = instance->VerifyChangedCertificateEx(
1698
0
              instance, hostname, port, common_name, subject, issuer, fp, old_subject,
1699
0
              old_issuer, old_fp, cflags);
1700
0
          if (fpIsAllocated)
1701
0
            free(fp);
1702
0
        }
1703
#if defined(WITH_FREERDP_DEPRECATED)
1704
        else if (instance->VerifyChangedCertificate)
1705
        {
1706
          char* fp = freerdp_certificate_get_fingerprint(cert);
1707
          const char* old_subject = freerdp_certificate_data_get_subject(stored_data);
1708
          const char* old_issuer = freerdp_certificate_data_get_issuer(stored_data);
1709
          const char* old_fingerprint =
1710
              freerdp_certificate_data_get_fingerprint(stored_data);
1711
1712
          WLog_WARN(TAG, "The VerifyChangedCertificate callback is deprecated, migrate "
1713
                         "your application to VerifyChangedCertificateEx");
1714
          accept_certificate = instance->VerifyChangedCertificate(
1715
              instance, common_name, subject, issuer, fp, old_subject, old_issuer,
1716
              old_fingerprint);
1717
          free(fp);
1718
        }
1719
#endif
1720
1721
0
        freerdp_certificate_data_free(stored_data);
1722
0
      }
1723
0
      else if (match == 0)
1724
0
        accept_certificate = 2; /* success! */
1725
1726
      /* Save certificate or do a simple accept / reject */
1727
0
      switch (accept_certificate)
1728
0
      {
1729
0
        case 1:
1730
1731
          /* user accepted certificate, add entry in known_hosts file */
1732
0
          verification_status = freerdp_certificate_store_save_data(
1733
0
                                    tls->certificate_store, certificate_data)
1734
0
                                    ? 1
1735
0
                                    : -1;
1736
0
          break;
1737
1738
0
        case 2:
1739
          /* user did accept temporaty, do not add to known hosts file */
1740
0
          verification_status = 1;
1741
0
          break;
1742
1743
0
        default:
1744
          /* user did not accept, abort and do not add entry in known_hosts file */
1745
0
          verification_status = -1; /* failure! */
1746
0
          break;
1747
0
      }
1748
1749
0
      free(issuer);
1750
0
      free(subject);
1751
0
      free(pem);
1752
0
    }
1753
1754
0
    if (verification_status > 0)
1755
0
      accept_cert(tls, pemCert, length);
1756
0
  }
1757
1758
0
end:
1759
0
  freerdp_certificate_data_free(certificate_data);
1760
0
  free(common_name);
1761
0
  freerdp_certificate_free_dns_names(dns_names_count, dns_names_lengths, dns_names);
1762
0
  free(pemCert);
1763
0
  return verification_status;
1764
0
}
1765
1766
void tls_print_new_certificate_warn(rdpCertificateStore* store, const char* hostname, UINT16 port,
1767
                                    const char* fingerprint)
1768
0
{
1769
0
  char* path = freerdp_certificate_store_get_cert_path(store, hostname, port);
1770
1771
0
  WLog_ERR(TAG, "The host key for %s:%" PRIu16 " has changed", hostname, port);
1772
0
  WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1773
0
  WLog_ERR(TAG, "@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
1774
0
  WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1775
0
  WLog_ERR(TAG, "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
1776
0
  WLog_ERR(TAG, "Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
1777
0
  WLog_ERR(TAG, "It is also possible that a host key has just been changed.");
1778
0
  WLog_ERR(TAG, "The fingerprint for the host key sent by the remote host is %s", fingerprint);
1779
0
  WLog_ERR(TAG, "Please contact your system administrator.");
1780
0
  WLog_ERR(TAG, "Add correct host key in %s to get rid of this message.", path);
1781
0
  WLog_ERR(TAG, "Host key for %s has changed and you have requested strict checking.", hostname);
1782
0
  WLog_ERR(TAG, "Host key verification failed.");
1783
1784
0
  free(path);
1785
0
}
1786
1787
void tls_print_certificate_error(rdpCertificateStore* store, rdpCertificateData* stored_data,
1788
                                 const char* hostname, UINT16 port, const char* fingerprint)
1789
0
{
1790
0
  char* path = freerdp_certificate_store_get_cert_path(store, hostname, port);
1791
1792
0
  WLog_ERR(TAG, "New host key for %s:%" PRIu16, hostname, port);
1793
0
  WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1794
0
  WLog_ERR(TAG, "@    WARNING: NEW HOST IDENTIFICATION!     @");
1795
0
  WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1796
1797
0
  WLog_ERR(TAG, "The fingerprint for the host key sent by the remote host is %s", fingerprint);
1798
0
  WLog_ERR(TAG, "Please contact your system administrator.");
1799
0
  WLog_ERR(TAG, "Add correct host key in %s to get rid of this message.", path);
1800
1801
0
  free(path);
1802
0
}
1803
1804
void tls_print_certificate_name_mismatch_error(const char* hostname, UINT16 port,
1805
                                               const char* common_name, char** alt_names,
1806
                                               size_t alt_names_count)
1807
0
{
1808
0
  WINPR_ASSERT(NULL != hostname);
1809
0
  WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1810
0
  WLog_ERR(TAG, "@           WARNING: CERTIFICATE NAME MISMATCH!           @");
1811
0
  WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1812
0
  WLog_ERR(TAG, "The hostname used for this connection (%s:%" PRIu16 ") ", hostname, port);
1813
0
  WLog_ERR(TAG, "does not match %s given in the certificate:",
1814
0
           alt_names_count < 1 ? "the name" : "any of the names");
1815
0
  WLog_ERR(TAG, "Common Name (CN):");
1816
0
  WLog_ERR(TAG, "\t%s", common_name ? common_name : "no CN found in certificate");
1817
1818
0
  if (alt_names_count > 0)
1819
0
  {
1820
0
    WINPR_ASSERT(NULL != alt_names);
1821
0
    WLog_ERR(TAG, "Alternative names:");
1822
1823
0
    for (size_t index = 0; index < alt_names_count; index++)
1824
0
    {
1825
0
      WINPR_ASSERT(alt_names[index]);
1826
0
      WLog_ERR(TAG, "\t %s", alt_names[index]);
1827
0
    }
1828
0
  }
1829
1830
0
  WLog_ERR(TAG, "A valid certificate for the wrong name should NOT be trusted!");
1831
0
}
1832
1833
rdpTls* freerdp_tls_new(rdpSettings* settings)
1834
0
{
1835
0
  rdpTls* tls;
1836
0
  tls = (rdpTls*)calloc(1, sizeof(rdpTls));
1837
1838
0
  if (!tls)
1839
0
    return NULL;
1840
1841
0
  tls->settings = settings;
1842
1843
0
  if (!settings->ServerMode)
1844
0
  {
1845
0
    tls->certificate_store = freerdp_certificate_store_new(settings);
1846
1847
0
    if (!tls->certificate_store)
1848
0
      goto out_free;
1849
0
  }
1850
1851
0
  tls->alertLevel = TLS_ALERT_LEVEL_WARNING;
1852
0
  tls->alertDescription = TLS_ALERT_DESCRIPTION_CLOSE_NOTIFY;
1853
0
  return tls;
1854
0
out_free:
1855
0
  free(tls);
1856
0
  return NULL;
1857
0
}
1858
1859
void freerdp_tls_free(rdpTls* tls)
1860
0
{
1861
0
  if (!tls)
1862
0
    return;
1863
1864
0
  tls_reset(tls);
1865
1866
0
  if (tls->certificate_store)
1867
0
  {
1868
0
    freerdp_certificate_store_free(tls->certificate_store);
1869
0
    tls->certificate_store = NULL;
1870
0
  }
1871
1872
0
  free(tls);
1873
0
}