FreeRDP
libfreerdp/crypto/tls.c File Reference
#include <freerdp/config.h>
#include "../core/settings.h"
#include <winpr/assert.h>
#include <string.h>
#include <errno.h>
#include <winpr/crt.h>
#include <winpr/string.h>
#include <winpr/sspi.h>
#include <winpr/ssl.h>
#include <winpr/stream.h>
#include <freerdp/utils/ringbuffer.h>
#include <freerdp/crypto/certificate.h>
#include <freerdp/crypto/certificate_data.h>
#include <freerdp/log.h>
#include "../crypto/tls.h"
#include "../core/tcp.h"
#include "opensslcompat.h"
#include "certificate.h"
#include "privatekey.h"

Macros

#define TAG   FREERDP_TAG("crypto")
 
#define BIO_TYPE_RDP_TLS   68
 
#define TLS_SERVER_END_POINT   "tls-server-end-point:"
 

Functions

static int tls_verify_certificate (rdpTls *tls, const rdpCertificate *cert, const char *hostname, UINT16 port)
 
static void tls_print_certificate_name_mismatch_error (const char *hostname, UINT16 port, const char *common_name, char **alt_names, size_t alt_names_count)
 
static void tls_print_new_certificate_warn (rdpCertificateStore *store, const char *hostname, UINT16 port, const char *fingerprint)
 
static void tls_print_certificate_error (rdpCertificateStore *store, rdpCertificateData *stored_data, const char *hostname, UINT16 port, const char *fingerprint)
 
static void free_tls_public_key (rdpTls *tls)
 
static void free_tls_bindings (rdpTls *tls)
 
static int bio_rdp_tls_write (BIO *bio, const char *buf, int size)
 
static int bio_rdp_tls_read (BIO *bio, char *buf, int size)
 
static int bio_rdp_tls_puts (BIO *bio, const char *str)
 
static int bio_rdp_tls_gets (BIO *bio, char *str, int size)
 
static long bio_rdp_tls_ctrl (BIO *bio, int cmd, long num, void *ptr)
 
static int bio_rdp_tls_new (BIO *bio)
 
static int bio_rdp_tls_free (BIO *bio)
 
static long bio_rdp_tls_callback_ctrl (BIO *bio, int cmd, bio_info_cb *fp)
 
static BIO_METHOD * BIO_s_rdp_tls (void)
 
static BIO * BIO_new_rdp_tls (SSL_CTX *ctx, int client)
 
static rdpCertificate * tls_get_certificate (rdpTls *tls, BOOL peer)
 
static const char * tls_get_server_name (rdpTls *tls)
 
static SecPkgContext_Bindingstls_get_channel_bindings (const rdpCertificate *cert)
 
static BOOL CALLBACK secrets_file_init_cb (PINIT_ONCE once, PVOID param, PVOID *context)
 
static void SSLCTX_keylog_cb (const SSL *ssl, const char *line)
 
static void tls_reset (rdpTls *tls)
 
static BOOL tls_prepare (rdpTls *tls, BIO *underlying, SSL_METHOD *method, int options, BOOL clientMode)
 
static void adjustSslOptions (int *options)
 
const SSL_METHOD * freerdp_tls_get_ssl_method (BOOL isDtls, BOOL isClient)
 
TlsHandshakeResult freerdp_tls_connect_ex (rdpTls *tls, BIO *underlying, const SSL_METHOD *methods)
 
static int bio_err_print (const char *str, size_t len, void *u)
 
TlsHandshakeResult freerdp_tls_handshake (rdpTls *tls)
 
static int pollAndHandshake (rdpTls *tls)
 
int freerdp_tls_connect (rdpTls *tls, BIO *underlying)
 
BOOL freerdp_tls_accept (rdpTls *tls, BIO *underlying, rdpSettings *settings)
 
TlsHandshakeResult freerdp_tls_accept_ex (rdpTls *tls, BIO *underlying, rdpSettings *settings, const SSL_METHOD *methods)
 
BOOL freerdp_tls_send_alert (rdpTls *tls)
 
int freerdp_tls_write_all (rdpTls *tls, const BYTE *data, int length)
 
int freerdp_tls_set_alert_code (rdpTls *tls, int level, int description)
 
static BOOL tls_match_hostname (const char *pattern, const size_t pattern_length, const char *hostname)
 
static BOOL is_redirected (rdpTls *tls)
 
static BOOL is_accepted (rdpTls *tls, const BYTE *pem, size_t length)
 
static BOOL compare_fingerprint (const char *fp, const char *hash, const rdpCertificate *cert, BOOL separator)
 
static BOOL compare_fingerprint_all (const char *fp, const char *hash, const rdpCertificate *cert)
 
static BOOL is_accepted_fingerprint (const rdpCertificate *cert, const char *CertificateAcceptedFingerprints)
 
static BOOL accept_cert (rdpTls *tls, const BYTE *pem, UINT32 length)
 
static BOOL tls_extract_pem (const rdpCertificate *cert, BYTE **PublicKey, size_t *PublicKeyLength)
 
rdpTls * freerdp_tls_new (rdpSettings *settings)
 
void freerdp_tls_free (rdpTls *tls)
 

Variables

static INIT_ONCE secrets_file_idx_once = INIT_ONCE_STATIC_INIT
 
static int secrets_file_idx = -1
 

Macro Definition Documentation

◆ BIO_TYPE_RDP_TLS

#define BIO_TYPE_RDP_TLS   68

◆ TAG

#define TAG   FREERDP_TAG("crypto")

FreeRDP: A Remote Desktop Protocol Implementation Transport Layer Security

Copyright 2011-2012 Marc-Andre Moreau marca.nosp@m.ndre.nosp@m..more.nosp@m.au@g.nosp@m.mail..nosp@m.com Copyright 2023 Armin Novak anova.nosp@m.k@th.nosp@m.incas.nosp@m.t.co.nosp@m.m Copyright 2023 Thincast Technologies GmbH

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

◆ TLS_SERVER_END_POINT

#define TLS_SERVER_END_POINT   "tls-server-end-point:"

Function Documentation

◆ accept_cert()

