25#ifndef JOIN_CRYPTO_TLS_HPP
26#define JOIN_CRYPTO_TLS_HPP
52 template <
class Protocol>
57 using Mode =
typename UnderlyingSocket::Mode;
58 using Option =
typename UnderlyingSocket::Option;
59 using State =
typename UnderlyingSocket::State;
61 using TimePoint =
typename UnderlyingSocket::TimePoint;
111 :
_socket (std::move (other._socket))
112 ,
_ctx (std::move (other._ctx))
113 ,
_ssl (std::move (other._ssl))
117 SSL_set_app_data (
_ssl.get (),
this);
128 _socket = std::move (other._socket);
129 _ctx = std::move (other._ctx);
130 _ssl = std::move (other._ssl);
134 SSL_set_app_data (
_ssl.get (),
this);
152 return _socket.open (
typename Protocol::Transport (
protocol.family ()));
181 return _socket.bindToDevice (dev);
218 if (
_socket.type () == SOCK_DGRAM)
233 if (
_socket.type () == SOCK_STREAM)
251 if (
_socket.type () == SOCK_DGRAM)
253 BIO* bio = BIO_new_dgram (
_socket.handle (), BIO_NOCLOSE);
263 BIO_ctrl (bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0,
264 const_cast<struct sockaddr*
> (
_socket.remoteEndpoint ().addr ()));
267 SSL_set_bio (
_ssl.get (), bio, bio);
268 SSL_set_read_ahead (
_ssl.get (), 1);
272 if (SSL_set_fd (
_ssl.get (),
_socket.handle ()) == 0)
280 if (SSL_is_server (
_ssl.get ()))
282 SSL_set_accept_state (
_ssl.get ());
286 const std::string& host =
_socket.remoteEndpoint ().hostname ();
287 if (!host.empty () && SSL_set_tlsext_host_name (
_ssl.get (), host.c_str ()) != 1)
294 SSL_set_connect_state (
_ssl.get ());
297 SSL_set_app_data (
_ssl.get (),
this);
309 SSL_set_verify (
_ssl.get (), SSL_VERIFY_NONE,
nullptr);
332 int result = SSL_do_handshake (
_ssl.get ());
362 return waitHandshake (std::chrono::steady_clock::now () + timeout);
383 const bool isDtls = (
_socket.type () == SOCK_DGRAM);
387 bool wantRead = SSL_want_read (
_ssl.get ());
388 bool wantWrite = SSL_want_write (
_ssl.get ());
390 if (!wantRead && !wantWrite)
399 struct timeval dtlsTimeout;
400 if (DTLSv1_get_timeout (
_ssl.get (), &dtlsTimeout))
402 activeDeadline = std::min (activeDeadline, std::chrono::steady_clock::now () +
403 std::chrono::seconds (dtlsTimeout.tv_sec) +
404 std::chrono::microseconds (dtlsTimeout.tv_usec));
408 if (
_socket.waitUntil (wantRead, wantWrite, activeDeadline) == -1)
411 (std::chrono::steady_clock::now () < deadline))
413 int ret = DTLSv1_handle_timeout (
_ssl.get ());
451 return _ssl !=
nullptr && SSL_is_init_finished (
_ssl.get ());
465 if ((SSL_get_shutdown (
_ssl.get ()) & SSL_SENT_SHUTDOWN) == 0)
467 int result = SSL_shutdown (
_ssl.get ());
474 if (
_socket.type () == SOCK_DGRAM)
476 if ((SSL_get_shutdown (
_ssl.get ()) & SSL_RECEIVED_SHUTDOWN) == 0)
478 int result = SSL_shutdown (
_ssl.get ());
510 return waitShutdown (std::chrono::steady_clock::now () + timeout);
538 bool wantRead = SSL_want_read (
_ssl.get ());
539 bool wantWrite = SSL_want_write (
_ssl.get ());
541 if (!wantRead && !wantWrite)
546 if (
_socket.waitUntil (wantRead, wantWrite, deadline) == -1)
594 return waitReadyRead (std::chrono::steady_clock::now () + timeout);
604 bool wantRead =
true;
605 bool wantWrite =
false;
607 if (
_ssl && (SSL_want_read (
_ssl.get ()) || SSL_want_write (
_ssl.get ())))
609 wantRead = SSL_want_read (
_ssl.get ());
610 wantWrite = SSL_want_write (
_ssl.get ());
613 return (
_socket.waitUntil (wantRead, wantWrite, deadline) == 0);
622 ssize_t
read (
char* buf,
size_t len)
noexcept
626 int nread = SSL_read (
_ssl.get (), buf,
static_cast<int> (len));
635 return _socket.read (buf, len);
646 return readExactly (data, size, TimePoint::max ());
656 int readExactly (
char* data,
size_t size, std::chrono::nanoseconds timeout)
658 return readExactly (data, size, std::chrono::steady_clock::now () + timeout);
678 while (numRead < size)
680 ssize_t result =
read (data + numRead, size - numRead);
716 return waitReadyWrite (std::chrono::steady_clock::now () + timeout);
726 bool wantRead =
false;
727 bool wantWrite =
true;
729 if (
_ssl && (SSL_want_read (
_ssl.get ()) || SSL_want_write (
_ssl.get ())))
731 wantRead = SSL_want_read (
_ssl.get ());
732 wantWrite = SSL_want_write (
_ssl.get ());
735 return (
_socket.waitUntil (wantRead, wantWrite, deadline) == 0);
744 ssize_t
write (
const char* buf,
size_t len)
noexcept
748 int nwritten = SSL_write (
_ssl.get (), buf,
static_cast<int> (len));
757 return _socket.write (buf, len);
778 int writeExactly (
const char* data,
size_t size, std::chrono::nanoseconds timeout)
780 return writeExactly (data, size, std::chrono::steady_clock::now () + timeout);
800 while (numWrite < size)
802 ssize_t result =
write (data + numWrite, size - numWrite);
839 return _socket.setOption (opt, val);
893 return _socket.localEndpoint ();
903 return _socket.remoteEndpoint ();
914 switch (SSL_get_error (
_ssl.get (), result))
916 case SSL_ERROR_WANT_READ:
917 case SSL_ERROR_WANT_WRITE:
918 case SSL_ERROR_WANT_X509_LOOKUP:
923 case SSL_ERROR_ZERO_RETURN:
929 case SSL_ERROR_SYSCALL:
931 if (errno == 0 || errno == ECONNRESET || errno == EPIPE)
937 lastError = std::error_code (errno, std::generic_category ());
944 std::cout << ERR_reason_error_string (ERR_get_error ()) << std::endl;
959 static void infoWrapper (
const SSL* ssl,
int where,
int ret)
noexcept
972 if (where & SSL_CB_ALERT)
974 std::cout <<
"SSL/TLS Alert ";
975 (where & SSL_CB_READ) ? std::cout <<
"[read] " : std::cout <<
"[write] ";
976 std::cout << SSL_alert_type_string_long (ret) <<
":";
977 std::cout << SSL_alert_desc_string_long (ret);
978 std::cout << std::endl;
980 else if (where & SSL_CB_LOOP)
982 std::cout <<
"SSL/TLS State ";
983 (SSL_in_connect_init (
_ssl.get ())) ? std::cout <<
"[connect] "
984 : (SSL_in_accept_init (
_ssl.get ())) ? std::cout <<
"[accept] "
985 : std::cout <<
"[undefined] ";
986 std::cout << SSL_state_string_long (
_ssl.get ());
987 std::cout << std::endl;
989 else if (where & SSL_CB_HANDSHAKE_START)
991 std::cout <<
"SSL/TLS Handshake [Start] " << SSL_state_string_long (
_ssl.get ()) << std::endl;
993 else if (where & SSL_CB_HANDSHAKE_DONE)
995 std::cout <<
"SSL/TLS Handshake [Done] " << SSL_state_string_long (
_ssl.get ()) << std::endl;
996 std::cout << SSL_CTX_sess_number (
_ctx.
handle ()) <<
" items in the session cache" << std::endl;
997 std::cout << SSL_CTX_sess_connect (
_ctx.
handle ()) <<
" client connects" << std::endl;
998 std::cout << SSL_CTX_sess_connect_good (
_ctx.
handle ()) <<
" client connects that finished"
1000 std::cout << SSL_CTX_sess_connect_renegotiate (
_ctx.
handle ()) <<
" client renegotiations requested"
1002 std::cout << SSL_CTX_sess_accept (
_ctx.
handle ()) <<
" server connects" << std::endl;
1003 std::cout << SSL_CTX_sess_accept_good (
_ctx.
handle ()) <<
" server connects that finished" << std::endl;
1004 std::cout << SSL_CTX_sess_accept_renegotiate (
_ctx.
handle ()) <<
" server renegotiations requested"
1006 std::cout << SSL_CTX_sess_hits (
_ctx.
handle ()) <<
" session cache hits" << std::endl;
1007 std::cout << SSL_CTX_sess_cb_hits (
_ctx.
handle ()) <<
" external session cache hits" << std::endl;
1008 std::cout << SSL_CTX_sess_misses (
_ctx.
handle ()) <<
" session cache misses" << std::endl;
1009 std::cout << SSL_CTX_sess_timeouts (
_ctx.
handle ()) <<
" session cache timeouts" << std::endl;
1010 std::cout <<
"negotiated " << SSL_get_cipher (
_ssl.get ()) <<
" cipher suite" << std::endl;
1022 SSL* ssl =
static_cast<SSL*
> (X509_STORE_CTX_get_ex_data (x509Ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()));
1035 int maxDepth = SSL_get_verify_depth (
_ssl.get ());
1036 int dpth = X509_STORE_CTX_get_error_depth (context);
1039 std::cout <<
"verification started at depth=" << dpth << std::endl;
1043 if ((maxDepth >= 0) && (dpth > maxDepth))
1046 X509_STORE_CTX_set_error (context, X509_V_ERR_CERT_CHAIN_TOO_LONG);
1052 std::cout <<
"verification failed at depth=" << dpth <<
" - "
1053 << X509_verify_cert_error_string (X509_STORE_CTX_get_error (context)) << std::endl;
1062 std::cout <<
"rejected by CERT at depth=" << dpth << std::endl;
1086 std::cout <<
"certificate accepted at depth=" << dpth << std::endl;
1099 int depth = X509_STORE_CTX_get_error_depth (context);
1100 X509* cert = X509_STORE_CTX_get_current_cert (context);
1103 X509_NAME_oneline (X509_get_subject_name (cert), buf,
sizeof (buf));
1105 std::cout <<
"subject=" << buf << std::endl;
1115 std::cout <<
"no match for hostname in the certificate" << std::endl;
1134 std::string serverName (
_socket.remoteEndpoint ().hostname ());
1137 if (!serverName.empty () && serverName.back () ==
'.')
1139 serverName.pop_back ();
1144 X509_get_ext_d2i (certificate, NID_subject_alt_name, 0, 0)));
1147 for (
int i = 0; (i < sk_GENERAL_NAME_num (altnames.get ())) && !match; ++i)
1150 GENERAL_NAME* current_name = sk_GENERAL_NAME_value (altnames.get (), i);
1152 if (current_name->type == GEN_DNS)
1155 const char* host =
reinterpret_cast<const char*
> (ASN1_STRING_get0_data (current_name->d.ia5));
1156 size_t len = size_t (ASN1_STRING_length (current_name->d.ia5));
1157 std::string pattern (host, host + len);
1160 if (!pattern.empty () && pattern.back () ==
'.')
1162 pattern.pop_back ();
1166 if (fnmatch (pattern.c_str (), serverName.c_str (), 0) == 0)
1214 template <
class Protocol>
1217 return a.handle () < b.handle ();
basic TLS/DTLS decorator.
Definition tls.hpp:54
bool waitReadyRead(TimePoint deadline) const noexcept
block until new data is available for reading, giving up at the given time point.
Definition tls.hpp:602
int readExactly(char *data, size_t size, std::chrono::nanoseconds timeout)
read data until size is reached, an error occurred or the given duration elapsed.
Definition tls.hpp:656
BasicTls(const BasicTls &other)=delete
copy constructor.
virtual ~BasicTls()=default
destroy the instance.
BasicTls(UnderlyingSocket &&socket, TlsContext ctx) noexcept
create a TLS decorator taking ownership of the given socket.
Definition tls.hpp:87
ssize_t read(char *buf, size_t len) noexcept
read data from the TLS stream.
Definition tls.hpp:622
int handshake()
perform the TLS handshake.
Definition tls.hpp:320
int writeExactly(const char *data, size_t size, TimePoint deadline)
write data until size is reached, an error occurred or the deadline expired.
Definition tls.hpp:790
bool waitHandshake()
block until TLS handshake is finished.
Definition tls.hpp:350
bool waitReadyRead() const noexcept
block until new data is available for reading.
Definition tls.hpp:582
BasicTls(UnderlyingSocket &&socket) noexcept
create a TLS decorator taking ownership of the given socket, without context.
Definition tls.hpp:77
BasicTls(BasicTls &&other) noexcept
move constructor.
Definition tls.hpp:110
typename UnderlyingSocket::State State
Definition tls.hpp:59
int type() const noexcept
get the underlying socket type.
Definition tls.hpp:864
typename Protocol::Transport::Socket UnderlyingSocket
Definition tls.hpp:56
bool opened() const noexcept
check if the underlying socket is opened.
Definition tls.hpp:159
bool waitHandshake(std::chrono::nanoseconds timeout)
block until TLS handshake is finished, giving up after the given duration.
Definition tls.hpp:360
void infoCallback(int where, int ret) const noexcept
SSL state info callback.
Definition tls.hpp:970
int bind(const Endpoint &ep) noexcept
assigns the specified endpoint to the underlying socket.
Definition tls.hpp:169
bool waitReadyWrite(TimePoint deadline) const noexcept
block until at least one byte can be written, giving up at the given time point.
Definition tls.hpp:724
virtual bool waitHandshake(TimePoint deadline)
block until TLS handshake is finished, giving up at the given time point.
Definition tls.hpp:370
BasicTls(TlsContext ctx, Mode mode=Mode::NonBlocking) noexcept
create a TLS decorator with an internally created socket.
Definition tls.hpp:68
Endpoint remoteEndpoint() const
get the remote endpoint.
Definition tls.hpp:901
int mtu() const noexcept
get the maximum transmission unit.
Definition tls.hpp:882
static int verifyWrapper(int preverified, X509_STORE_CTX *x509Ctx) noexcept
c style verify callback wrapper.
Definition tls.hpp:1020
bool waitShutdown(TimePoint deadline) noexcept
block until TLS shutdown is finished, giving up at the given time point.
Definition tls.hpp:518
bool waitShutdown(std::chrono::nanoseconds timeout) noexcept
block until TLS shutdown is finished, giving up after the given duration.
Definition tls.hpp:508
int open(const Protocol &protocol=Protocol()) noexcept
open the underlying socket using the given protocol.
Definition tls.hpp:150
int readExactly(char *data, size_t size)
read data until size is reached or an error occurred.
Definition tls.hpp:644
TlsContext _ctx
TLS context.
Definition tls.hpp:1202
int handleTlsError(int result) noexcept
handle TLS error.
Definition tls.hpp:912
bool waitShutdown() noexcept
block until TLS shutdown is finished.
Definition tls.hpp:498
bool encrypted() const noexcept
check if the stream is encrypted.
Definition tls.hpp:449
UnderlyingSocket _socket
verify certificate revocation using CRL.
Definition tls.hpp:1199
typename UnderlyingSocket::Mode Mode
Definition tls.hpp:57
typename Protocol::Endpoint Endpoint
Definition tls.hpp:60
int disconnect() noexcept
disconnect the underlying socket from the remote endpoint.
Definition tls.hpp:564
int verifyCallback(int preverified, X509_STORE_CTX *context) noexcept
verify peer certificate.
Definition tls.hpp:1033
SslPtr _ssl
TLS handle.
Definition tls.hpp:1205
int deferHandshake()
set the TLS layer up without negotiating immediately.
Definition tls.hpp:208
static void infoWrapper(const SSL *ssl, int where, int ret) noexcept
c style info callback wrapper.
Definition tls.hpp:959
int setOption(Option opt, int val) noexcept
set an option for the underlying socket.
Definition tls.hpp:837
void setMode(Mode mode) noexcept
set the mode of the underlying socket.
Definition tls.hpp:826
int shutdown() noexcept
Perform the TLS shutdown.
Definition tls.hpp:458
int writeExactly(const char *data, size_t size)
write data until size is reached or an error occurred.
Definition tls.hpp:766
int verifyCert(X509_STORE_CTX *context) const
verify certificate validity.
Definition tls.hpp:1097
ssize_t write(const char *buf, size_t len) noexcept
write data to the TLS stream.
Definition tls.hpp:744
int protocol() const noexcept
get the underlying protocol.
Definition tls.hpp:873
Endpoint localEndpoint() const noexcept
get the local endpoint.
Definition tls.hpp:891
bool checkHostname(X509 *certificate) const noexcept
check certificate hostname against remote endpoint.
Definition tls.hpp:1129
typename UnderlyingSocket::Option Option
Definition tls.hpp:58
int handle() const noexcept
get the underlying socket handle.
Definition tls.hpp:846
int bindToDevice(const std::string &dev) noexcept
assigns the specified device to the underlying socket.
Definition tls.hpp:179
int connect(const Endpoint &ep) noexcept
connect the underlying socket to the remote endpoint.
Definition tls.hpp:190
bool waitReadyWrite() const noexcept
block until at least one byte can be written on the socket.
Definition tls.hpp:704
BasicTls & operator=(const BasicTls &other)=delete
copy assignment operator.
bool waitReadyRead(std::chrono::nanoseconds timeout) const noexcept
block until new data is available for reading, giving up after the given duration.
Definition tls.hpp:592
typename UnderlyingSocket::TimePoint TimePoint
Definition tls.hpp:61
int writeExactly(const char *data, size_t size, std::chrono::nanoseconds timeout)
write data until size is reached, an error occurred or the given duration elapsed.
Definition tls.hpp:778
void close() noexcept
close the socket handle.
Definition tls.hpp:572
bool waitReadyWrite(std::chrono::nanoseconds timeout) const noexcept
block until at least one byte can be written on the socket, giving up after the given duration.
Definition tls.hpp:714
bool connected() noexcept
check if the underlying socket is connected.
Definition tls.hpp:199
int readExactly(char *data, size_t size, TimePoint deadline)
read data until size is reached, an error occurred or the deadline expired.
Definition tls.hpp:668
int family() const noexcept
get the underlying socket address family.
Definition tls.hpp:855
TLS/DTLS context.
Definition tls_context.hpp:42
bool isServer() const noexcept
check if the role is a server role.
Definition tls_context.cpp:340
bool verify() const noexcept
check if peer verification is enabled.
Definition tls_context.cpp:322
SSL_CTX * handle() const noexcept
get the native SSL_CTX handle.
Definition tls_context.cpp:313
int depth() const noexcept
get the maximum certificate chain depth.
Definition tls_context.cpp:331
Definition acceptor.hpp:32
std::unique_ptr< STACK_OF(GENERAL_NAME), StackOfGeneralNameDelete > StackOfGeneralNamePtr
Definition openssl.hpp:210
bool operator<(const BasicDatagramSocket< Protocol > &a, const BasicDatagramSocket< Protocol > &b) noexcept
compare if socket handle is inferior.
Definition datagram_socket.hpp:394
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
std::unique_ptr< SSL, SslDelete > SslPtr
Definition openssl.hpp:225
#define JOIN_UNLIKELY(x)
Definition utils.hpp:46