25#ifndef JOIN_CRYPTO_TLS_HPP
26#define JOIN_CRYPTO_TLS_HPP
53 template <
class Protocol>
58 using Mode =
typename UnderlyingSocket::Mode;
59 using Option =
typename UnderlyingSocket::Option;
60 using State =
typename UnderlyingSocket::State;
62 using TimePoint =
typename UnderlyingSocket::TimePoint;
112 :
_socket (std::move (other._socket))
113 ,
_ctx (std::move (other._ctx))
114 ,
_ssl (std::move (other._ssl))
118 SSL_set_app_data (
_ssl.get (),
this);
129 _socket = std::move (other._socket);
130 _ctx = std::move (other._ctx);
131 _ssl = std::move (other._ssl);
135 SSL_set_app_data (
_ssl.get (),
this);
153 return _socket.open (
typename Protocol::Transport (
protocol.family ()));
182 return _socket.bindToDevice (dev);
219 if (
_socket.type () == SOCK_DGRAM)
234 if (
_socket.type () == SOCK_STREAM)
252 if (
_socket.type () == SOCK_DGRAM)
254 BIO* bio = BIO_new_dgram (
_socket.handle (), BIO_NOCLOSE);
264 BIO_ctrl (bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0,
265 const_cast<struct sockaddr*
> (
_socket.remoteEndpoint ().addr ()));
268 SSL_set_bio (
_ssl.get (), bio, bio);
269 SSL_set_read_ahead (
_ssl.get (), 1);
273 if (SSL_set_fd (
_ssl.get (),
_socket.handle ()) == 0)
281 if (SSL_is_server (
_ssl.get ()))
283 SSL_set_accept_state (
_ssl.get ());
287 const std::string& host =
_socket.remoteEndpoint ().hostname ();
288 if (!host.empty () && SSL_set_tlsext_host_name (
_ssl.get (), host.c_str ()) != 1)
295 SSL_set_connect_state (
_ssl.get ());
298 SSL_set_app_data (
_ssl.get (),
this);
310 SSL_set_verify (
_ssl.get (), SSL_VERIFY_NONE,
nullptr);
333 int result = SSL_do_handshake (
_ssl.get ());
363 return waitHandshake (std::chrono::steady_clock::now () + timeout);
384 const bool isDtls = (
_socket.type () == SOCK_DGRAM);
388 bool wantRead = SSL_want_read (
_ssl.get ());
389 bool wantWrite = SSL_want_write (
_ssl.get ());
391 if (!wantRead && !wantWrite)
400 struct timeval dtlsTimeout;
401 if (DTLSv1_get_timeout (
_ssl.get (), &dtlsTimeout))
403 activeDeadline = std::min (activeDeadline, std::chrono::steady_clock::now () +
404 std::chrono::seconds (dtlsTimeout.tv_sec) +
405 std::chrono::microseconds (dtlsTimeout.tv_usec));
409 if (
_socket.waitUntil (wantRead, wantWrite, activeDeadline) == -1)
412 (std::chrono::steady_clock::now () < deadline))
414 int ret = DTLSv1_handle_timeout (
_ssl.get ());
452 return _ssl !=
nullptr && SSL_is_init_finished (
_ssl.get ());
466 if ((SSL_get_shutdown (
_ssl.get ()) & SSL_SENT_SHUTDOWN) == 0)
468 int result = SSL_shutdown (
_ssl.get ());
475 if (
_socket.type () == SOCK_DGRAM)
477 if ((SSL_get_shutdown (
_ssl.get ()) & SSL_RECEIVED_SHUTDOWN) == 0)
479 int result = SSL_shutdown (
_ssl.get ());
511 return waitShutdown (std::chrono::steady_clock::now () + timeout);
539 bool wantRead = SSL_want_read (
_ssl.get ());
540 bool wantWrite = SSL_want_write (
_ssl.get ());
542 if (!wantRead && !wantWrite)
547 if (
_socket.waitUntil (wantRead, wantWrite, deadline) == -1)
595 return waitReadyRead (std::chrono::steady_clock::now () + timeout);
605 bool wantRead =
true;
606 bool wantWrite =
false;
608 if (
_ssl && (SSL_want_read (
_ssl.get ()) || SSL_want_write (
_ssl.get ())))
610 wantRead = SSL_want_read (
_ssl.get ());
611 wantWrite = SSL_want_write (
_ssl.get ());
614 return (
_socket.waitUntil (wantRead, wantWrite, deadline) == 0);
623 ssize_t
read (
char* buf,
size_t len)
noexcept
627 int nread = SSL_read (
_ssl.get (), buf,
static_cast<int> (len));
636 return _socket.read (buf, len);
647 return readExactly (data, size, TimePoint::max ());
657 int readExactly (
char* data,
size_t size, std::chrono::nanoseconds timeout)
659 return readExactly (data, size, std::chrono::steady_clock::now () + timeout);
679 while (numRead < size)
681 ssize_t result =
read (data + numRead, size - numRead);
717 return waitReadyWrite (std::chrono::steady_clock::now () + timeout);
727 bool wantRead =
false;
728 bool wantWrite =
true;
730 if (
_ssl && (SSL_want_read (
_ssl.get ()) || SSL_want_write (
_ssl.get ())))
732 wantRead = SSL_want_read (
_ssl.get ());
733 wantWrite = SSL_want_write (
_ssl.get ());
736 return (
_socket.waitUntil (wantRead, wantWrite, deadline) == 0);
745 ssize_t
write (
const char* buf,
size_t len)
noexcept
749 int nwritten = SSL_write (
_ssl.get (), buf,
static_cast<int> (len));
758 return _socket.write (buf, len);
779 int writeExactly (
const char* data,
size_t size, std::chrono::nanoseconds timeout)
781 return writeExactly (data, size, std::chrono::steady_clock::now () + timeout);
801 while (numWrite < size)
803 ssize_t result =
write (data + numWrite, size - numWrite);
840 return _socket.setOption (opt, val);
894 return _socket.localEndpoint ();
904 return _socket.remoteEndpoint ();
915 switch (SSL_get_error (
_ssl.get (), result))
917 case SSL_ERROR_WANT_READ:
918 case SSL_ERROR_WANT_WRITE:
919 case SSL_ERROR_WANT_X509_LOOKUP:
924 case SSL_ERROR_ZERO_RETURN:
930 case SSL_ERROR_SYSCALL:
932 if (errno == 0 || errno == ECONNRESET || errno == EPIPE)
938 lastError = std::error_code (errno, std::generic_category ());
945 std::cout << ERR_reason_error_string (ERR_get_error ()) << std::endl;
960 static void infoWrapper (
const SSL* ssl,
int where,
int ret)
noexcept
973 if (where & SSL_CB_ALERT)
975 std::cout <<
"SSL/TLS Alert ";
976 (where & SSL_CB_READ) ? std::cout <<
"[read] " : std::cout <<
"[write] ";
977 std::cout << SSL_alert_type_string_long (ret) <<
":";
978 std::cout << SSL_alert_desc_string_long (ret);
979 std::cout << std::endl;
981 else if (where & SSL_CB_LOOP)
983 std::cout <<
"SSL/TLS State ";
984 (SSL_in_connect_init (
_ssl.get ())) ? std::cout <<
"[connect] "
985 : (SSL_in_accept_init (
_ssl.get ())) ? std::cout <<
"[accept] "
986 : std::cout <<
"[undefined] ";
987 std::cout << SSL_state_string_long (
_ssl.get ());
988 std::cout << std::endl;
990 else if (where & SSL_CB_HANDSHAKE_START)
992 std::cout <<
"SSL/TLS Handshake [Start] " << SSL_state_string_long (
_ssl.get ()) << std::endl;
994 else if (where & SSL_CB_HANDSHAKE_DONE)
996 std::cout <<
"SSL/TLS Handshake [Done] " << SSL_state_string_long (
_ssl.get ()) << std::endl;
997 std::cout << SSL_CTX_sess_number (
_ctx.
handle ()) <<
" items in the session cache" << std::endl;
998 std::cout << SSL_CTX_sess_connect (
_ctx.
handle ()) <<
" client connects" << std::endl;
999 std::cout << SSL_CTX_sess_connect_good (
_ctx.
handle ()) <<
" client connects that finished"
1001 std::cout << SSL_CTX_sess_connect_renegotiate (
_ctx.
handle ()) <<
" client renegotiations requested"
1003 std::cout << SSL_CTX_sess_accept (
_ctx.
handle ()) <<
" server connects" << std::endl;
1004 std::cout << SSL_CTX_sess_accept_good (
_ctx.
handle ()) <<
" server connects that finished" << std::endl;
1005 std::cout << SSL_CTX_sess_accept_renegotiate (
_ctx.
handle ()) <<
" server renegotiations requested"
1007 std::cout << SSL_CTX_sess_hits (
_ctx.
handle ()) <<
" session cache hits" << std::endl;
1008 std::cout << SSL_CTX_sess_cb_hits (
_ctx.
handle ()) <<
" external session cache hits" << std::endl;
1009 std::cout << SSL_CTX_sess_misses (
_ctx.
handle ()) <<
" session cache misses" << std::endl;
1010 std::cout << SSL_CTX_sess_timeouts (
_ctx.
handle ()) <<
" session cache timeouts" << std::endl;
1011 std::cout <<
"negotiated " << SSL_get_cipher (
_ssl.get ()) <<
" cipher suite" << std::endl;
1023 SSL* ssl =
static_cast<SSL*
> (X509_STORE_CTX_get_ex_data (x509Ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()));
1036 int maxDepth = SSL_get_verify_depth (
_ssl.get ());
1037 int dpth = X509_STORE_CTX_get_error_depth (context);
1040 std::cout <<
"verification started at depth=" << dpth << std::endl;
1044 if ((maxDepth >= 0) && (dpth > maxDepth))
1047 X509_STORE_CTX_set_error (context, X509_V_ERR_CERT_CHAIN_TOO_LONG);
1053 std::cout <<
"verification failed at depth=" << dpth <<
" - "
1054 << X509_verify_cert_error_string (X509_STORE_CTX_get_error (context)) << std::endl;
1063 std::cout <<
"rejected by CERT at depth=" << dpth << std::endl;
1087 std::cout <<
"certificate accepted at depth=" << dpth << std::endl;
1100 int depth = X509_STORE_CTX_get_error_depth (context);
1101 X509* cert = X509_STORE_CTX_get_current_cert (context);
1104 X509_NAME_oneline (X509_get_subject_name (cert), buf,
sizeof (buf));
1106 std::cout <<
"subject=" << buf << std::endl;
1116 std::cout <<
"no match for hostname in the certificate" << std::endl;
1135 std::string serverName (
_socket.remoteEndpoint ().hostname ());
1138 if (!serverName.empty () && serverName.back () ==
'.')
1140 serverName.pop_back ();
1145 X509_get_ext_d2i (certificate, NID_subject_alt_name, 0, 0)));
1148 for (
int i = 0; (i < sk_GENERAL_NAME_num (altnames.get ())) && !match; ++i)
1151 GENERAL_NAME* current_name = sk_GENERAL_NAME_value (altnames.get (), i);
1153 if (current_name->type == GEN_DNS)
1156 const char* host =
reinterpret_cast<const char*
> (ASN1_STRING_get0_data (current_name->d.ia5));
1157 size_t len = size_t (ASN1_STRING_length (current_name->d.ia5));
1158 std::string pattern (host, host + len);
1161 if (!pattern.empty () && pattern.back () ==
'.')
1163 pattern.pop_back ();
1167 if (fnmatch (pattern.c_str (), serverName.c_str (), 0) == 0)
1215 template <
class Protocol>
1218 return a.handle () == b.handle ();
1227 template <
class Protocol>
1230 return a.handle () <=> b.handle ();
basic TLS/DTLS decorator.
Definition tls.hpp:55
bool waitReadyRead(TimePoint deadline) const noexcept
block until new data is available for reading, giving up at the given time point.
Definition tls.hpp:603
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:657
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:88
ssize_t read(char *buf, size_t len) noexcept
read data from the TLS stream.
Definition tls.hpp:623
int handshake()
perform the TLS handshake.
Definition tls.hpp:321
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:791
bool waitHandshake()
block until TLS handshake is finished.
Definition tls.hpp:351
bool waitReadyRead() const noexcept
block until new data is available for reading.
Definition tls.hpp:583
BasicTls(UnderlyingSocket &&socket) noexcept
create a TLS decorator taking ownership of the given socket, without context.
Definition tls.hpp:78
BasicTls(BasicTls &&other) noexcept
move constructor.
Definition tls.hpp:111
typename UnderlyingSocket::State State
Definition tls.hpp:60
int type() const noexcept
get the underlying socket type.
Definition tls.hpp:865
typename Protocol::Transport::Socket UnderlyingSocket
Definition tls.hpp:57
bool opened() const noexcept
check if the underlying socket is opened.
Definition tls.hpp:160
bool waitHandshake(std::chrono::nanoseconds timeout)
block until TLS handshake is finished, giving up after the given duration.
Definition tls.hpp:361
void infoCallback(int where, int ret) const noexcept
SSL state info callback.
Definition tls.hpp:971
int bind(const Endpoint &ep) noexcept
assigns the specified endpoint to the underlying socket.
Definition tls.hpp:170
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:725
virtual bool waitHandshake(TimePoint deadline)
block until TLS handshake is finished, giving up at the given time point.
Definition tls.hpp:371
BasicTls(TlsContext ctx, Mode mode=Mode::NonBlocking) noexcept
create a TLS decorator with an internally created socket.
Definition tls.hpp:69
Endpoint remoteEndpoint() const
get the remote endpoint.
Definition tls.hpp:902
int mtu() const noexcept
get the maximum transmission unit.
Definition tls.hpp:883
static int verifyWrapper(int preverified, X509_STORE_CTX *x509Ctx) noexcept
c style verify callback wrapper.
Definition tls.hpp:1021
bool waitShutdown(TimePoint deadline) noexcept
block until TLS shutdown is finished, giving up at the given time point.
Definition tls.hpp:519
bool waitShutdown(std::chrono::nanoseconds timeout) noexcept
block until TLS shutdown is finished, giving up after the given duration.
Definition tls.hpp:509
int open(const Protocol &protocol=Protocol()) noexcept
open the underlying socket using the given protocol.
Definition tls.hpp:151
int readExactly(char *data, size_t size)
read data until size is reached or an error occurred.
Definition tls.hpp:645
TlsContext _ctx
TLS context.
Definition tls.hpp:1203
int handleTlsError(int result) noexcept
handle TLS error.
Definition tls.hpp:913
bool waitShutdown() noexcept
block until TLS shutdown is finished.
Definition tls.hpp:499
bool encrypted() const noexcept
check if the stream is encrypted.
Definition tls.hpp:450
UnderlyingSocket _socket
verify certificate revocation using CRL.
Definition tls.hpp:1200
typename UnderlyingSocket::Mode Mode
Definition tls.hpp:58
typename Protocol::Endpoint Endpoint
Definition tls.hpp:61
int disconnect() noexcept
disconnect the underlying socket from the remote endpoint.
Definition tls.hpp:565
int verifyCallback(int preverified, X509_STORE_CTX *context) noexcept
verify peer certificate.
Definition tls.hpp:1034
SslPtr _ssl
TLS handle.
Definition tls.hpp:1206
int deferHandshake()
set the TLS layer up without negotiating immediately.
Definition tls.hpp:209
static void infoWrapper(const SSL *ssl, int where, int ret) noexcept
c style info callback wrapper.
Definition tls.hpp:960
int setOption(Option opt, int val) noexcept
set an option for the underlying socket.
Definition tls.hpp:838
void setMode(Mode mode) noexcept
set the mode of the underlying socket.
Definition tls.hpp:827
int shutdown() noexcept
Perform the TLS shutdown.
Definition tls.hpp:459
int writeExactly(const char *data, size_t size)
write data until size is reached or an error occurred.
Definition tls.hpp:767
int verifyCert(X509_STORE_CTX *context) const
verify certificate validity.
Definition tls.hpp:1098
ssize_t write(const char *buf, size_t len) noexcept
write data to the TLS stream.
Definition tls.hpp:745
int protocol() const noexcept
get the underlying protocol.
Definition tls.hpp:874
Endpoint localEndpoint() const noexcept
get the local endpoint.
Definition tls.hpp:892
bool checkHostname(X509 *certificate) const noexcept
check certificate hostname against remote endpoint.
Definition tls.hpp:1130
typename UnderlyingSocket::Option Option
Definition tls.hpp:59
int handle() const noexcept
get the underlying socket handle.
Definition tls.hpp:847
int bindToDevice(const std::string &dev) noexcept
assigns the specified device to the underlying socket.
Definition tls.hpp:180
int connect(const Endpoint &ep) noexcept
connect the underlying socket to the remote endpoint.
Definition tls.hpp:191
bool waitReadyWrite() const noexcept
block until at least one byte can be written on the socket.
Definition tls.hpp:705
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:593
typename UnderlyingSocket::TimePoint TimePoint
Definition tls.hpp:62
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:779
void close() noexcept
close the socket handle.
Definition tls.hpp:573
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:715
bool connected() noexcept
check if the underlying socket is connected.
Definition tls.hpp:200
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:669
int family() const noexcept
get the underlying socket address family.
Definition tls.hpp:856
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
bool operator==(const BasicLinkLayerEndpoint< Protocol > &a, const BasicLinkLayerEndpoint< Protocol > &b) noexcept
compare if endpoints are equal.
Definition endpoint.hpp:196
std::unique_ptr< STACK_OF(GENERAL_NAME), StackOfGeneralNameDelete > StackOfGeneralNamePtr
Definition openssl.hpp:210
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
std::strong_ordering operator<=>(const BasicLinkLayerEndpoint< Protocol > &a, const BasicLinkLayerEndpoint< Protocol > &b) noexcept
three-way compare endpoints.
Definition endpoint.hpp:208
#define JOIN_UNLIKELY(x)
Definition utils.hpp:51