libfilezilla
Public Member Functions | Static Public Member Functions | Friends | List of all members
tls_layer Class Referencefinal

A Transport Layer Security (TLS) layer. More...

#include <tls_layer.hpp>

Inheritance diagram for tls_layer:
Inheritance graph
[legend]
Collaboration diagram for tls_layer:
Collaboration graph
[legend]

Public Member Functions

 tls_layer (event_loop &event_loop, event_handler *evt_handler, socket_interface &layer, tls_system_trust_store *system_trust_store, logger_interface &logger)
 
bool client_handshake (std::vector< uint8_t > const &required_certificate, std::vector< uint8_t > const &session_to_resume=std::vector< uint8_t >(), native_string const &session_hostname=native_string())
 Starts shaking hands for a new TLS session as client. More...
 
bool client_handshake (event_handler *const verification_handler, std::vector< uint8_t > const &session_to_resume=std::vector< uint8_t >(), native_string const &session_hostname=native_string())
 Starts shaking hands for a new TLS session as client. More...
 
bool server_handshake (std::vector< uint8_t > const &session_to_resume={}, std::string_view const &preamble={}, tls_server_flags flags={})
 Starts shaking hand for a new TLS session as server. More...
 
std::vector< uint8_t > get_session_parameters () const
 Gets session parameters for resumption.
 
std::vector< uint8_t > get_raw_certificate () const
 Gets the session's peer certificate in DER.
 
void set_verification_result (bool trusted)
 Must be called after having received certificate_verification_event. More...
 
std::string get_protocol () const
 
std::string get_key_exchange () const
 
std::string get_cipher () const
 
std::string get_mac () const
 
int get_algorithm_warnings () const
 
bool resumed_session () const
 After a successful handshake, returns whether the session has been resumed.
 
bool set_certificate_file (native_string const &keyfile, native_string const &certsfile, native_string const &password, bool pem=true)
 Sets the file containing the certificate (and its chain) and the file with the corresponding private key. More...
 
bool set_certificate (std::string_view const &key, std::string_view const &certs, native_string const &password, bool pem=true)
 Sets the certificate (and its chain) and the private key. More...
 
bool set_alpn (std::string_view const &alpn)
 Negotiate application protocol. More...
 
bool set_alpn (std::vector< std::string > const &alpns, bool server_priority=false)
 
void set_min_tls_ver (tls_ver ver)
 Sets minimum allowed TLS version.
 
void set_max_tls_ver (tls_ver ver)
 Sets maximum allowed TLS versions. More...
 
std::string get_alpn () const
 After a successful handshake, returns which protocol, if any, has been negotiated.
 
native_string get_hostname () const
 If running as server, get the SNI sent by the client.
 
bool is_server () const
 
int new_session_ticket ()
 If running as server with TLS1.3, send out a new session ticket before the next data payload. More...
 
void set_unexpected_eof_cb (std::function< bool()> const &cb)
 Sets a callback to control whether unexpected eof is seen as error. More...
 
void set_unexpected_eof_cb (std::function< bool()> &&cb)
 
virtual socket_state get_state () const override
 
virtual int connect (native_string const &host, unsigned int port, address_type family=address_type::unknown) override
 
virtual int read (void *buffer, unsigned int size, int &error) override
 
virtual int write (void const *buffer, unsigned int size, int &error) override
 
virtual int shutdown () override
 Signals peers that we want to close the connections. More...
 
virtual int shutdown_read () override
 Check that all layers further down also have reached EOF. More...
 
virtual void set_event_handler (event_handler *pEvtHandler, fz::socket_event_flag retrigger_block=socket_event_flag{}) override
 The handler for any events generated (or forwarded) by this layer.
 
- Public Member Functions inherited from socket_layer
 socket_layer (event_handler *handler, socket_interface &next_layer, bool event_passthrough)
 
 socket_layer (socket_layer const &)=delete
 
socket_layeroperator= (socket_layer const &)=delete
 
virtual native_string peer_host () const override
 
virtual int peer_port (int &error) const override
 
socket_interfacenext ()
 The next layer further down. Usually another layer or the actual socket.
 
- Public Member Functions inherited from socket_interface
 socket_interface (socket_interface const &)=delete
 
socket_interfaceoperator= (socket_interface const &)=delete
 
template<typename T , std::enable_if_t< std::is_signed_v< T >, int > = 0>
int read (void *buffer, T size, int &error)
 
template<typename T , std::enable_if_t< std::is_unsigned_v< T > &&(sizeof(T) > sizeof(unsigned int)), int > = 0>
int read (void *buffer, T size, int &error)
 
template<typename T , std::enable_if_t< std::is_signed_v< T >, int > = 0>
int write (void const *buffer, T size, int &error)
 
template<typename T , std::enable_if_t< std::is_unsigned_v< T > &&(sizeof(T) > sizeof(unsigned int)), int > = 0>
int write (void const *buffer, T size, int &error)
 
- Public Member Functions inherited from socket_event_source
socket_event_sourceroot () const
 Gets the root source. More...
 

