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