![]() |
libfilezilla
|
A Transport Layer Security (TLS) layer. More...
#include <tls_layer.hpp>
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={}) |
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) |
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 |
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. More... | |
![]() | |
socket_layer (event_handler *handler, socket_interface &next_layer, bool event_passthrough) | |
socket_layer (socket_layer const &)=delete | |
socket_layer & | operator= (socket_layer const &)=delete |
virtual void | set_event_handler (event_handler *handler, fz::socket_event_flag retrigger_block=fz::socket_event_flag{}) override |
The handler for any events generated (or forwarded) by this layer. More... | |
virtual native_string | peer_host () const override |
virtual int | peer_port (int &error) const override |
socket_interface & | next () |
The next layer further down. Usually another layer or the actual socket. | |
virtual int | shutdown_read () override |
Check that all layers further down also have reached EOF. More... | |
virtual int | connect (native_string const &host, unsigned int port, address_type family=address_type::unknown) override |
virtual int | shutdown () override |
Signals peers that we want to close the connections. More... | |
virtual socket_state | get_state () const override |
![]() | |
socket_interface (socket_interface const &)=delete | |
socket_interface & | operator= (socket_interface const &)=delete |
virtual int | read (void *buffer, unsigned int size, int &error)=0 |
virtual int | write (void const *buffer, unsigned int size, int &error)=0 |
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) |
virtual void | set_event_handler (event_handler *pEvtHandler, fz::socket_event_flag retrigger_block=fz::socket_event_flag{})=0 |
virtual native_string | peer_host () const =0 |
virtual int | peer_port (int &error) const =0 |
virtual int | connect (native_string const &host, unsigned int port, address_type family=address_type::unknown)=0 |
virtual fz::socket_state | get_state () const =0 |
virtual int | shutdown ()=0 |
Signals peers that we want to close the connections. More... | |
virtual int | shutdown_read ()=0 |
![]() | |
socket_event_source * | root () 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... | |
Friends | |
class | tls_layer_impl |
Additional Inherited Members | |
![]() | |
event_handler (event_loop &loop) | |
event_handler (event_handler const &h) | |
event_handler & | operator= (event_handler const &)=delete |
void | remove_handler () |
Deactivates handler, removes all pending events and stops all timers for this handler. More... | |
virtual void | operator() (event_base const &)=0 |
Called by the event loop in the worker thread with the event to process. 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 (duration const &interval, bool one_shot) |
Adds a timer, returns the timer id. More... | |
void | stop_timer (timer_id id) |
![]() | |
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_layer & | operator= (socket_layer const &)=delete |
virtual void | set_event_handler (event_handler *handler, fz::socket_event_flag retrigger_block=fz::socket_event_flag{}) override |
The handler for any events generated (or forwarded) by this layer. More... | |
virtual native_string | peer_host () const override |
virtual int | peer_port (int &error) const override |
socket_interface & | next () |
The next layer further down. Usually another layer or the actual socket. | |
virtual int | shutdown_read () override |
Check that all layers further down also have reached EOF. More... | |
virtual int | connect (native_string const &host, unsigned int port, address_type family=address_type::unknown) override |
virtual int | shutdown () override |
Signals peers that we want to close the connections. More... | |
virtual socket_state | get_state () const override |
![]() | |
socket_interface (socket_event_source *root) | |
socket_interface (socket_interface const &)=delete | |
socket_interface & | operator= (socket_interface const &)=delete |
virtual int | read (void *buffer, unsigned int size, int &error)=0 |
virtual int | write (void const *buffer, unsigned int size, int &error)=0 |
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) |
virtual void | set_event_handler (event_handler *pEvtHandler, fz::socket_event_flag retrigger_block=fz::socket_event_flag{})=0 |
virtual native_string | peer_host () const =0 |
virtual int | peer_port (int &error) const =0 |
virtual int | connect (native_string const &host, unsigned int port, address_type family=address_type::unknown)=0 |
virtual fz::socket_state | get_state () const =0 |
virtual int | shutdown ()=0 |
Signals peers that we want to close the connections. More... | |
virtual int | shutdown_read ()=0 |
![]() | |
socket_event_source (socket_event_source *root) | |
socket_event_source * | root () const |
Gets the root source. More... | |
![]() | |
event_loop & | event_loop_ |
![]() | |
event_handler * | event_handler_ {} |
socket_interface & | next_layer_ |
bool | event_passthrough_ {} |
![]() | |
socket_event_source *const | root_ {} |
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.
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.
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.
|
overridevirtual |
Reimplemented from socket_layer.
|
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.
|
overridevirtual |
Reimplemented from socket_layer.
|
overridevirtual |
Implements socket_interface.
bool server_handshake | ( | std::vector< uint8_t > const & | session_to_resume = {} , |
std::string_view const & | preamble = {} |
||
) |
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
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.
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.
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.
|
overridevirtual |
The handler for any events generated (or forwarded) by this layer.
Reimplemented from socket_layer.
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.
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.
|
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.
|
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.
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.
|
overridevirtual |
Implements socket_interface.