Static Public Member Functions

static std::string list_tls_ciphers (std::string const &priority)
 Returns a human-readable list of all TLS ciphers available with the passed priority string.
 
static std::string get_gnutls_version ()
 Returns the version of the loaded GnuTLS library, may be different than the version used at compile-time.
 
static std::pair< std::string, std::string > generate_selfsigned_certificate (native_string const &password, std::string const &distinguished_name, std::vector< std::string > const &hostnames)
 Creates a new private key and a self-signed certificate. More...
 
static std::pair< std::string, std::string > generate_csr (native_string const &password, std::string const &distinguished_name, std::vector< std::string > const &hostnames, bool csr_as_pem=true)
 

Friends

class tls_layer_impl
 

Additional Inherited Members

- Protected Member Functions inherited from event_handler
 event_handler (event_loop &loop)
 
 event_handler (event_handler const &h)
 
event_handleroperator= (event_handler const &)=delete
 
void remove_handler ()
 Deactivates handler, removes all pending events and stops all timers for this handler. More...
 
template<typename T , typename... Args>
void send_event (Args &&... args)
 Sends the passed event asynchronously to the handler. More...
 
template<typename T >
void send_event (T *evt)
 
timer_id add_timer (monotonic_clock const &deadline, duration const &interval={})
 Adds a timer, returns the timer id. More...
 
timer_id add_timer (duration const &interval, bool one_shot)
 Adds a timer, returns the timer id. More...
 
void stop_timer (timer_id id)
 
timer_id stop_add_timer (timer_id id, monotonic_clock const &deadline, duration const &interval={})
 
timer_id stop_add_timer (timer_id id, duration const &interval, bool one_shot)
 
- Protected Member Functions inherited from socket_layer
void forward_socket_event (socket_event_source *source, socket_event_flag t, int error)
 
void forward_hostaddress_event (socket_event_source *source, std::string const &address)
 
void set_event_passthrough (socket_event_flag retrigger_block=socket_event_flag{})
 
 socket_layer (event_handler *handler, socket_interface &next_layer, bool event_passthrough)
 
 socket_layer (socket_layer const &)=delete
 
socket_layeroperator= (socket_layer const &)=delete
 
virtual native_string peer_host () const override
 
virtual int peer_port (int &error) const override
 
socket_interfacenext ()
 The next layer further down. Usually another layer or the actual socket.
 
- Protected Member Functions inherited from socket_interface
 socket_interface (socket_event_source *root)
 
 socket_interface (socket_interface const &)=delete
 
socket_interfaceoperator= (socket_interface const &)=delete
 
template<typename T , std::enable_if_t< std::is_signed_v< T >, int > = 0>
int read (void *buffer, T size, int &error)
 
template<typename T , std::enable_if_t< std::is_unsigned_v< T > &&(sizeof(T) > sizeof(unsigned int)), int > = 0>
int read (void *buffer, T size, int &error)
 
template<typename T , std::enable_if_t< std::is_signed_v< T >, int > = 0>
int write (void const *buffer, T size, int &error)
 
template<typename T , std::enable_if_t< std::is_unsigned_v< T > &&(sizeof(T) > sizeof(unsigned int)), int > = 0>
int write (void const *buffer, T size, int &error)
 
- Protected Member Functions inherited from socket_event_source
 socket_event_source (socket_event_source *root)
 
socket_event_sourceroot () const
 Gets the root source. More...
 
- Protected Attributes inherited from event_handler
event_loopevent_loop_
 
- Protected Attributes inherited from socket_layer
event_handlerevent_handler_ {}
 
socket_interfacenext_layer_
 
bool event_passthrough_ {}
 
- Protected Attributes inherited from socket_event_source
socket_event_source *const root_ {}
 

Detailed Description

A Transport Layer Security (TLS) layer.

Can be used both for client- and server-side TLS.

This class also supports TLS session resumption. Resumption has to be requested explicitly, there is no shared state between unrelated sessions.

Two trust models are possible with this class for client-side TLS: Certificates can either be evaluated against the system trust store, or you can implement a custom trust model such as TOFU.

Member Function Documentation

◆ client_handshake() [1/2]

bool client_handshake ( event_handler *const  verification_handler,
std::vector< uint8_t > const &  session_to_resume = std::vector< uint8_t >(),
native_string const &  session_hostname = native_string() 
)

Starts shaking hands for a new TLS session as client.

Returns true if the handshake has started, false on error.

If the handshake is started, wait for a connection event for the result.

If no verification handler is passed, verification is done solely using the system trust store.

If a verification handler is passed, it will receive a certificate_verification_event event upon which the handshake is paused until set_verification_result gets called including a tls_session_info structure. The handler is called even for certificates not trusted by the system trust store, allowing the following impairments: Unknown issuer, wrong hostname and certificates used outside their validity time.

◆ client_handshake() [2/2]

bool client_handshake ( std::vector< uint8_t > const &  required_certificate,
std::vector< uint8_t > const &  session_to_resume = std::vector< uint8_t >(),
native_string const &  session_hostname = native_string() 
)

