join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
tls.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_CRYPTO_TLS_HPP
26#define JOIN_CRYPTO_TLS_HPP
27
28// libjoin.
31#include <join/tls_protocol.hpp>
32#include <join/tls_context.hpp>
33#include <join/tls_error.hpp>
34#include <join/error.hpp>
35
36// C++.
37#include <algorithm>
38#include <iostream>
39#include <compare>
40#include <utility>
41#include <chrono>
42#include <string>
43
44// C.
45#include <fnmatch.h>
46#include <cassert>
47
48namespace join
49{
53 template <class Protocol>
55 {
56 public:
57 using UnderlyingSocket = typename Protocol::Transport::Socket;
58 using Mode = typename UnderlyingSocket::Mode;
59 using Option = typename UnderlyingSocket::Option;
60 using State = typename UnderlyingSocket::State;
61 using Endpoint = typename Protocol::Endpoint;
62 using TimePoint = typename UnderlyingSocket::TimePoint;
63
69 explicit BasicTls (TlsContext ctx, Mode mode = Mode::NonBlocking) noexcept
70 : BasicTls (UnderlyingSocket{mode}, ctx)
71 {
72 }
73
78 explicit BasicTls (UnderlyingSocket&& socket) noexcept
79 : _socket (std::move (socket))
80 {
81 }
82
88 BasicTls (UnderlyingSocket&& socket, TlsContext ctx) noexcept
89 : _socket (std::move (socket))
90 , _ctx (ctx)
91 {
92 }
93
98 BasicTls (const BasicTls& other) = delete;
99
105 BasicTls& operator= (const BasicTls& other) = delete;
106
111 BasicTls (BasicTls&& other) noexcept
112 : _socket (std::move (other._socket))
113 , _ctx (std::move (other._ctx))
114 , _ssl (std::move (other._ssl))
115 {
116 if (_ssl)
117 {
118 SSL_set_app_data (_ssl.get (), this);
119 }
120 }
121
127 BasicTls& operator= (BasicTls&& other) noexcept
128 {
129 _socket = std::move (other._socket);
130 _ctx = std::move (other._ctx);
131 _ssl = std::move (other._ssl);
132
133 if (_ssl)
134 {
135 SSL_set_app_data (_ssl.get (), this);
136 }
137
138 return *this;
139 }
140
144 virtual ~BasicTls () = default;
145
151 int open (const Protocol& protocol = Protocol ()) noexcept
152 {
153 return _socket.open (typename Protocol::Transport (protocol.family ()));
154 }
155
160 bool opened () const noexcept
161 {
162 return _socket.opened ();
163 }
164
170 int bind (const Endpoint& ep) noexcept
171 {
172 return _socket.bind (ep);
173 }
174
180 int bindToDevice (const std::string& dev) noexcept
181 {
182 return _socket.bindToDevice (dev);
183 }
184
191 int connect (const Endpoint& ep) noexcept
192 {
193 return _socket.connect (ep);
194 }
195
200 bool connected () noexcept
201 {
202 return _socket.connected ();
203 }
204
210 {
211 if (!_ctx.handle ())
212 {
214 return -1;
215 }
216
217 if (!_ssl)
218 {
219 if (_socket.type () == SOCK_DGRAM)
220 {
221 if (!_socket.opened ())
222 {
224 return -1;
225 }
226
227 if (!_ctx.isServer () && !_socket.connected ())
228 {
230 return -1;
231 }
232 }
233
234 if (_socket.type () == SOCK_STREAM)
235 {
236 if (!_socket.connected ())
237 {
239 return -1;
240 }
241 }
242
243 _ssl.reset (SSL_new (_ctx.handle ()));
244 if (!_ssl)
245 {
246 // LCOV_EXCL_START
248 return -1;
249 // LCOV_EXCL_STOP
250 }
251
252 if (_socket.type () == SOCK_DGRAM)
253 {
254 BIO* bio = BIO_new_dgram (_socket.handle (), BIO_NOCLOSE);
255 if (!bio)
256 {
258 _ssl.reset ();
259 return -1;
260 }
261
262 if (_socket.connected ())
263 {
264 BIO_ctrl (bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0,
265 const_cast<struct sockaddr*> (_socket.remoteEndpoint ().addr ()));
266 }
267
268 SSL_set_bio (_ssl.get (), bio, bio);
269 SSL_set_read_ahead (_ssl.get (), 1);
270 }
271 else
272 {
273 if (SSL_set_fd (_ssl.get (), _socket.handle ()) == 0)
274 {
276 _ssl.reset ();
277 return -1;
278 }
279 }
280
281 if (SSL_is_server (_ssl.get ()))
282 {
283 SSL_set_accept_state (_ssl.get ());
284 }
285 else
286 {
287 const std::string& host = _socket.remoteEndpoint ().hostname ();
288 if (!host.empty () && SSL_set_tlsext_host_name (_ssl.get (), host.c_str ()) != 1)
289 {
291 _ssl.reset ();
292 return -1;
293 }
294
295 SSL_set_connect_state (_ssl.get ());
296 }
297
298 SSL_set_app_data (_ssl.get (), this);
299#ifdef DEBUG
300 SSL_set_info_callback (_ssl.get (), infoWrapper);
301#endif
302
303 if (_ctx.verify ())
304 {
305 SSL_set_verify (_ssl.get (), SSL_VERIFY_PEER, verifyWrapper);
306 SSL_set_verify_depth (_ssl.get (), _ctx.depth ());
307 }
308 else
309 {
310 SSL_set_verify (_ssl.get (), SSL_VERIFY_NONE, nullptr);
311 }
312 }
313
314 return 0;
315 }
316
322 {
323 if (encrypted ())
324 {
325 return 0;
326 }
327
328 if (deferHandshake () == -1)
329 {
330 return -1;
331 }
332
333 int result = SSL_do_handshake (_ssl.get ());
334 if (result < 1)
335 {
336 int ret = handleTlsError (result);
337 if (lastError != make_error_code (Errc::TemporaryError))
338 {
339 _ssl.reset ();
340 }
341 return ret;
342 }
343
344 return 0;
345 }
346
352 {
353 return waitHandshake (TimePoint::max ());
354 }
355
361 bool waitHandshake (std::chrono::nanoseconds timeout)
362 {
363 return waitHandshake (std::chrono::steady_clock::now () + timeout);
364 }
365
371 virtual bool waitHandshake (TimePoint deadline)
372 {
373 if (JOIN_UNLIKELY ((deadline != TimePoint::max ()) && (_socket.mode () == Mode::Blocking)))
374 {
376 return false;
377 }
378
379 if (handshake () == 0)
380 {
381 return true;
382 }
383
384 const bool isDtls = (_socket.type () == SOCK_DGRAM);
385
386 while (lastError == make_error_code (Errc::TemporaryError))
387 {
388 bool wantRead = SSL_want_read (_ssl.get ());
389 bool wantWrite = SSL_want_write (_ssl.get ());
390
391 if (!wantRead && !wantWrite)
392 {
393 break; // LCOV_EXCL_LINE
394 }
395
396 TimePoint activeDeadline = deadline;
397
398 if (isDtls)
399 {
400 struct timeval dtlsTimeout;
401 if (DTLSv1_get_timeout (_ssl.get (), &dtlsTimeout))
402 {
403 activeDeadline = std::min (activeDeadline, std::chrono::steady_clock::now () +
404 std::chrono::seconds (dtlsTimeout.tv_sec) +
405 std::chrono::microseconds (dtlsTimeout.tv_usec));
406 }
407 }
408
409 if (_socket.waitUntil (wantRead, wantWrite, activeDeadline) == -1)
410 {
411 if (isDtls && (lastError == make_error_code (Errc::TimedOut)) &&
412 (std::chrono::steady_clock::now () < deadline))
413 {
414 int ret = DTLSv1_handle_timeout (_ssl.get ());
415 if (ret < 0)
416 {
418 return false;
419 }
420 else if (ret == 0)
421 {
422 continue;
423 }
424
426 if (handshake () == 0)
427 {
428 return true;
429 }
430
431 continue;
432 }
433
434 return false;
435 }
436
437 if (handshake () == 0)
438 {
439 return true;
440 }
441 }
442
443 return false;
444 }
445
450 bool encrypted () const noexcept
451 {
452 return _ssl != nullptr && SSL_is_init_finished (_ssl.get ());
453 }
454
459 int shutdown () noexcept
460 {
461 if (!_ssl)
462 {
463 return 0;
464 }
465
466 if ((SSL_get_shutdown (_ssl.get ()) & SSL_SENT_SHUTDOWN) == 0)
467 {
468 int result = SSL_shutdown (_ssl.get ());
469 if (result < 0)
470 {
471 return handleTlsError (result);
472 }
473 }
474
475 if (_socket.type () == SOCK_DGRAM)
476 {
477 if ((SSL_get_shutdown (_ssl.get ()) & SSL_RECEIVED_SHUTDOWN) == 0)
478 {
479 int result = SSL_shutdown (_ssl.get ());
480 if (result < 0)
481 {
482 handleTlsError (result);
483 if (lastError != Errc::ConnectionClosed && lastError != TlsErrc::TlsCloseNotifyAlert)
484 {
485 return -1;
486 }
487 }
488 }
489 }
490
491 _ssl.reset ();
492 return 0;
493 }
494
499 bool waitShutdown () noexcept
500 {
501 return waitShutdown (TimePoint::max ());
502 }
503
509 bool waitShutdown (std::chrono::nanoseconds timeout) noexcept
510 {
511 return waitShutdown (std::chrono::steady_clock::now () + timeout);
512 }
513
519 bool waitShutdown (TimePoint deadline) noexcept
520 {
521 if (JOIN_UNLIKELY ((deadline != TimePoint::max ()) && (_socket.mode () == Mode::Blocking)))
522 {
524 return false;
525 }
526
527 if (!_ssl)
528 {
529 return true;
530 }
531
532 if (shutdown () == 0)
533 {
534 return true;
535 }
536
537 while (lastError == make_error_code (Errc::TemporaryError))
538 {
539 bool wantRead = SSL_want_read (_ssl.get ());
540 bool wantWrite = SSL_want_write (_ssl.get ());
541
542 if (!wantRead && !wantWrite)
543 {
544 break; // LCOV_EXCL_LINE
545 }
546
547 if (_socket.waitUntil (wantRead, wantWrite, deadline) == -1)
548 {
549 return false;
550 }
551
552 if (shutdown () == 0)
553 {
554 return true;
555 }
556 }
557
558 return false;
559 }
560
565 int disconnect () noexcept
566 {
567 return _socket.disconnect ();
568 }
569
573 void close () noexcept
574 {
575 _ssl.reset ();
576 _socket.close ();
577 }
578
583 bool waitReadyRead () const noexcept
584 {
585 return waitReadyRead (TimePoint::max ());
586 }
587
593 bool waitReadyRead (std::chrono::nanoseconds timeout) const noexcept
594 {
595 return waitReadyRead (std::chrono::steady_clock::now () + timeout);
596 }
597
603 bool waitReadyRead (TimePoint deadline) const noexcept
604 {
605 bool wantRead = true;
606 bool wantWrite = false;
607
608 if (_ssl && (SSL_want_read (_ssl.get ()) || SSL_want_write (_ssl.get ())))
609 {
610 wantRead = SSL_want_read (_ssl.get ());
611 wantWrite = SSL_want_write (_ssl.get ());
612 }
613
614 return (_socket.waitUntil (wantRead, wantWrite, deadline) == 0);
615 }
616
623 ssize_t read (char* buf, size_t len) noexcept
624 {
625 if (_ssl)
626 {
627 int nread = SSL_read (_ssl.get (), buf, static_cast<int> (len));
628 if (nread < 1)
629 {
630 return handleTlsError (nread);
631 }
632
633 return nread;
634 }
635
636 return _socket.read (buf, len);
637 }
638
645 int readExactly (char* data, size_t size)
646 {
647 return readExactly (data, size, TimePoint::max ());
648 }
649
657 int readExactly (char* data, size_t size, std::chrono::nanoseconds timeout)
658 {
659 return readExactly (data, size, std::chrono::steady_clock::now () + timeout);
660 }
661
669 int readExactly (char* data, size_t size, TimePoint deadline)
670 {
671 if (JOIN_UNLIKELY ((deadline != TimePoint::max ()) && (_socket.mode () == Mode::Blocking)))
672 {
674 return -1;
675 }
676
677 size_t numRead = 0;
678
679 while (numRead < size)
680 {
681 ssize_t result = read (data + numRead, size - numRead);
682 if (result == -1)
683 {
684 if (lastError == Errc::TemporaryError)
685 {
686 if (waitReadyRead (deadline))
687 {
688 continue;
689 }
690 }
691
692 return -1;
693 }
694
695 numRead += result;
696 }
697
698 return 0;
699 }
700
705 bool waitReadyWrite () const noexcept
706 {
707 return waitReadyWrite (TimePoint::max ());
708 }
709
715 bool waitReadyWrite (std::chrono::nanoseconds timeout) const noexcept
716 {
717 return waitReadyWrite (std::chrono::steady_clock::now () + timeout);
718 }
719
725 bool waitReadyWrite (TimePoint deadline) const noexcept
726 {
727 bool wantRead = false;
728 bool wantWrite = true;
729
730 if (_ssl && (SSL_want_read (_ssl.get ()) || SSL_want_write (_ssl.get ())))
731 {
732 wantRead = SSL_want_read (_ssl.get ());
733 wantWrite = SSL_want_write (_ssl.get ());
734 }
735
736 return (_socket.waitUntil (wantRead, wantWrite, deadline) == 0);
737 }
738
745 ssize_t write (const char* buf, size_t len) noexcept
746 {
747 if (_ssl)
748 {
749 int nwritten = SSL_write (_ssl.get (), buf, static_cast<int> (len));
750 if (nwritten < 1)
751 {
752 return handleTlsError (nwritten);
753 }
754
755 return nwritten;
756 }
757
758 return _socket.write (buf, len);
759 }
760
767 int writeExactly (const char* data, size_t size)
768 {
769 return writeExactly (data, size, TimePoint::max ());
770 }
771
779 int writeExactly (const char* data, size_t size, std::chrono::nanoseconds timeout)
780 {
781 return writeExactly (data, size, std::chrono::steady_clock::now () + timeout);
782 }
783
791 int writeExactly (const char* data, size_t size, TimePoint deadline)
792 {
793 if (JOIN_UNLIKELY ((deadline != TimePoint::max ()) && (_socket.mode () == Mode::Blocking)))
794 {
796 return -1;
797 }
798
799 size_t numWrite = 0;
800
801 while (numWrite < size)
802 {
803 ssize_t result = write (data + numWrite, size - numWrite);
804 if (result == -1)
805 {
806 if (lastError == Errc::TemporaryError)
807 {
808 if (waitReadyWrite (deadline))
809 {
810 continue;
811 }
812 }
813
814 return -1;
815 }
816
817 numWrite += result;
818 }
819
820 return 0;
821 }
822
827 void setMode (Mode mode) noexcept
828 {
829 _socket.setMode (mode);
830 }
831
838 int setOption (Option opt, int val) noexcept
839 {
840 return _socket.setOption (opt, val);
841 }
842
847 int handle () const noexcept
848 {
849 return _socket.handle ();
850 }
851
856 int family () const noexcept
857 {
858 return _socket.family ();
859 }
860
865 int type () const noexcept
866 {
867 return _socket.type ();
868 }
869
874 int protocol () const noexcept
875 {
876 return _socket.protocol ();
877 }
878
883 int mtu () const noexcept
884 {
885 return _socket.mtu ();
886 }
887
892 Endpoint localEndpoint () const noexcept
893 {
894 return _socket.localEndpoint ();
895 }
896
903 {
904 return _socket.remoteEndpoint ();
905 }
906
907 protected:
913 int handleTlsError (int result) noexcept
914 {
915 switch (SSL_get_error (_ssl.get (), result))
916 {
917 case SSL_ERROR_WANT_READ:
918 case SSL_ERROR_WANT_WRITE:
919 case SSL_ERROR_WANT_X509_LOOKUP:
920 // want read, want write or want lookup.
922 break;
923
924 case SSL_ERROR_ZERO_RETURN:
925 // a close notify alert was received.
926 // we have to answer by sending a close notify alert too.
928 break;
929
930 case SSL_ERROR_SYSCALL:
931 // an error occurred at the socket level.
932 if (errno == 0 || errno == ECONNRESET || errno == EPIPE)
933 {
935 }
936 else
937 {
938 lastError = std::error_code (errno, std::generic_category ());
939 }
940 break;
941
942 default:
943 // SSL protocol error.
944#ifdef DEBUG
945 std::cout << ERR_reason_error_string (ERR_get_error ()) << std::endl;
946#endif
948 break;
949 }
950
951 return -1;
952 }
953
960 static void infoWrapper (const SSL* ssl, int where, int ret) noexcept
961 {
962 assert (ssl);
963 static_cast<BasicTls<Protocol>*> (SSL_get_app_data (ssl))->infoCallback (where, ret);
964 }
965
971 void infoCallback (int where, int ret) const noexcept
972 {
973 if (where & SSL_CB_ALERT)
974 {
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;
980 }
981 else if (where & SSL_CB_LOOP)
982 {
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;
989 }
990 else if (where & SSL_CB_HANDSHAKE_START)
991 {
992 std::cout << "SSL/TLS Handshake [Start] " << SSL_state_string_long (_ssl.get ()) << std::endl;
993 }
994 else if (where & SSL_CB_HANDSHAKE_DONE)
995 {
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"
1000 << std::endl;
1001 std::cout << SSL_CTX_sess_connect_renegotiate (_ctx.handle ()) << " client renegotiations requested"
1002 << std::endl;
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"
1006 << std::endl;
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;
1012 }
1013 }
1014
1021 static int verifyWrapper (int preverified, X509_STORE_CTX* x509Ctx) noexcept
1022 {
1023 SSL* ssl = static_cast<SSL*> (X509_STORE_CTX_get_ex_data (x509Ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()));
1024 assert (ssl);
1025 return static_cast<BasicTls<Protocol>*> (SSL_get_app_data (ssl))->verifyCallback (preverified, x509Ctx);
1026 }
1027
1034 int verifyCallback (int preverified, X509_STORE_CTX* context) noexcept
1035 {
1036 int maxDepth = SSL_get_verify_depth (_ssl.get ());
1037 int dpth = X509_STORE_CTX_get_error_depth (context);
1038
1039#ifdef DEBUG
1040 std::cout << "verification started at depth=" << dpth << std::endl;
1041#endif
1042
1043 // catch a too long certificate chain.
1044 if ((maxDepth >= 0) && (dpth > maxDepth))
1045 {
1046 preverified = 0;
1047 X509_STORE_CTX_set_error (context, X509_V_ERR_CERT_CHAIN_TOO_LONG);
1048 }
1049
1050 if (!preverified)
1051 {
1052#ifdef DEBUG
1053 std::cout << "verification failed at depth=" << dpth << " - "
1054 << X509_verify_cert_error_string (X509_STORE_CTX_get_error (context)) << std::endl;
1055#endif
1056 return 0;
1057 }
1058
1059 // check the certificate host name.
1060 if (!verifyCert (context))
1061 {
1062#ifdef DEBUG
1063 std::cout << "rejected by CERT at depth=" << dpth << std::endl;
1064#endif
1065 return 0;
1066 }
1067
1068 // check the revocation list.
1069 /*if (!verifyCrl (context))
1070 {
1071 #ifdef DEBUG
1072 std::cout << "rejected by CRL at depth=" << dpth << std::endl;
1073 #endif
1074 return 0;
1075 }*/
1076
1077 // check ocsp.
1078 /*if (!verifyOcsp (context))
1079 {
1080 #ifdef DEBUG
1081 std::cout << "rejected by OCSP at depth=" << dpth << std::endl;
1082 #endif
1083 return 0;
1084 }*/
1085
1086#ifdef DEBUG
1087 std::cout << "certificate accepted at depth=" << dpth << std::endl;
1088#endif
1089
1090 return 1;
1091 }
1092
1098 int verifyCert (X509_STORE_CTX* context) const
1099 {
1100 int depth = X509_STORE_CTX_get_error_depth (context);
1101 X509* cert = X509_STORE_CTX_get_current_cert (context);
1102
1103 char buf[256];
1104 X509_NAME_oneline (X509_get_subject_name (cert), buf, sizeof (buf));
1105#ifdef DEBUG
1106 std::cout << "subject=" << buf << std::endl;
1107#endif
1108
1109 // check the certificate host name
1110 if (depth == 0)
1111 {
1112 // confirm a match between the hostname and the hostnames listed in the certificate.
1113 if (!checkHostname (cert))
1114 {
1115#ifdef DEBUG
1116 std::cout << "no match for hostname in the certificate" << std::endl;
1117#endif
1118 return 0;
1119 }
1120 }
1121
1122 return 1;
1123 }
1124
1130 bool checkHostname (X509* certificate) const noexcept
1131 {
1132 bool match = false;
1133
1134 // get remote hostname name.
1135 std::string serverName (_socket.remoteEndpoint ().hostname ());
1136
1137 // strip off trailing dots.
1138 if (!serverName.empty () && serverName.back () == '.')
1139 {
1140 serverName.pop_back ();
1141 }
1142
1143 // get alternative names.
1144 join::StackOfGeneralNamePtr altnames (reinterpret_cast<STACK_OF (GENERAL_NAME)*> (
1145 X509_get_ext_d2i (certificate, NID_subject_alt_name, 0, 0)));
1146 if (altnames)
1147 {
1148 for (int i = 0; (i < sk_GENERAL_NAME_num (altnames.get ())) && !match; ++i)
1149 {
1150 // get a handle to alternative name.
1151 GENERAL_NAME* current_name = sk_GENERAL_NAME_value (altnames.get (), i);
1152
1153 if (current_name->type == GEN_DNS)
1154 {
1155 // get data and length.
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);
1159
1160 // strip off trailing dots.
1161 if (!pattern.empty () && pattern.back () == '.')
1162 {
1163 pattern.pop_back ();
1164 }
1165
1166 // compare to pattern.
1167 if (fnmatch (pattern.c_str (), serverName.c_str (), 0) == 0)
1168 {
1169 // an alternative name matched the server hostname.
1170 match = true;
1171 }
1172 }
1173 }
1174 }
1175
1176 return match;
1177 }
1178
1184 /*int verifyCrl ([[maybe_unused]]X509_STORE_CTX *context) const
1185 {
1186 return 1;
1187 }*/
1188
1194 /*int verifyOcsp ([[maybe_unused]]X509_STORE_CTX *context) const
1195 {
1196 return 1;
1197 }*/
1198
1201
1204
1207 };
1208
1215 template <class Protocol>
1216 inline bool operator== (const BasicTls<Protocol>& a, const BasicTls<Protocol>& b) noexcept
1217 {
1218 return a.handle () == b.handle ();
1219 }
1220
1227 template <class Protocol>
1228 inline std::strong_ordering operator<=> (const BasicTls<Protocol>& a, const BasicTls<Protocol>& b) noexcept
1229 {
1230 return a.handle () <=> b.handle ();
1231 }
1232}
1233
1234#endif
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