@@ -691,6 +691,330 @@ void linux_tcp_conn_t::on_event(int /* events */) {
691691 event_watcher->stop_watching_for_errors ();
692692}
693693
694+ tls_conn_wrapper_t ::tls_conn_wrapper_t (SSL_CTX *tls_ctx)
695+ THROWS_ONLY (linux_tcp_conn_t ::connect_failed_exc_t ) {
696+ ERR_clear_error ();
697+
698+ conn = SSL_new (tls_ctx);
699+ if (nullptr == conn) {
700+ unsigned long err_code = ERR_get_error ();
701+
702+ throw linux_tcp_conn_t::connect_failed_exc_t (
703+ err_code, ERR_error_string (err_code, nullptr ));
704+ }
705+
706+ // Add support for partial writes.
707+ SSL_set_mode (conn, SSL_MODE_ENABLE_PARTIAL_WRITE);
708+ }
709+
710+ tls_conn_wrapper_t ::~tls_conn_wrapper_t () {
711+ SSL_free (conn);
712+ }
713+
714+ // Set the underlying IO.
715+ void tls_conn_wrapper_t::set_fd (fd_t sock)
716+ THROWS_ONLY(linux_tcp_conn_t ::connect_failed_exc_t ) {
717+ if (0 == SSL_set_fd (conn, sock)) {
718+ unsigned long err_code = ERR_get_error ();
719+ throw linux_tcp_conn_t::connect_failed_exc_t (
720+ err_code, ERR_error_string (err_code, nullptr ));
721+ }
722+ }
723+
724+ /* This is the client version of the constructor. The base class constructor
725+ will establish a TCP connection to the peer at the given host:port and then we
726+ wrap the tcp connection in TLS using the configuration in the given tls_ctx. */
727+ linux_secure_tcp_conn_t ::linux_secure_tcp_conn_t (
728+ SSL_CTX *tls_ctx, const ip_address_t &host, int port,
729+ signal_t *interruptor, int local_port) THROWS_ONLY(connect_failed_exc_t , interrupted_exc_t ) :
730+ linux_tcp_conn_t (host, port, interruptor, local_port),
731+ conn(tls_ctx) {
732+
733+ conn.set_fd (sock.get ());
734+ SSL_set_connect_state (conn.get ());
735+ perform_handshake (interruptor);
736+ }
737+
738+ /* This is the server version of the constructor */
739+ linux_secure_tcp_conn_t ::linux_secure_tcp_conn_t (
740+ SSL_CTX *tls_ctx, fd_t _sock, signal_t *interruptor)
741+ THROWS_ONLY (connect_failed_exc_t , interrupted_exc_t ) :
742+ linux_tcp_conn_t(_sock),
743+ conn(tls_ctx) {
744+
745+ conn.set_fd (sock.get ());
746+ SSL_set_accept_state (conn.get ());
747+ perform_handshake (interruptor);
748+ }
749+
750+ linux_secure_tcp_conn_t ::~linux_secure_tcp_conn_t () THROWS_NOTHING {
751+ assert_thread ();
752+
753+ if (is_open ()) shutdown ();
754+ }
755+
756+ void linux_secure_tcp_conn_t::perform_handshake (signal_t *interruptor)
757+ THROWS_ONLY(linux_tcp_conn_t ::connect_failed_exc_t , interrupted_exc_t ) {
758+ // Perform TLS handshake.
759+ while (true ) {
760+ ERR_clear_error ();
761+ int ret = SSL_do_handshake (conn.get ());
762+
763+ if (ret > 0 ) {
764+ return ; // Successful TLS handshake.
765+ }
766+
767+ if (ret == 0 ) {
768+ // The handshake failed but the connection shut down cleanly.
769+ throw linux_tcp_conn_t::connect_failed_exc_t (
770+ 0 , " TLS handshake failed, shutdown cleanly" );
771+ }
772+
773+ switch (SSL_get_error (conn.get (), ret)) {
774+ case SSL_ERROR_WANT_READ:
775+ /* The handshake needs to read data, but the underlying I/O has no data
776+ ready to read. Wait for it to be ready or for an interrupt signal. */
777+ {
778+ linux_event_watcher_t ::watch_t watch (get_event_watcher (), poll_event_in);
779+ wait_interruptible (&watch, interruptor);
780+ }
781+ break ;
782+ case SSL_ERROR_WANT_WRITE:
783+ /* The handshake needs to write data, but the underlying I/O is not ready
784+ to write. Wait for it to be ready or for an interrupt signal. */
785+ {
786+ linux_event_watcher_t ::watch_t watch (get_event_watcher (), poll_event_out);
787+ wait_interruptible (&watch, interruptor);
788+ }
789+ break ;
790+ default :
791+ // Some other error with the underlying I/O.
792+ unsigned long err_code = ERR_get_error ();
793+ throw linux_tcp_conn_t::connect_failed_exc_t (
794+ err_code, ERR_error_string (err_code, nullptr ));
795+ }
796+
797+ if (interruptor->is_pulsed ()) {
798+ // The handshake cannot continue because we need to shutdown now.
799+ throw interrupted_exc_t ();
800+ }
801+
802+ /* Go around the loop and try to complete the handshake. */
803+ }
804+ }
805+
806+ size_t linux_secure_tcp_conn_t::read_internal (void *buffer, size_t size)
807+ THROWS_ONLY(tcp_conn_read_closed_exc_t ) {
808+ assert_thread ();
809+ rassert (!closed.is_pulsed ());
810+
811+ while (true ) {
812+ ERR_clear_error ();
813+
814+ int ret = SSL_read (conn.get (), buffer, size);
815+
816+ if (ret > 0 ) {
817+ return ret; // Operation successful, returns number of bytes read.
818+ }
819+
820+ switch (SSL_get_error (conn.get (), ret)) {
821+ case SSL_ERROR_ZERO_RETURN:
822+ // Indicates that the peer has sent the "close notify" alert. The
823+ // shutdown state is currently SSL_RECEIVED_SHUTDOWN. We must now
824+ // send our "close notify" alert.
825+ shutdown ();
826+ throw tcp_conn_read_closed_exc_t ();
827+ case SSL_ERROR_WANT_READ:
828+ /* The underlying I/O has no data ready to read. Wait for it to be
829+ ready or for someone to send a close signal. */
830+ {
831+ linux_event_watcher_t ::watch_t watch (
832+ get_event_watcher (), poll_event_in);
833+ wait_any_t waiter (&watch, &closed);
834+ waiter.wait_lazily_unordered ();
835+ }
836+ break ;
837+ case SSL_ERROR_WANT_WRITE:
838+ /* Though we are reading, a TLS renegotiation may occur at any time
839+ requiring a write. Wait for the underyling I/O to be ready for a
840+ write, or for someone to send a close signal. */
841+ {
842+ linux_event_watcher_t ::watch_t watch (
843+ get_event_watcher (), poll_event_out);
844+ wait_any_t waiter (&watch, &closed);
845+ waiter.wait_lazily_unordered ();
846+ }
847+ break ;
848+ default :
849+ // Some other error. Assume that the connection is unusable.
850+ on_shutdown ();
851+ throw tcp_conn_read_closed_exc_t ();
852+ }
853+
854+ if (closed.is_pulsed ()) {
855+ /* We were closed for whatever reason. Whatever signalled us has
856+ already called on_shutdown(). */
857+ throw tcp_conn_read_closed_exc_t ();
858+ }
859+
860+ /* Go around the loop and try to read again */
861+ }
862+ }
863+
864+ void linux_secure_tcp_conn_t::perform_write (const void *buffer, size_t size) {
865+ assert_thread ();
866+
867+ if (closed.is_pulsed ()) {
868+ /* The connection was closed, but there are still operations in the
869+ write queue; we are one of those operations. Just don't do anything. */
870+ return ;
871+ }
872+
873+ // Loop for retrying if the underlying socket would block and to retry on
874+ // partial writes.
875+ while (size > 0 ) {
876+ ERR_clear_error ();
877+
878+ int ret = SSL_write (conn.get (), buffer, size);
879+
880+ if (ret > 0 ) {
881+ // Operation successful, returns number of bytes written.
882+ rassert (static_cast <size_t >(ret) <= size);
883+ size -= ret;
884+
885+ // Slide down the buffer.
886+ buffer = reinterpret_cast <const void *>(
887+ reinterpret_cast <const char *>(buffer) + ret);
888+
889+ if (write_perfmon) write_perfmon->record (ret);
890+
891+ // Go around the loop again if there is more data to write.
892+ continue ;
893+ }
894+
895+ switch (SSL_get_error (conn.get (), ret)) {
896+ case SSL_ERROR_ZERO_RETURN:
897+ // Indicates that the peer has sent the "close notify" alert. The
898+ // shutdown state is currently SSL_RECEIVED_SHUTDOWN. We must now
899+ // send our "close notify" alert.
900+ shutdown ();
901+ return ;
902+ case SSL_ERROR_WANT_READ:
903+ /* Though we are writing, a TLS renegotiation may occur at any time
904+ requiring a read. Wait for the underyling I/O to be ready for a
905+ read, or for someone to send a close signal. */
906+ {
907+ linux_event_watcher_t ::watch_t watch (get_event_watcher (), poll_event_in);
908+ wait_any_t waiter (&watch, &closed);
909+ waiter.wait_lazily_unordered ();
910+ }
911+ break ;
912+ case SSL_ERROR_WANT_WRITE:
913+ /* The underlying I/O is not ready to accept a write. Wait for it
914+ to be ready or for someone to send a close signal. */
915+ {
916+ linux_event_watcher_t ::watch_t watch (
917+ get_event_watcher (), poll_event_out);
918+ wait_any_t waiter (&watch, &closed);
919+ waiter.wait_lazily_unordered ();
920+ }
921+ break ;
922+ default :
923+ // Some other error. Assume that the connection is unusable.
924+ on_shutdown ();
925+ return ;
926+ }
927+
928+ if (closed.is_pulsed ()) {
929+ /* We were closed for whatever reason. Whatever signalled
930+ us has already called on_shutdown(). */
931+ throw tcp_conn_read_closed_exc_t ();
932+ }
933+
934+ /* Go around the loop and try to read again */
935+ }
936+ }
937+
938+ void linux_secure_tcp_conn_t::shutdown () {
939+ assert_thread ();
940+
941+ // Wait at most 5 seconds for the orderly shutdown. If it doesn't complete by then,
942+ // we simply shutdown the socket.
943+ signal_timer_t shutdown_timeout (5000 );
944+
945+ bool skip_shutdown = false ; // Set to true if TLS shutdown encounters an error.
946+
947+ // If we have not already received a "close notify" alert from the peer,
948+ // then we should send one. If we have received one, this loop will respond
949+ // with our own "close notify" alert.
950+ while (!(skip_shutdown || shutdown_timeout.is_pulsed ())) {
951+ ERR_clear_error ();
952+
953+ int ret = SSL_shutdown (conn.get ());
954+
955+ if (ret > 0 ) {
956+ // "close notify" has been sent and received.
957+ break ;
958+ }
959+
960+ if (ret == 0 ) {
961+ // "close notify" has been sent but not yet received from peer.
962+ continue ;
963+ }
964+
965+ switch (SSL_get_error (conn.get (), ret)) {
966+ case SSL_ERROR_WANT_READ:
967+ {
968+ /* The shutdown needs to read data, but the underlying I/O has no data
969+ ready to read. Wait for it to be ready or for a timeout. */
970+ linux_event_watcher_t ::watch_t watch (get_event_watcher (), poll_event_in);
971+ wait_any_t waiter (&watch, &shutdown_timeout);
972+ waiter.wait_lazily_unordered ();
973+ }
974+ continue ;
975+ case SSL_ERROR_WANT_WRITE:
976+ {
977+ /* The handshake needs to write data, but the underlying I/O is not ready
978+ to write. Wait for it to be ready or for a timeout. */
979+ linux_event_watcher_t ::watch_t watch (
980+ get_event_watcher (), poll_event_out);
981+ wait_any_t waiter (&watch, &shutdown_timeout);
982+ waiter.wait_lazily_unordered ();
983+ }
984+ continue ;
985+ default :
986+ // Unable to perform clean shutdown. Just skip it.
987+ skip_shutdown = true ;
988+ }
989+ }
990+
991+ // Shutdown the underlying TCP connection.
992+ int res = ::shutdown (sock.get (), SHUT_RDWR);
993+ if (res != 0 && get_errno () != ENOTCONN) {
994+ logERR (
995+ " Could not shutdown socket for reading and writing: %s" ,
996+ errno_string (get_errno ()).c_str ());
997+ }
998+
999+ on_shutdown ();
1000+ }
1001+
1002+ /* It is not possible to close only the read or write side of a TLS connection
1003+ so we use only a single shutdown method which attempts to shutdown the TLS
1004+ before shutting down the underlying tcp connection */
1005+ void linux_secure_tcp_conn_t::on_shutdown () {
1006+ assert_thread ();
1007+
1008+ rassert (!closed.is_pulsed ());
1009+ rassert (!read_closed.is_pulsed ());
1010+ rassert (!write_closed.is_pulsed ());
1011+
1012+ closed.pulse ();
1013+ read_closed.pulse ();
1014+ write_closed.pulse ();
1015+ }
1016+
1017+
6941018linux_tcp_conn_descriptor_t ::linux_tcp_conn_descriptor_t (fd_t fd) : fd_(fd) {
6951019 rassert (fd != -1 );
6961020}
@@ -699,13 +1023,27 @@ linux_tcp_conn_descriptor_t::~linux_tcp_conn_descriptor_t() {
6991023 rassert (fd_ == -1 );
7001024}
7011025
702- void linux_tcp_conn_descriptor_t::make_overcomplicated (scoped_ptr_t <linux_tcp_conn_t > *tcp_conn) {
703- tcp_conn->init (new linux_tcp_conn_t (fd_));
1026+ void linux_tcp_conn_descriptor_t::make_server_connection (
1027+ SSL_CTX *tls_ctx, scoped_ptr_t <linux_tcp_conn_t > *tcp_conn, signal_t *closer
1028+ ) THROWS_ONLY(linux_tcp_conn_t ::connect_failed_exc_t , interrupted_exc_t ) {
1029+ fd_t sock = fd_;
7041030 fd_ = -1 ;
1031+
1032+ if (tls_ctx == nullptr ) {
1033+ tcp_conn->init (new linux_tcp_conn_t (sock));
1034+ } else {
1035+ tcp_conn->init (new linux_secure_tcp_conn_t (tls_ctx, sock, closer));
1036+ }
7051037}
7061038
707- void linux_tcp_conn_descriptor_t::make_overcomplicated (linux_tcp_conn_t **tcp_conn_out) {
708- *tcp_conn_out = new linux_tcp_conn_t (fd_);
1039+ void linux_tcp_conn_descriptor_t::make_server_connection (
1040+ SSL_CTX *tls_ctx, linux_tcp_conn_t **tcp_conn_out, signal_t *closer
1041+ ) THROWS_ONLY(linux_tcp_conn_t ::connect_failed_exc_t , interrupted_exc_t ) {
1042+ if (tls_ctx == nullptr ) {
1043+ *tcp_conn_out = new linux_tcp_conn_t (fd_);
1044+ } else {
1045+ *tcp_conn_out = new linux_secure_tcp_conn_t (tls_ctx, fd_, closer);
1046+ }
7091047 fd_ = -1 ;
7101048}
7111049
0 commit comments