static BOOL accept_cert ( rdpTls *  tls,
const BYTE pem,
UINT32  length 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ adjustSslOptions()

static void adjustSslOptions ( int *  options)
static
Here is the caller graph for this function:

◆ bio_err_print()

static int bio_err_print ( const char *  str,
size_t  len,
void *  u 
)
static
Here is the caller graph for this function:

◆ BIO_new_rdp_tls()

static BIO* BIO_new_rdp_tls ( SSL_CTX *  ctx,
int  client 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bio_rdp_tls_callback_ctrl()

static long bio_rdp_tls_callback_ctrl ( BIO *  bio,
int  cmd,
bio_info_cb *  fp 
)
static
Here is the caller graph for this function:

◆ bio_rdp_tls_ctrl()

static long bio_rdp_tls_ctrl ( BIO *  bio,
int  cmd,
long  num,
void *  ptr 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bio_rdp_tls_free()

static int bio_rdp_tls_free ( BIO *  bio)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bio_rdp_tls_gets()

static int bio_rdp_tls_gets ( BIO *  bio,
char *  str,
int  size 
)
static
Here is the caller graph for this function:

◆ bio_rdp_tls_new()

static int bio_rdp_tls_new ( BIO *  bio)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bio_rdp_tls_puts()

static int bio_rdp_tls_puts ( BIO *  bio,
const char *  str 
)
static
Here is the caller graph for this function:

◆ bio_rdp_tls_read()

static int bio_rdp_tls_read ( BIO *  bio,
char *  buf,
int  size 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bio_rdp_tls_write()

static int bio_rdp_tls_write ( BIO *  bio,
const char *  buf,
int  size 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BIO_s_rdp_tls()

static BIO_METHOD* BIO_s_rdp_tls ( void  )
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ compare_fingerprint()

static BOOL compare_fingerprint ( const char *  fp,
const char *  hash,
const rdpCertificate *  cert,
BOOL  separator 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ compare_fingerprint_all()

static BOOL compare_fingerprint_all ( const char *  fp,
const char *  hash,
const rdpCertificate *  cert 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_tls_bindings()

static void free_tls_bindings ( rdpTls *  tls)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_tls_public_key()

static void free_tls_public_key ( rdpTls *  tls)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_tls_accept()

BOOL freerdp_tls_accept ( rdpTls *  tls,
BIO *  underlying,
rdpSettings *  settings 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_tls_accept_ex()

TlsHandshakeResult freerdp_tls_accept_ex ( rdpTls *  tls,
BIO *  underlying,
rdpSettings *  settings,
const SSL_METHOD *  methods 
)

SSL_OP_NO_SSLv2:

We only want SSLv3 and TLSv1, so disable SSLv2. SSLv3 is used by, eg. Microsoft RDC for Mac OS X.

SSL_OP_NO_COMPRESSION:

The Microsoft RDP server does not advertise support for TLS compression, but alternative servers may support it. This was observed between early versions of the FreeRDP server and the FreeRDP client, and caused major performance issues, which is why we're disabling it.

SSL_OP_TLS_BLOCK_PADDING_BUG:

The Microsoft RDP server does not support TLS padding. It absolutely needs to be disabled otherwise it won't work.

SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:

Just like TLS padding, the Microsoft RDP server does not support empty fragments. This needs to be disabled.

SSL_OP_NO_RENEGOTIATION

Disable SSL client site renegotiation.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_tls_connect()

int freerdp_tls_connect ( rdpTls *  tls,
BIO *  underlying 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_tls_connect_ex()

TlsHandshakeResult freerdp_tls_connect_ex ( rdpTls *  tls,
BIO *  underlying,
const SSL_METHOD *  methods 
)

SSL_OP_NO_COMPRESSION:

The Microsoft RDP server does not advertise support for TLS compression, but alternative servers may support it. This was observed between early versions of the FreeRDP server and the FreeRDP client, and caused major performance issues, which is why we're disabling it.

SSL_OP_TLS_BLOCK_PADDING_BUG:

The Microsoft RDP server does not support TLS padding. It absolutely needs to be disabled otherwise it won't work.

SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:

Just like TLS padding, the Microsoft RDP server does not support empty fragments. This needs to be disabled.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_tls_free()

void freerdp_tls_free ( rdpTls *  tls)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_tls_get_ssl_method()

const SSL_METHOD* freerdp_tls_get_ssl_method ( BOOL  isDtls,
BOOL  isClient 
)
Here is the caller graph for this function:

◆ freerdp_tls_handshake()

TlsHandshakeResult freerdp_tls_handshake ( rdpTls *  tls)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_tls_new()

rdpTls* freerdp_tls_new ( rdpSettings *  settings)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_tls_send_alert()

BOOL freerdp_tls_send_alert ( rdpTls *  tls)

FIXME: The following code does not work on OpenSSL > 1.1.0 because the SSL struct is opaqe now

OpenSSL doesn't really expose an API for sending a TLS alert manually.

The following code disables the sending of the default "close notify" and then proceeds to force sending a custom TLS alert before shutting down.

Manually sending a TLS alert is necessary in certain cases, like when server-side NLA results in an authentication failure.

Here is the caller graph for this function:

◆ freerdp_tls_set_alert_code()

int freerdp_tls_set_alert_code ( rdpTls *  tls,
int  level,
int  description 
)
Here is the caller graph for this function:

◆ freerdp_tls_write_all()

int freerdp_tls_write_all ( rdpTls *  tls,
const BYTE data,
int  length 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_accepted()

static BOOL is_accepted ( rdpTls *  tls,
const BYTE pem,
size_t  length 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_accepted_fingerprint()

static BOOL is_accepted_fingerprint ( const rdpCertificate *  cert,
const char *  CertificateAcceptedFingerprints 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_redirected()

static BOOL is_redirected ( rdpTls *  tls)
static
Here is the caller graph for this function:

◆ pollAndHandshake()

static int pollAndHandshake ( rdpTls *  tls)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ secrets_file_init_cb()

static BOOL CALLBACK secrets_file_init_cb ( PINIT_ONCE  once,
PVOID  param,
PVOID *  context 
)
static
Here is the caller graph for this function:

◆ SSLCTX_keylog_cb()

static void SSLCTX_keylog_cb ( const SSL *  ssl,
const char *  line 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tls_extract_pem()

static BOOL tls_extract_pem ( const rdpCertificate *  cert,
BYTE **  PublicKey,
size_t *  PublicKeyLength 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tls_get_certificate()

static rdpCertificate* tls_get_certificate ( rdpTls *  tls,
BOOL  peer 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tls_get_channel_bindings()

static SecPkgContext_Bindings* tls_get_channel_bindings ( const rdpCertificate *  cert)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tls_get_server_name()

static const char* tls_get_server_name ( rdpTls *  tls)
static
Here is the caller graph for this function:

◆ tls_match_hostname()

static BOOL tls_match_hostname ( const char *  pattern,
const size_t  pattern_length,
const char *  hostname 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tls_prepare()

static BOOL tls_prepare ( rdpTls *  tls,
BIO *  underlying,
SSL_METHOD *  method,
int  options,
BOOL  clientMode 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tls_print_certificate_error()

void tls_print_certificate_error ( rdpCertificateStore *  store,
rdpCertificateData *  stored_data,
const char *  hostname,
UINT16  port,
const char *  fingerprint 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tls_print_certificate_name_mismatch_error()

void tls_print_certificate_name_mismatch_error ( const char *  hostname,
UINT16  port,
const char *  common_name,
char **  alt_names,
size_t  alt_names_count 
)
static
Here is the caller graph for this function:

◆ tls_print_new_certificate_warn()

void tls_print_new_certificate_warn ( rdpCertificateStore *  store,
const char *  hostname,
UINT16  port,
const char *  fingerprint 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tls_reset()

static void tls_reset ( rdpTls *  tls)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tls_verify_certificate()

int tls_verify_certificate ( rdpTls *  tls,
const rdpCertificate *  cert,
const char *  hostname,
UINT16  port 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ secrets_file_idx

int secrets_file_idx = -1
static

◆ secrets_file_idx_once

INIT_ONCE secrets_file_idx_once = INIT_ONCE_STATIC_INIT
static