22#include <freerdp/config.h> 
   24#include "../core/settings.h" 
   26#include <winpr/assert.h> 
   31#include <winpr/winpr.h> 
   32#include <winpr/string.h> 
   33#include <winpr/sspi.h> 
   35#include <winpr/json.h> 
   37#include <winpr/stream.h> 
   38#include <freerdp/utils/ringbuffer.h> 
   40#include <freerdp/crypto/certificate.h> 
   41#include <freerdp/crypto/certificate_data.h> 
   42#include <freerdp/utils/helpers.h> 
   44#include <freerdp/log.h> 
   45#include "../crypto/tls.h" 
   46#include "../core/tcp.h" 
   48#include "opensslcompat.h" 
   49#include "certificate.h" 
   50#include "privatekey.h" 
   52#ifdef WINPR_HAVE_POLL_H 
   56#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H 
   57#include <valgrind/memcheck.h> 
   60#define TAG FREERDP_TAG("crypto") 
   90static int tls_verify_certificate(rdpTls* tls, 
const rdpCertificate* cert, 
const char* hostname,
 
   92static void tls_print_certificate_name_mismatch_error(
const char* hostname, UINT16 port,
 
   93                                                      const char* common_name, 
char** alt_names,
 
   94                                                      size_t alt_names_count);
 
   95static void tls_print_new_certificate_warn(rdpCertificateStore* store, 
const char* hostname,
 
   96                                           UINT16 port, 
const char* type, 
const char* fingerprint);
 
   97static void tls_print_certificate_error(rdpCertificateStore* store, rdpCertificateData* stored_data,
 
   98                                        const char* hostname, UINT16 port, 
const char* fingerprint);
 
  100static void free_tls_public_key(rdpTls* tls)
 
  103  free(tls->PublicKey);
 
  104  tls->PublicKey = NULL;
 
  105  tls->PublicKeyLength = 0;
 
  108static void free_tls_bindings(rdpTls* tls)
 
  113    free(tls->Bindings->Bindings);
 
  116  tls->Bindings = NULL;
 
  119static int bio_rdp_tls_write(BIO* bio, 
const char* buf, 
int size)
 
  123  BIO_RDP_TLS* tls = (BIO_RDP_TLS*)BIO_get_data(bio);
 
  128  BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
 
  129  EnterCriticalSection(&tls->lock);
 
  130  status = SSL_write(tls->ssl, buf, size);
 
  131  error = SSL_get_error(tls->ssl, status);
 
  132  LeaveCriticalSection(&tls->lock);
 
  139        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
  142      case SSL_ERROR_WANT_WRITE:
 
  143        BIO_set_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
 
  146      case SSL_ERROR_WANT_READ:
 
  147        BIO_set_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
 
  150      case SSL_ERROR_WANT_X509_LOOKUP:
 
  151        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
 
  152        BIO_set_retry_reason(bio, BIO_RR_SSL_X509_LOOKUP);
 
  155      case SSL_ERROR_WANT_CONNECT:
 
  156        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
 
  157        BIO_set_retry_reason(bio, BIO_RR_CONNECT);
 
  160      case SSL_ERROR_SYSCALL:
 
  161        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
  165        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
  175static int bio_rdp_tls_read(BIO* bio, 
char* buf, 
int size)
 
  179  BIO_RDP_TLS* tls = (BIO_RDP_TLS*)BIO_get_data(bio);
 
  184  BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
 
  185  EnterCriticalSection(&tls->lock);
 
  186  status = SSL_read(tls->ssl, buf, size);
 
  187  error = SSL_get_error(tls->ssl, status);
 
  188  LeaveCriticalSection(&tls->lock);
 
  196        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
  199      case SSL_ERROR_WANT_READ:
 
  200        BIO_set_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
 
  203      case SSL_ERROR_WANT_WRITE:
 
  204        BIO_set_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
 
  207      case SSL_ERROR_WANT_X509_LOOKUP:
 
  208        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
 
  209        BIO_set_retry_reason(bio, BIO_RR_SSL_X509_LOOKUP);
 
  212      case SSL_ERROR_WANT_ACCEPT:
 
  213        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
 
  214        BIO_set_retry_reason(bio, BIO_RR_ACCEPT);
 
  217      case SSL_ERROR_WANT_CONNECT:
 
  218        BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
 
  219        BIO_set_retry_reason(bio, BIO_RR_CONNECT);
 
  223        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
  226      case SSL_ERROR_ZERO_RETURN:
 
  227        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
  230      case SSL_ERROR_SYSCALL:
 
  231        BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
  238#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H 
  242    VALGRIND_MAKE_MEM_DEFINED(buf, status);
 
  249static int bio_rdp_tls_puts(BIO* bio, 
const char* str)
 
  254  const int max = (INT_MAX > SIZE_MAX) ? SIZE_MAX : INT_MAX;
 
  255  const size_t size = strnlen(str, max);
 
  259  return BIO_write(bio, str, (
int)size);
 
  262static int bio_rdp_tls_gets(WINPR_ATTR_UNUSED BIO* bio, WINPR_ATTR_UNUSED 
char* str,
 
  263                            WINPR_ATTR_UNUSED 
int size)
 
  268static long bio_rdp_tls_ctrl(BIO* bio, 
int cmd, 
long num, 
void* ptr)
 
  270  BIO* ssl_rbio = NULL;
 
  271  BIO* ssl_wbio = NULL;
 
  272  BIO* next_bio = NULL;
 
  274  BIO_RDP_TLS* tls = (BIO_RDP_TLS*)BIO_get_data(bio);
 
  279  if (!tls->ssl && (cmd != BIO_C_SET_SSL))
 
  282  next_bio = BIO_next(bio);
 
  283  ssl_rbio = tls->ssl ? SSL_get_rbio(tls->ssl) : NULL;
 
  284  ssl_wbio = tls->ssl ? SSL_get_wbio(tls->ssl) : NULL;
 
  289      SSL_shutdown(tls->ssl);
 
  291      if (SSL_in_connect_init(tls->ssl))
 
  292        SSL_set_connect_state(tls->ssl);
 
  293      else if (SSL_in_accept_init(tls->ssl))
 
  294        SSL_set_accept_state(tls->ssl);
 
  299        status = BIO_ctrl(next_bio, cmd, num, ptr);
 
  301        status = BIO_ctrl(ssl_rbio, cmd, num, ptr);
 
  308      status = BIO_ctrl(ssl_rbio, cmd, num, ptr);
 
  315    case BIO_CTRL_SET_CALLBACK:
 
  319    case BIO_CTRL_GET_CALLBACK:
 
  326        void* vptr = WINPR_FUNC_PTR_CAST(SSL_get_info_callback(tls->ssl), 
void*);
 
  327        *((
void**)ptr) = vptr;
 
  334        SSL_set_connect_state(tls->ssl);
 
  336        SSL_set_accept_state(tls->ssl);
 
  341    case BIO_CTRL_GET_CLOSE:
 
  342      status = BIO_get_shutdown(bio);
 
  345    case BIO_CTRL_SET_CLOSE:
 
  346      BIO_set_shutdown(bio, (
int)num);
 
  350    case BIO_CTRL_WPENDING:
 
  351      status = BIO_ctrl(ssl_wbio, cmd, num, ptr);
 
  354    case BIO_CTRL_PENDING:
 
  355      status = SSL_pending(tls->ssl);
 
  358        status = BIO_pending(ssl_rbio);
 
  363      BIO_clear_retry_flags(bio);
 
  364      status = BIO_ctrl(ssl_wbio, cmd, num, ptr);
 
  366        WLog_DBG(TAG, 
"BIO_ctrl returned %d", status);
 
  367      BIO_copy_next_retry(bio);
 
  372      if (next_bio && (next_bio != ssl_rbio))
 
  374#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ 
  375    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) 
  376        SSL_set_bio(tls->ssl, next_bio, next_bio);
 
  377        CRYPTO_add(&(bio->next_bio->references), 1, CRYPTO_LOCK_BIO);
 
  383        BIO_up_ref(next_bio);
 
  384        SSL_set_bio(tls->ssl, next_bio, next_bio);
 
  396        if (ssl_rbio != ssl_wbio)
 
  397          BIO_free_all(ssl_wbio);
 
  399#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ 
  400    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) 
  403          CRYPTO_add(&(bio->next_bio->references), -1, CRYPTO_LOCK_BIO);
 
  405        tls->ssl->wbio = tls->ssl->rbio = NULL;
 
  408        SSL_set_bio(tls->ssl, NULL, NULL);
 
  418        *((SSL**)ptr) = tls->ssl;
 
  425      BIO_set_shutdown(bio, (
int)num);
 
  429        tls->ssl = (SSL*)ptr;
 
  430        ssl_rbio = SSL_get_rbio(tls->ssl);
 
  436          BIO_push(ssl_rbio, next_bio);
 
  438        BIO_set_next(bio, ssl_rbio);
 
  439#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ 
  440    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) 
  441        CRYPTO_add(&(ssl_rbio->references), 1, CRYPTO_LOCK_BIO);
 
  443        BIO_up_ref(ssl_rbio);
 
  447      BIO_set_init(bio, 1);
 
  451    case BIO_C_DO_STATE_MACHINE:
 
  452      BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL);
 
  453      BIO_set_retry_reason(bio, 0);
 
  454      status = SSL_do_handshake(tls->ssl);
 
  458        const int err = (status < INT32_MIN) ? INT32_MIN : (int)status;
 
  459        switch (SSL_get_error(tls->ssl, err))
 
  461          case SSL_ERROR_WANT_READ:
 
  462            BIO_set_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
 
  465          case SSL_ERROR_WANT_WRITE:
 
  466            BIO_set_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
 
  469          case SSL_ERROR_WANT_CONNECT:
 
  470            BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY);
 
  471            BIO_set_retry_reason(bio, BIO_get_retry_reason(next_bio));
 
  475            BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
  483      status = BIO_ctrl(ssl_rbio, cmd, num, ptr);
 
  490static int bio_rdp_tls_new(BIO* bio)
 
  492  BIO_RDP_TLS* tls = NULL;
 
  493  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
 
  495  if (!(tls = calloc(1, 
sizeof(BIO_RDP_TLS))))
 
  498  InitializeCriticalSectionAndSpinCount(&tls->lock, 4000);
 
  499  BIO_set_data(bio, (
void*)tls);
 
  503static int bio_rdp_tls_free(BIO* bio)
 
  505  BIO_RDP_TLS* tls = NULL;
 
  510  tls = (BIO_RDP_TLS*)BIO_get_data(bio);
 
  515  BIO_set_data(bio, NULL);
 
  516  if (BIO_get_shutdown(bio))
 
  518    if (BIO_get_init(bio) && tls->ssl)
 
  520      SSL_shutdown(tls->ssl);
 
  524    BIO_set_init(bio, 0);
 
  525    BIO_set_flags(bio, 0);
 
  528  DeleteCriticalSection(&tls->lock);
 
  534static long bio_rdp_tls_callback_ctrl(BIO* bio, 
int cmd, bio_info_cb* fp)
 
  541  BIO_RDP_TLS* tls = (BIO_RDP_TLS*)BIO_get_data(bio);
 
  548    case BIO_CTRL_SET_CALLBACK:
 
  550      typedef void (*fkt_t)(
const SSL*, int, int);
 
  556      fkt_t fkt = WINPR_FUNC_PTR_CAST(fp, fkt_t);
 
  557      SSL_set_info_callback(tls->ssl, fkt);
 
  563      status = BIO_callback_ctrl(SSL_get_rbio(tls->ssl), cmd, fp);
 
  570#define BIO_TYPE_RDP_TLS 68 
  572static BIO_METHOD* BIO_s_rdp_tls(
void)
 
  574  static BIO_METHOD* bio_methods = NULL;
 
  576  if (bio_methods == NULL)
 
  578    if (!(bio_methods = BIO_meth_new(BIO_TYPE_RDP_TLS, 
"RdpTls")))
 
  581    BIO_meth_set_write(bio_methods, bio_rdp_tls_write);
 
  582    BIO_meth_set_read(bio_methods, bio_rdp_tls_read);
 
  583    BIO_meth_set_puts(bio_methods, bio_rdp_tls_puts);
 
  584    BIO_meth_set_gets(bio_methods, bio_rdp_tls_gets);
 
  585    BIO_meth_set_ctrl(bio_methods, bio_rdp_tls_ctrl);
 
  586    BIO_meth_set_create(bio_methods, bio_rdp_tls_new);
 
  587    BIO_meth_set_destroy(bio_methods, bio_rdp_tls_free);
 
  588    BIO_meth_set_callback_ctrl(bio_methods, bio_rdp_tls_callback_ctrl);
 
  594static BIO* BIO_new_rdp_tls(SSL_CTX* ctx, 
int client)
 
  598  bio = BIO_new(BIO_s_rdp_tls());
 
  612    SSL_set_connect_state(ssl);
 
  614    SSL_set_accept_state(ssl);
 
  616  BIO_set_ssl(bio, ssl, BIO_CLOSE);
 
  620static rdpCertificate* tls_get_certificate(rdpTls* tls, BOOL peer)
 
  622  X509* remote_cert = NULL;
 
  625    remote_cert = SSL_get_peer_certificate(tls->ssl);
 
  627    remote_cert = X509_dup(SSL_get_certificate(tls->ssl));
 
  631    WLog_ERR(TAG, 
"failed to get the server TLS certificate");
 
  636  STACK_OF(X509)* chain = SSL_get_peer_cert_chain(tls->ssl);
 
  637  rdpCertificate* cert = freerdp_certificate_new_from_x509(remote_cert, chain);
 
  638  X509_free(remote_cert);
 
  643static const char* tls_get_server_name(rdpTls* tls)
 
  645  return tls->serverName ? tls->serverName : tls->hostname;
 
  648#define TLS_SERVER_END_POINT "tls-server-end-point:" 
  652  size_t CertificateHashLength = 0;
 
  653  BYTE* ChannelBindingToken = NULL;
 
  655  const size_t PrefixLength = strnlen(TLS_SERVER_END_POINT, ARRAYSIZE(TLS_SERVER_END_POINT));
 
  660  WINPR_MD_TYPE alg = freerdp_certificate_get_signature_alg(cert);
 
  661  const char* hash = NULL;
 
  667      hash = winpr_md_type_to_string(WINPR_MD_SHA256);
 
  670      hash = winpr_md_type_to_string(alg);
 
  676  char* CertificateHash = freerdp_certificate_get_hash(cert, hash, &CertificateHashLength);
 
  677  if (!CertificateHash)
 
  680  const size_t ChannelBindingTokenLength = PrefixLength + CertificateHashLength;
 
  683  if (!ContextBindings)
 
  687  if (slen > UINT32_MAX)
 
  690  ContextBindings->BindingsLength = (UINT32)slen;
 
  693  if (!ChannelBindings)
 
  696  ContextBindings->Bindings = ChannelBindings;
 
  697  ChannelBindings->cbApplicationDataLength = (UINT32)ChannelBindingTokenLength;
 
  699  ChannelBindingToken = &((BYTE*)ChannelBindings)[ChannelBindings->dwApplicationDataOffset];
 
  700  memcpy(ChannelBindingToken, TLS_SERVER_END_POINT, PrefixLength);
 
  701  memcpy(ChannelBindingToken + PrefixLength, CertificateHash, CertificateHashLength);
 
  702  free(CertificateHash);
 
  703  return ContextBindings;
 
  705  free(CertificateHash);
 
  706  free(ContextBindings);
 
  710static INIT_ONCE secrets_file_idx_once = INIT_ONCE_STATIC_INIT;
 
  711static int secrets_file_idx = -1;
 
  713static BOOL CALLBACK secrets_file_init_cb(WINPR_ATTR_UNUSED 
PINIT_ONCE once,
 
  714                                          WINPR_ATTR_UNUSED PVOID param,
 
  715                                          WINPR_ATTR_UNUSED PVOID* context)
 
  717  secrets_file_idx = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
 
  719  return (secrets_file_idx != -1);
 
  722static void SSLCTX_keylog_cb(
const SSL* ssl, 
const char* line)
 
  726  if (secrets_file_idx == -1)
 
  729  dfile = SSL_get_ex_data(ssl, secrets_file_idx);
 
  732    FILE* f = winpr_fopen(dfile, 
"a+");
 
  735      (void)fwrite(line, strlen(line), 1, f);
 
  736      (void)fwrite(
"\n", 1, 1, f);
 
  742static void tls_reset(rdpTls* tls)
 
  748    SSL_CTX_free(tls->ctx);
 
  755    BIO_free_all(tls->bio);
 
  756  else if (tls->underlying)
 
  757    BIO_free_all(tls->underlying);
 
  759  tls->underlying = NULL;
 
  761  free_tls_public_key(tls);
 
  762  free_tls_bindings(tls);
 
  765#if OPENSSL_VERSION_NUMBER >= 0x010000000L 
  766static BOOL tls_prepare(rdpTls* tls, BIO* underlying, 
const SSL_METHOD* method, 
int options,
 
  769static BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method, 
int options,
 
  775  rdpSettings* settings = tls->context->settings;
 
  776  WINPR_ASSERT(settings);
 
  779  tls->ctx = SSL_CTX_new(method);
 
  781  tls->underlying = underlying;
 
  785    WLog_ERR(TAG, 
"SSL_CTX_new failed");
 
  789  SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
 
  790  SSL_CTX_set_options(tls->ctx, WINPR_ASSERTING_INT_CAST(uint64_t, options));
 
  791  SSL_CTX_set_read_ahead(tls->ctx, 1);
 
  792#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 
  794  if (!SSL_CTX_set_min_proto_version(tls->ctx, version))
 
  796    WLog_ERR(TAG, 
"SSL_CTX_set_min_proto_version %s failed", version);
 
  800  if (!SSL_CTX_set_max_proto_version(tls->ctx, version))
 
  802    WLog_ERR(TAG, 
"SSL_CTX_set_max_proto_version %s failed", version);
 
  806#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) 
  807  SSL_CTX_set_security_level(tls->ctx, WINPR_ASSERTING_INT_CAST(
int, settings->TlsSecLevel));
 
  810  if (settings->AllowedTlsCiphers)
 
  812    if (!SSL_CTX_set_cipher_list(tls->ctx, settings->AllowedTlsCiphers))
 
  814      WLog_ERR(TAG, 
"SSL_CTX_set_cipher_list %s failed", settings->AllowedTlsCiphers);
 
  819  tls->bio = BIO_new_rdp_tls(tls->ctx, clientMode);
 
  821  if (BIO_get_ssl(tls->bio, &tls->ssl) < 0)
 
  823    WLog_ERR(TAG, 
"unable to retrieve the SSL of the connection");
 
  827  if (settings->TlsSecretsFile)
 
  829#if OPENSSL_VERSION_NUMBER >= 0x10101000L 
  830    InitOnceExecuteOnce(&secrets_file_idx_once, secrets_file_init_cb, NULL, NULL);
 
  832    if (secrets_file_idx != -1)
 
  834      SSL_set_ex_data(tls->ssl, secrets_file_idx, settings->TlsSecretsFile);
 
  835      SSL_CTX_set_keylog_callback(tls->ctx, SSLCTX_keylog_cb);
 
  838    WLog_WARN(TAG, 
"Key-Logging not available - requires OpenSSL 1.1.1 or higher");
 
  842  BIO_push(tls->bio, underlying);
 
  847adjustSslOptions(WINPR_ATTR_UNUSED 
int* options) 
 
  849  WINPR_ASSERT(options);
 
  850#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 
  851  *options |= SSL_OP_NO_SSLv2;
 
  852  *options |= SSL_OP_NO_SSLv3;
 
  856const SSL_METHOD* freerdp_tls_get_ssl_method(BOOL isDtls, BOOL isClient)
 
  861      return DTLS_client_method();
 
  862#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 
  863    return SSLv23_client_method();
 
  865    return TLS_client_method();
 
  870    return DTLS_server_method();
 
  872#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 
  873  return SSLv23_server_method();
 
  875  return TLS_server_method();
 
  879TlsHandshakeResult freerdp_tls_connect_ex(rdpTls* tls, BIO* underlying, 
const SSL_METHOD* methods)
 
  893#ifdef SSL_OP_NO_COMPRESSION 
  894  options |= SSL_OP_NO_COMPRESSION;
 
  902  options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
 
  909  options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
 
  911  tls->isClientMode = TRUE;
 
  912  adjustSslOptions(&options);
 
  914  if (!tls_prepare(tls, underlying, methods, options, TRUE))
 
  917#if !defined(OPENSSL_NO_TLSEXT) 
  918  const char* str = tls_get_server_name(tls);
 
  919  void* ptr = WINPR_CAST_CONST_PTR_AWAY(str, 
void*);
 
  920  SSL_set_tlsext_host_name(tls->ssl, ptr);
 
  923  return freerdp_tls_handshake(tls);
 
  926static int bio_err_print(
const char* str, 
size_t len, 
void* u)
 
  929  WLog_Print(log, WLOG_ERROR, 
"[BIO_do_handshake] %s [%" PRIuz 
"]", str, len);
 
  933TlsHandshakeResult freerdp_tls_handshake(rdpTls* tls)
 
  935  TlsHandshakeResult ret = TLS_HANDSHAKE_ERROR;
 
  938  const long status = BIO_do_handshake(tls->bio);
 
  941    if (!BIO_should_retry(tls->bio))
 
  943      wLog* log = WLog_Get(TAG);
 
  944      WLog_Print(log, WLOG_ERROR, 
"BIO_do_handshake failed");
 
  945      ERR_print_errors_cb(bio_err_print, log);
 
  946      return TLS_HANDSHAKE_ERROR;
 
  949    return TLS_HANDSHAKE_CONTINUE;
 
  952  int verify_status = 0;
 
  953  rdpCertificate* cert = tls_get_certificate(tls, tls->isClientMode);
 
  957    WLog_ERR(TAG, 
"tls_get_certificate failed to return the server certificate.");
 
  958    return TLS_HANDSHAKE_ERROR;
 
  963    free_tls_bindings(tls);
 
  964    tls->Bindings = tls_get_channel_bindings(cert);
 
  967      WLog_ERR(TAG, 
"unable to retrieve bindings");
 
  971    free_tls_public_key(tls);
 
  972    if (!freerdp_certificate_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
 
  975               "freerdp_certificate_get_public_key failed to return the server public key.");
 
  980    ret = TLS_HANDSHAKE_SUCCESS;
 
  982    if (tls->isClientMode)
 
  984      WINPR_ASSERT(tls->port <= UINT16_MAX);
 
  986          tls_verify_certificate(tls, cert, tls_get_server_name(tls), (UINT16)tls->port);
 
  988      if (verify_status < 1)
 
  990        WLog_ERR(TAG, 
"certificate not trusted, aborting.");
 
  991        freerdp_tls_send_alert(tls);
 
  992        ret = TLS_HANDSHAKE_VERIFY_ERROR;
 
  997  freerdp_certificate_free(cert);
 
 1001static int pollAndHandshake(rdpTls* tls)
 
 1007    HANDLE events[] = { freerdp_abort_event(tls->context), NULL };
 
 1009    if (BIO_get_event(tls->bio, &events[1]) < 0)
 
 1011      WLog_ERR(TAG, 
"unable to retrieve BIO associated event");
 
 1017      WLog_ERR(TAG, 
"unable to retrieve BIO event");
 
 1021    status = WaitForMultipleObjectsEx(ARRAYSIZE(events), events, FALSE, INFINITE, TRUE);
 
 1024      case WAIT_OBJECT_0 + 1:
 
 1027        WLog_DBG(TAG, 
"Abort event set, cancel connect");
 
 1030      case WAIT_IO_COMPLETION:
 
 1033        WLog_ERR(TAG, 
"error during WaitForSingleObject(): 0x%08" PRIX32 
"", status);
 
 1037    TlsHandshakeResult result = freerdp_tls_handshake(tls);
 
 1040      case TLS_HANDSHAKE_CONTINUE:
 
 1042      case TLS_HANDSHAKE_SUCCESS:
 
 1044      case TLS_HANDSHAKE_ERROR:
 
 1045      case TLS_HANDSHAKE_VERIFY_ERROR:
 
 1052int freerdp_tls_connect(rdpTls* tls, BIO* underlying)
 
 1054  const SSL_METHOD* method = freerdp_tls_get_ssl_method(FALSE, TRUE);
 
 1057  TlsHandshakeResult result = freerdp_tls_connect_ex(tls, underlying, method);
 
 1060    case TLS_HANDSHAKE_SUCCESS:
 
 1062    case TLS_HANDSHAKE_CONTINUE:
 
 1064    case TLS_HANDSHAKE_ERROR:
 
 1065    case TLS_HANDSHAKE_VERIFY_ERROR:
 
 1071  return pollAndHandshake(tls);
 
 1074#if defined(MICROSOFT_IOS_SNI_BUG) && !defined(OPENSSL_NO_TLSEXT) && \ 
 1075    !defined(LIBRESSL_VERSION_NUMBER) 
 1076static void tls_openssl_tlsext_debug_callback(SSL* s, 
int client_server, 
int type,
 
 1077                                              unsigned char* data, 
int len, 
void* arg)
 
 1079  if (type == TLSEXT_TYPE_server_name)
 
 1081    WLog_DBG(TAG, 
"Client uses SNI (extension disabled)");
 
 1082    s->servername_done = 2;
 
 1087BOOL freerdp_tls_accept(rdpTls* tls, BIO* underlying, rdpSettings* settings)
 
 1090  TlsHandshakeResult res =
 
 1091      freerdp_tls_accept_ex(tls, underlying, settings, freerdp_tls_get_ssl_method(FALSE, FALSE));
 
 1094    case TLS_HANDSHAKE_SUCCESS:
 
 1096    case TLS_HANDSHAKE_CONTINUE:
 
 1098    case TLS_HANDSHAKE_ERROR:
 
 1099    case TLS_HANDSHAKE_VERIFY_ERROR:
 
 1104  return pollAndHandshake(tls) > 0;
 
 1107TlsHandshakeResult freerdp_tls_accept_ex(rdpTls* tls, BIO* underlying, rdpSettings* settings,
 
 1108                                         const SSL_METHOD* methods)
 
 1121  options |= SSL_OP_NO_SSLv2;
 
 1131#ifdef SSL_OP_NO_COMPRESSION 
 1132  options |= SSL_OP_NO_COMPRESSION;
 
 1140  options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
 
 1147  options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
 
 1155#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && (OPENSSL_VERSION_NUMBER < 0x30000000L) && \ 
 1156    !defined(LIBRESSL_VERSION_NUMBER) 
 1157  options |= SSL_OP_NO_RENEGOTIATION;
 
 1160  if (!tls_prepare(tls, underlying, methods, options, FALSE))
 
 1161    return TLS_HANDSHAKE_ERROR;
 
 1166    WLog_ERR(TAG, 
"invalid private key");
 
 1167    return TLS_HANDSHAKE_ERROR;
 
 1170  EVP_PKEY* privkey = freerdp_key_get_evp_pkey(key);
 
 1173    WLog_ERR(TAG, 
"invalid private key");
 
 1174    return TLS_HANDSHAKE_ERROR;
 
 1177  status = SSL_use_PrivateKey(tls->ssl, privkey);
 
 1182  EVP_PKEY_free(privkey);
 
 1186    WLog_ERR(TAG, 
"SSL_CTX_use_PrivateKey_file failed");
 
 1187    return TLS_HANDSHAKE_ERROR;
 
 1190  rdpCertificate* cert =
 
 1194    WLog_ERR(TAG, 
"invalid certificate");
 
 1195    return TLS_HANDSHAKE_ERROR;
 
 1198  status = SSL_use_certificate(tls->ssl, freerdp_certificate_get_x509(cert));
 
 1202    WLog_ERR(TAG, 
"SSL_use_certificate_file failed");
 
 1203    return TLS_HANDSHAKE_ERROR;
 
 1206  const size_t cnt = freerdp_certificate_get_chain_len(cert);
 
 1207  for (
size_t x = 0; x < cnt; x++)
 
 1209    X509* xcert = freerdp_certificate_get_chain_at(cert, x);
 
 1210    WINPR_ASSERT(xcert);
 
 1211    const long rc = SSL_add1_chain_cert(tls->ssl, xcert);
 
 1214      WLog_ERR(TAG, 
"SSL_add1_chain_cert failed");
 
 1215      return TLS_HANDSHAKE_ERROR;
 
 1219#if defined(MICROSOFT_IOS_SNI_BUG) && !defined(OPENSSL_NO_TLSEXT) && \ 
 1220    !defined(LIBRESSL_VERSION_NUMBER) 
 1221  SSL_set_tlsext_debug_callback(tls->ssl, tls_openssl_tlsext_debug_callback);
 
 1224  return freerdp_tls_handshake(tls);
 
 1227BOOL freerdp_tls_send_alert(rdpTls* tls)
 
 1241#if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x10100000L)) || \ 
 1242    (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER <= 0x2080300fL)) 
 1244  if (tls->alertDescription != TLS_ALERT_DESCRIPTION_CLOSE_NOTIFY)
 
 1255    SSL_SESSION* ssl_session = SSL_get_session(tls->ssl);
 
 1256    SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(tls->ssl);
 
 1257    SSL_set_quiet_shutdown(tls->ssl, 1);
 
 1259    if ((tls->alertLevel == TLS_ALERT_LEVEL_FATAL) && (ssl_session))
 
 1260      SSL_CTX_remove_session(ssl_ctx, ssl_session);
 
 1262    tls->ssl->s3->alert_dispatch = 1;
 
 1263    tls->ssl->s3->send_alert[0] = tls->alertLevel;
 
 1264    tls->ssl->s3->send_alert[1] = tls->alertDescription;
 
 1266    if (tls->ssl->s3->wbuf.left == 0)
 
 1267      tls->ssl->method->ssl_dispatch_alert(tls->ssl);
 
 1274int freerdp_tls_write_all(rdpTls* tls, 
const BYTE* data, 
size_t length)
 
 1278  BIO* bio = tls->bio;
 
 1280  if (length > INT32_MAX)
 
 1283  while (offset < length)
 
 1286    const int status = BIO_write(bio, &data[offset], (
int)(length - offset));
 
 1289      offset += (size_t)status;
 
 1292      if (!BIO_should_retry(bio))
 
 1295      if (BIO_write_blocked(bio))
 
 1297        const long rc = BIO_wait_write(bio, 100);
 
 1301      else if (BIO_read_blocked(bio))
 
 1311int freerdp_tls_set_alert_code(rdpTls* tls, 
int level, 
int description)
 
 1314  tls->alertLevel = level;
 
 1315  tls->alertDescription = description;
 
 1319static BOOL tls_match_hostname(
const char* pattern, 
const size_t pattern_length,
 
 1320                               const char* hostname)
 
 1322  if (strlen(hostname) == pattern_length)
 
 1324    if (_strnicmp(hostname, pattern, pattern_length) == 0)
 
 1328  if ((pattern_length > 2) && (pattern[0] == 
'*') && (pattern[1] == 
'.') &&
 
 1329      ((strlen(hostname)) >= pattern_length))
 
 1331    const char* check_hostname = &hostname[strlen(hostname) - pattern_length + 1];
 
 1333    if (_strnicmp(check_hostname, &pattern[1], pattern_length - 1) == 0)
 
 1342static BOOL is_redirected(rdpTls* tls)
 
 1344  rdpSettings* settings = tls->context->settings;
 
 1346  if (settings->GatewayArmTransport)
 
 1349  if (LB_NOREDIRECT & settings->RedirectionFlags)
 
 1352  return settings->RedirectionFlags != 0;
 
 1355static BOOL is_accepted(rdpTls* tls, 
const rdpCertificate* cert)
 
 1358  WINPR_ASSERT(tls->context);
 
 1360  rdpSettings* settings = tls->context->settings;
 
 1361  WINPR_ASSERT(settings);
 
 1363  FreeRDP_Settings_Keys_String keyAccepted = FreeRDP_AcceptedCert;
 
 1364  FreeRDP_Settings_Keys_UInt32 keyLength = FreeRDP_AcceptedCertLength;
 
 1366  if (tls->isGatewayTransport)
 
 1368    keyAccepted = FreeRDP_GatewayAcceptedCert;
 
 1369    keyLength = FreeRDP_GatewayAcceptedCertLength;
 
 1371  else if (is_redirected(tls))
 
 1373    keyAccepted = FreeRDP_RedirectionAcceptedCert;
 
 1374    keyLength = FreeRDP_RedirectionAcceptedCertLength;
 
 1380  if ((AcceptedKeyLength > 0) && AcceptedKey)
 
 1382    BOOL accepted = FALSE;
 
 1383    size_t pemLength = 0;
 
 1384    char* pem = freerdp_certificate_get_pem_ex(cert, &pemLength, FALSE);
 
 1385    if (pem && (AcceptedKeyLength == pemLength))
 
 1387      if (memcmp(AcceptedKey, pem, AcceptedKeyLength) == 0)
 
 1401static BOOL compare_fingerprint(
const char* fp, 
const char* hash, 
const rdpCertificate* cert,
 
 1405  char* strhash = NULL;
 
 1411  strhash = freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, separator);
 
 1415  equal = (_stricmp(strhash, fp) == 0);
 
 1420static BOOL compare_fingerprint_all(
const char* fp, 
const char* hash, 
const rdpCertificate* cert)
 
 1425  if (compare_fingerprint(fp, hash, cert, FALSE))
 
 1427  if (compare_fingerprint(fp, hash, cert, TRUE))
 
 1432static BOOL is_accepted_fingerprint(
const rdpCertificate* cert,
 
 1433                                    const char* CertificateAcceptedFingerprints)
 
 1438  if (CertificateAcceptedFingerprints)
 
 1440    char* context = NULL;
 
 1441    char* copy = _strdup(CertificateAcceptedFingerprints);
 
 1442    char* cur = strtok_s(copy, 
",", &context);
 
 1445      char* subcontext = NULL;
 
 1446      const char* h = strtok_s(cur, 
":", &subcontext);
 
 1451      const char* fp = h + strlen(h) + 1;
 
 1452      if (compare_fingerprint_all(fp, h, cert))
 
 1458      cur = strtok_s(NULL, 
",", &context);
 
 1466static BOOL accept_cert(rdpTls* tls, 
const rdpCertificate* cert)
 
 1469  WINPR_ASSERT(tls->context);
 
 1472  FreeRDP_Settings_Keys_String 
id = FreeRDP_AcceptedCert;
 
 1473  FreeRDP_Settings_Keys_UInt32 lid = FreeRDP_AcceptedCertLength;
 
 1475  rdpSettings* settings = tls->context->settings;
 
 1476  WINPR_ASSERT(settings);
 
 1478  if (tls->isGatewayTransport)
 
 1480    id = FreeRDP_GatewayAcceptedCert;
 
 1481    lid = FreeRDP_GatewayAcceptedCertLength;
 
 1483  else if (is_redirected(tls))
 
 1485    id = FreeRDP_RedirectionAcceptedCert;
 
 1486    lid = FreeRDP_RedirectionAcceptedCertLength;
 
 1489  size_t pemLength = 0;
 
 1490  char* pem = freerdp_certificate_get_pem_ex(cert, &pemLength, FALSE);
 
 1492  if (pemLength <= UINT32_MAX)
 
 1501static BOOL tls_extract_full_pem(
const rdpCertificate* cert, BYTE** PublicKey,
 
 1502                                 size_t* PublicKeyLength)
 
 1504  if (!cert || !PublicKey)
 
 1506  *PublicKey = (BYTE*)freerdp_certificate_get_pem(cert, PublicKeyLength);
 
 1507  return *PublicKey != NULL;
 
 1510static int tls_config_parse_bool(WINPR_JSON* json, 
const char* opt)
 
 1521static int tls_config_check_allowed_hashed(
const char* configfile, 
const rdpCertificate* cert,
 
 1524  WINPR_ASSERT(configfile);
 
 1538                "[%s] invalid certificate-db entry at position %" PRIuz 
": not a JSON object",
 
 1547                "[%s] invalid certificate-db entry at position %" PRIuz
 
 1548                ": invalid 'type' element, expected type string",
 
 1556                "[%s] invalid certificate-db entry at position %" PRIuz
 
 1557                ": invalid 'hash' element, expected type string",
 
 1565    char* hash = freerdp_certificate_get_fingerprint_by_hash_ex(cert, skey, FALSE);
 
 1569                "[%s] invalid certificate-db entry at position %" PRIuz
 
 1570                ": hash type '%s' not supported by certificate",
 
 1571                configfile, x, skey);
 
 1575    const int cmp = _stricmp(hash, sval);
 
 1585static int tls_config_check_certificate(
const rdpCertificate* cert, BOOL* pAllowUserconfig)
 
 1588  WINPR_ASSERT(pAllowUserconfig);
 
 1591  const char configfile[] = 
"certificates.json";
 
 1592  WINPR_JSON* json = freerdp_GetJSONConfigFile(TRUE, configfile);
 
 1596    WLog_DBG(TAG, 
"No or no valid configuration file for certificate handling, asking user");
 
 1600  if (tls_config_parse_bool(json, 
"deny") > 0)
 
 1602    WLog_WARN(TAG, 
"[%s] certificate denied by configuration", configfile);
 
 1607  if (tls_config_parse_bool(json, 
"ignore") > 0)
 
 1609    WLog_WARN(TAG, 
"[%s] certificate ignored by configuration", configfile);
 
 1614  if (tls_config_check_allowed_hashed(configfile, cert, json) > 0)
 
 1616    WLog_WARN(TAG, 
"[%s] certificate manually accepted by configuration", configfile);
 
 1621  if (tls_config_parse_bool(json, 
"deny-userconfig") > 0)
 
 1623    WLog_WARN(TAG, 
"[%s] configuration denies user to accept certificates", configfile);
 
 1630  *pAllowUserconfig = (rc == 0);
 
 1635int tls_verify_certificate(rdpTls* tls, 
const rdpCertificate* cert, 
const char* hostname,
 
 1640  BOOL certificate_status = 0;
 
 1641  char* common_name = NULL;
 
 1642  size_t common_name_length = 0;
 
 1643  char** dns_names = 0;
 
 1644  size_t dns_names_count = 0;
 
 1645  size_t* dns_names_lengths = NULL;
 
 1646  int verification_status = -1;
 
 1647  BOOL hostname_match = FALSE;
 
 1648  rdpCertificateData* certificate_data = NULL;
 
 1649  BYTE* pemCert = NULL;
 
 1650  DWORD flags = VERIFY_CERT_FLAG_NONE;
 
 1654  rdpContext* context = tls->context;
 
 1655  WINPR_ASSERT(context);
 
 1657  freerdp* instance = context->instance;
 
 1658  WINPR_ASSERT(instance);
 
 1660  const rdpSettings* settings = context->settings;
 
 1661  WINPR_ASSERT(settings);
 
 1663  if (freerdp_shall_disconnect_context(context))
 
 1666  if (!tls_extract_full_pem(cert, &pemCert, &length))
 
 1670  if (is_accepted(tls, cert))
 
 1672    verification_status = 1;
 
 1676  if (is_accepted_fingerprint(cert, settings->CertificateAcceptedFingerprints))
 
 1678    verification_status = 1;
 
 1682  if (tls->isGatewayTransport || is_redirected(tls))
 
 1683    flags |= VERIFY_CERT_FLAG_LEGACY;
 
 1685  if (tls->isGatewayTransport)
 
 1686    flags |= VERIFY_CERT_FLAG_GATEWAY;
 
 1688  if (is_redirected(tls))
 
 1689    flags |= VERIFY_CERT_FLAG_REDIRECT;
 
 1692  if (settings->ExternalCertificateManagement)
 
 1694    if (instance->VerifyX509Certificate)
 
 1695      verification_status =
 
 1696          instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, flags);
 
 1698      WLog_ERR(TAG, 
"No VerifyX509Certificate callback registered!");
 
 1700    if (verification_status > 0)
 
 1701      accept_cert(tls, cert);
 
 1702    else if (verification_status < 0)
 
 1704      WLog_ERR(TAG, 
"VerifyX509Certificate failed: (length = %" PRIuz 
") status: [%d] %s",
 
 1705               length, verification_status, pemCert);
 
 1712    WLog_WARN(TAG, 
"[DANGER] Certificate not checked, /cert:ignore in use.");
 
 1713    WLog_WARN(TAG, 
"[DANGER] This prevents MITM attacks from being detected!");
 
 1715              "[DANGER] Avoid using this unless in a secure LAN (=no internet) environment");
 
 1716    verification_status = 1; 
 
 1718  else if (!tls->isGatewayTransport && (settings->AuthenticationLevel == 0))
 
 1719    verification_status = 1; 
 
 1723    if (!tls->isGatewayTransport && settings->CertificateName)
 
 1724      hostname = settings->CertificateName;
 
 1727    certificate_status = freerdp_certificate_verify(
 
 1728        cert, freerdp_certificate_store_get_certs_path(tls->certificate_store));
 
 1730    certificate_data = freerdp_certificate_data_new(hostname, port, cert);
 
 1731    if (!certificate_data)
 
 1734    common_name = freerdp_certificate_get_common_name(cert, &common_name_length);
 
 1735    dns_names = freerdp_certificate_get_dns_names(cert, &dns_names_count, &dns_names_lengths);
 
 1741      if (tls_match_hostname(common_name, common_name_length, hostname))
 
 1742        hostname_match = TRUE;
 
 1749      for (
size_t index = 0; index < dns_names_count; index++)
 
 1751        if (tls_match_hostname(dns_names[index], dns_names_lengths[index], hostname))
 
 1753          hostname_match = TRUE;
 
 1761    if (certificate_status && hostname_match)
 
 1762      verification_status = 1; 
 
 1764    if (!hostname_match)
 
 1765      flags |= VERIFY_CERT_FLAG_MISMATCH;
 
 1767    BOOL allowUserconfig = TRUE;
 
 1768    if (!certificate_status || !hostname_match)
 
 1769      verification_status = tls_config_check_certificate(cert, &allowUserconfig);
 
 1773    if (allowUserconfig && (!certificate_status || !hostname_match))
 
 1775      DWORD accept_certificate = 0;
 
 1776      size_t pem_length = 0;
 
 1777      char* issuer = freerdp_certificate_get_issuer(cert);
 
 1778      char* subject = freerdp_certificate_get_subject(cert);
 
 1779      char* pem = freerdp_certificate_get_pem(cert, &pem_length);
 
 1786          freerdp_certificate_store_contains_data(tls->certificate_store, certificate_data);
 
 1792        if (!hostname_match)
 
 1793          tls_print_certificate_name_mismatch_error(hostname, port, common_name,
 
 1794                                                    dns_names, dns_names_count);
 
 1797          const char* type = 
"";
 
 1799            type = 
"tofo (auto-accept)";
 
 1802            type = 
"strict (auto-deny)";
 
 1805            type = 
"ignore (no check)";
 
 1807          char* efp = freerdp_certificate_get_fingerprint(cert);
 
 1808          tls_print_new_certificate_warn(tls->certificate_store, hostname, port, type,
 
 1814        if (settings->AutoAcceptCertificate)
 
 1816          WLog_INFO(TAG, 
"No certificate stored, automatically accepting.");
 
 1817          accept_certificate = 1;
 
 1819        else if (settings->AutoDenyCertificate)
 
 1821          WLog_INFO(TAG, 
"No certificate stored, automatically denying.");
 
 1822          accept_certificate = 0;
 
 1824        else if (instance->VerifyX509Certificate)
 
 1826          int rc = instance->VerifyX509Certificate(instance, pemCert, pem_length,
 
 1827                                                   hostname, port, flags);
 
 1830            accept_certificate = 1;
 
 1832            accept_certificate = 2;
 
 1834            accept_certificate = 0;
 
 1836        else if (instance->VerifyCertificateEx)
 
 1838          const BOOL use_pem =
 
 1841          DWORD cflags = flags;
 
 1844            cflags |= VERIFY_CERT_FLAG_FP_IS_PEM;
 
 1848            fp = freerdp_certificate_get_fingerprint(cert);
 
 1849          accept_certificate = instance->VerifyCertificateEx(
 
 1850              instance, hostname, port, common_name, subject, issuer, fp, cflags);
 
 1854#if defined(WITH_FREERDP_DEPRECATED) 
 1855        else if (instance->VerifyCertificate)
 
 1857          char* fp = freerdp_certificate_get_fingerprint(cert);
 
 1859          WLog_WARN(TAG, 
"The VerifyCertificate callback is deprecated, migrate your " 
 1860                         "application to VerifyCertificateEx");
 
 1861          accept_certificate = instance->VerifyCertificate(instance, common_name, subject,
 
 1862                                                           issuer, fp, !hostname_match);
 
 1867      else if (match == -1)
 
 1869        rdpCertificateData* stored_data =
 
 1870            freerdp_certificate_store_load_data(tls->certificate_store, hostname, port);
 
 1874          char* efp = freerdp_certificate_get_fingerprint(cert);
 
 1875          tls_print_certificate_error(tls->certificate_store, stored_data, hostname, port,
 
 1881          WLog_WARN(TAG, 
"Failed to get certificate entry for %s:%" PRIu16 
"", hostname,
 
 1884        if (settings->AutoDenyCertificate)
 
 1886          WLog_INFO(TAG, 
"No certificate stored, automatically denying.");
 
 1887          accept_certificate = 0;
 
 1889        else if (instance->VerifyX509Certificate)
 
 1892              instance->VerifyX509Certificate(instance, pemCert, pem_length, hostname,
 
 1893                                              port, flags | VERIFY_CERT_FLAG_CHANGED);
 
 1896            accept_certificate = 1;
 
 1898            accept_certificate = 2;
 
 1900            accept_certificate = 0;
 
 1902        else if (instance->VerifyChangedCertificateEx)
 
 1904          DWORD cflags = flags | VERIFY_CERT_FLAG_CHANGED;
 
 1905          const char* old_subject = freerdp_certificate_data_get_subject(stored_data);
 
 1906          const char* old_issuer = freerdp_certificate_data_get_issuer(stored_data);
 
 1907          const char* old_fp = freerdp_certificate_data_get_fingerprint(stored_data);
 
 1908          const char* old_pem = freerdp_certificate_data_get_pem(stored_data);
 
 1909          const BOOL fpIsAllocated =
 
 1915            cflags |= VERIFY_CERT_FLAG_FP_IS_PEM;
 
 1921            fp = freerdp_certificate_get_fingerprint(cert);
 
 1923          accept_certificate = instance->VerifyChangedCertificateEx(
 
 1924              instance, hostname, port, common_name, subject, issuer, fp, old_subject,
 
 1925              old_issuer, old_fp, cflags);
 
 1929#if defined(WITH_FREERDP_DEPRECATED) 
 1930        else if (instance->VerifyChangedCertificate)
 
 1932          char* fp = freerdp_certificate_get_fingerprint(cert);
 
 1933          const char* old_subject = freerdp_certificate_data_get_subject(stored_data);
 
 1934          const char* old_issuer = freerdp_certificate_data_get_issuer(stored_data);
 
 1935          const char* old_fingerprint =
 
 1936              freerdp_certificate_data_get_fingerprint(stored_data);
 
 1938          WLog_WARN(TAG, 
"The VerifyChangedCertificate callback is deprecated, migrate " 
 1939                         "your application to VerifyChangedCertificateEx");
 
 1940          accept_certificate = instance->VerifyChangedCertificate(
 
 1941              instance, common_name, subject, issuer, fp, old_subject, old_issuer,
 
 1947        freerdp_certificate_data_free(stored_data);
 
 1949      else if (match == 0)
 
 1950        accept_certificate = 2; 
 
 1953      switch (accept_certificate)
 
 1958          verification_status = freerdp_certificate_store_save_data(
 
 1959                                    tls->certificate_store, certificate_data)
 
 1966          verification_status = 1;
 
 1971          verification_status = -1; 
 
 1980    if (verification_status > 0)
 
 1981      accept_cert(tls, cert);
 
 1985  freerdp_certificate_data_free(certificate_data);
 
 1987  freerdp_certificate_free_dns_names(dns_names_count, dns_names_lengths, dns_names);
 
 1989  return verification_status;
 
 1992void tls_print_new_certificate_warn(rdpCertificateStore* store, 
const char* hostname, UINT16 port,
 
 1993                                    const char* type, 
const char* fingerprint)
 
 1995  char* path = freerdp_certificate_store_get_cert_path(store, hostname, port);
 
 1997  WLog_ERR(TAG, 
"The host key for %s:%" PRIu16 
" has changed", hostname, port);
 
 1998  WLog_ERR(TAG, 
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 
 1999  WLog_ERR(TAG, 
"@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
 
 2000  WLog_ERR(TAG, 
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 
 2001  WLog_ERR(TAG, 
"IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
 
 2002  WLog_ERR(TAG, 
"Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
 
 2003  WLog_ERR(TAG, 
"It is also possible that a host key has just been changed.");
 
 2004  WLog_ERR(TAG, 
"The fingerprint for the host key sent by the remote host is %s", fingerprint);
 
 2005  WLog_ERR(TAG, 
"Please contact your system administrator.");
 
 2006  WLog_ERR(TAG, 
"Add correct host key in %s to get rid of this message.", path);
 
 2007  WLog_ERR(TAG, 
"Host key for %s has changed and you have requested %s checking.", hostname,
 
 2009  WLog_ERR(TAG, 
"Host key verification failed.");
 
 2014void tls_print_certificate_error(rdpCertificateStore* store,
 
 2015                                 WINPR_ATTR_UNUSED rdpCertificateData* stored_data,
 
 2016                                 const char* hostname, UINT16 port, 
const char* fingerprint)
 
 2018  char* path = freerdp_certificate_store_get_cert_path(store, hostname, port);
 
 2020  WLog_ERR(TAG, 
"New host key for %s:%" PRIu16, hostname, port);
 
 2021  WLog_ERR(TAG, 
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 
 2022  WLog_ERR(TAG, 
"@    WARNING: NEW HOST IDENTIFICATION!     @");
 
 2023  WLog_ERR(TAG, 
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 
 2025  WLog_ERR(TAG, 
"The fingerprint for the host key sent by the remote host is %s", fingerprint);
 
 2026  WLog_ERR(TAG, 
"Please contact your system administrator.");
 
 2027  WLog_ERR(TAG, 
"Add correct host key in %s to get rid of this message.", path);
 
 2032void tls_print_certificate_name_mismatch_error(
const char* hostname, UINT16 port,
 
 2033                                               const char* common_name, 
char** alt_names,
 
 2034                                               size_t alt_names_count)
 
 2036  WINPR_ASSERT(NULL != hostname);
 
 2037  WLog_ERR(TAG, 
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 
 2038  WLog_ERR(TAG, 
"@           WARNING: CERTIFICATE NAME MISMATCH!           @");
 
 2039  WLog_ERR(TAG, 
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 
 2040  WLog_ERR(TAG, 
"The hostname used for this connection (%s:%" PRIu16 
") ", hostname, port);
 
 2041  WLog_ERR(TAG, 
"does not match %s given in the certificate:",
 
 2042           alt_names_count < 1 ? 
"the name" : 
"any of the names");
 
 2043  WLog_ERR(TAG, 
"Common Name (CN):");
 
 2044  WLog_ERR(TAG, 
"\t%s", common_name ? common_name : 
"no CN found in certificate");
 
 2046  if (alt_names_count > 0)
 
 2048    WINPR_ASSERT(NULL != alt_names);
 
 2049    WLog_ERR(TAG, 
"Alternative names:");
 
 2051    for (
size_t index = 0; index < alt_names_count; index++)
 
 2053      WINPR_ASSERT(alt_names[index]);
 
 2054      WLog_ERR(TAG, 
"\t %s", alt_names[index]);
 
 2058  WLog_ERR(TAG, 
"A valid certificate for the wrong name should NOT be trusted!");
 
 2061rdpTls* freerdp_tls_new(rdpContext* context)
 
 2064  tls = (rdpTls*)calloc(1, 
sizeof(rdpTls));
 
 2069  tls->context = context;
 
 2073    tls->certificate_store = freerdp_certificate_store_new(tls->context->settings);
 
 2075    if (!tls->certificate_store)
 
 2079  tls->alertLevel = TLS_ALERT_LEVEL_WARNING;
 
 2080  tls->alertDescription = TLS_ALERT_DESCRIPTION_CLOSE_NOTIFY;
 
 2087void freerdp_tls_free(rdpTls* tls)
 
 2094  if (tls->certificate_store)
 
 2096    freerdp_certificate_store_free(tls->certificate_store);
 
 2097    tls->certificate_store = NULL;
 
WINPR_API BOOL WINPR_JSON_IsString(const WINPR_JSON *item)
Check if JSON item is of type String.
 
WINPR_API BOOL WINPR_JSON_IsBool(const WINPR_JSON *item)
Check if JSON item is of type BOOL.
 
WINPR_API WINPR_JSON * WINPR_JSON_GetArrayItem(const WINPR_JSON *array, size_t index)
Return a pointer to an item in the array.
 
WINPR_API WINPR_JSON * WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON *object, const char *string)
Same as WINPR_JSON_GetObjectItem but with case sensitive matching.
 
WINPR_API BOOL WINPR_JSON_IsObject(const WINPR_JSON *item)
Check if JSON item is of type Object.
 
WINPR_API const char * WINPR_JSON_GetStringValue(WINPR_JSON *item)
Return the String value of a JSON item.
 
WINPR_API void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.
 
WINPR_API size_t WINPR_JSON_GetArraySize(const WINPR_JSON *array)
Get the number of arrayitems from an array.
 
WINPR_API BOOL WINPR_JSON_IsArray(const WINPR_JSON *item)
Check if JSON item is of type Array.
 
WINPR_API BOOL WINPR_JSON_IsTrue(const WINPR_JSON *item)
Check if JSON item is BOOL value True.
 
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
 
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param)
Sets a string settings value. The param is copied.
 
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
 
FREERDP_API UINT16 freerdp_settings_get_uint16(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id)
Returns a UINT16 settings value.
 
FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.
 
FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
 
FREERDP_API BOOL freerdp_settings_set_string_len(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param, size_t len)
Sets a string settings value. The param is copied.
 
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
 
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.