Starts shaking hands for a new TLS session as client.

Returns true if the handshake has started, false on error.

If the handshake is started, wait for a connection event for the result.

The certificate that eventually gets negotiated for the session must match the passed required_certificate, either in DER or PEM, or the handshake will fail.

◆ generate_selfsigned_certificate()

static std::pair<std::string, std::string> generate_selfsigned_certificate ( native_string const &  password,
std::string const &  distinguished_name,
std::vector< std::string > const &  hostnames 
)
static

Creates a new private key and a self-signed certificate.

The distinguished name must be a RFC4514-compliant string.

If the password is non-empty, the private key gets encrypted using it.

The output pair is in PEM, first element is the key and the second the certificate.

◆ new_session_ticket()

int new_session_ticket ( )

If running as server with TLS1.3, send out a new session ticket before the next data payload.

Returns 0 on success, socket error otheerwise. Never returns EAGAIN.

It's a NOOP if TLS version != 1.3

Returns EINVAL if not server.

◆ server_handshake()

bool server_handshake ( std::vector< uint8_t > const &  session_to_resume = {},
std::string_view const &  preamble = {},
tls_server_flags  flags = {} 
)

Starts shaking hand for a new TLS session as server.

Returns true if the handshake has started, false on error.

If the handshake is started, wait for a connection event for the result.

Before calling server_handshake, a valid certificate and key must be passed in through set_certificate.

Session parameters of an existing session can be passed to allow session resumption. Check after handshake completion with resumed_session()

The preamble is sent out after setting up all the parameters, but before the first handshake message

◆ set_alpn()

bool set_alpn ( std::string_view const &  alpn)

Negotiate application protocol.

If the peer makes use of ALPN, the handshake fails if no matching protocol is found. If the peer does not use/support ALPN, the handshake continues and no protocol is negotiated.

Needs to be called prior to handshaking.

Which protocol is eventually chosen is always a server-side decsion. Iff running as server, server_priority controls the ALPN should be chosen based on the server's or the client's order in the list of ALPNs supported by both. server_priority is ignored if unning as client.

◆ set_certificate()

bool set_certificate ( std::string_view const &  key,
std::string_view const &  certs,
native_string const &  password,
bool  pem = true 
)

Sets the certificate (and its chain) and the private key.

For servers it is mandatory and is the certificate the server presents to the client.

For clients it is the optional client certificate.

If the pem flag is set, the input is assumed to be in PEM, otherwise DER.

◆ set_certificate_file()

bool set_certificate_file ( native_string const &  keyfile,
native_string const &  certsfile,
native_string const &  password,
bool  pem = true 
)

Sets the file containing the certificate (and its chain) and the file with the corresponding private key.

For servers a certificate is mandatory, it is presented to the client during the handshake.

For clients it is the optional client certificate.

If the pem flag is set, the input is assumed to be in PEM, otherwise DER.

◆ set_max_tls_ver()

void set_max_tls_ver ( tls_ver  ver)

Sets maximum allowed TLS versions.

Don't set a max version in production, it is for testing things.

◆ set_unexpected_eof_cb()

void set_unexpected_eof_cb ( std::function< bool()> const &  cb)

Sets a callback to control whether unexpected eof is seen as error.

With TLS, an EOF on the socket prior to receiving a closure alert normally is an error. In many cases this is harmless though, e.g. if the connection is idle.

If this callback is set, premature termination is no longer seen as error if the callback returns false.

Callback must not call any tls_layer function.

Only controls the layer's own logging. Functions such as read will still return ECONNABORTED.

◆ set_verification_result()

void set_verification_result ( bool  trusted)

Must be called after having received certificate_verification_event.

Can be used to trust a certificate even if it is not trusted via the system trust store.

◆ shutdown()

virtual int shutdown ( )
overridevirtual

Signals peers that we want to close the connections.

Only disallows further sends, does not affect reading from the socket.

Returns 0 on success, an error code otherwise. If it returns EGAIN, shutdown is not yet complete. Call shutdown again after the next write event.

Reimplemented from socket_layer.

◆ shutdown_read()

virtual int shutdown_read ( )
overridevirtual

Check that all layers further down also have reached EOF.

Can only be called after read has returned 0, calling it earlier is undefined. shutdown_read should be called after eof to ensure all layers have reached EOF.

Returns
0 on success
EAGAIN if the shutdown cannot be completed, wait for a read event and try again.
otherwise an error has occurred.

On an ordinary socket, this is a no-op. Some layers however may return an EOF before the next lower layer has reached its own EOF, such as the EOF of the secure channel from fz::tls_layer.

Closing the layer stack without all layers having reached EOF can lead to truncation on the write side: With a lower layer's EOF waiting in TCP's receive buffer and data pending in the send buffer, closing the socket is not graceful, it discards all pending data. Through shutdown_read you can assure that no pending data is left to receive, on this or any lower layer, so that closing the socket is done graceful ensuring delivery of all data in the send buffer (assuming there are no network errors).

Reimplemented from socket_layer.


The documentation for this class was generated from the following file: