LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-common/io - ssl_server.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 73 75 97.3 %
Date: 2026-08-03 02:19:58 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <boost/asio.hpp>
       6             : #include <boost/bind/bind.hpp>
       7             : 
       8             : #include "io/ssl_server.h"
       9             : #include "io/ssl_session.h"
      10             : 
      11             : #include "io/event_manager.h"
      12             : #include "io/io_utils.h"
      13             : #include "io/io_log.h"
      14             : 
      15             : using namespace boost::placeholders;
      16             : 
      17        7415 : SslServer::SslServer(EventManager *evm, boost::asio::ssl::context::method m,
      18        7415 :                      bool ssl_enabled, bool ssl_handshake_delayed)
      19        7415 :     : TcpServer(evm), context_(m),
      20        7415 :       ssl_enabled_(ssl_enabled), ssl_handshake_delayed_(ssl_handshake_delayed) {
      21        7415 :     boost::system::error_code ec;
      22             :     // By default set verify mode to none, to be set by derived class later.
      23        7415 :     context_.set_verify_mode(boost::asio::ssl::context::verify_none, ec);
      24        7415 :     assert(ec.value() == 0);
      25        7415 :     context_.set_options(boost::asio::ssl::context::default_workarounds |
      26             :             boost::asio::ssl::context::no_sslv3 |
      27             :             boost::asio::ssl::context::no_sslv2 |
      28             :             boost::asio::ssl::context::no_tlsv1 |
      29             :             boost::asio::ssl::context::no_tlsv1_1, ec);
      30        7415 :     assert(ec.value() == 0);
      31             : 
      32             : #if BOOST_VERSION >= 105400
      33        7415 :     if (getenv("CONTRAIL_SSL_SOCKET_COMPRESSION_ENABLE")) {
      34           0 :         context_.clear_options(boost::asio::ssl::context::no_compression, ec);
      35           0 :         assert(ec.value() == 0);
      36             :     }
      37             : #endif
      38        7415 : }
      39             : 
      40        7415 : SslServer::~SslServer() {
      41        7415 : }
      42             : 
      43        1198 : boost::asio::ssl::context *SslServer::context() {
      44        1198 :     return &context_;
      45             : }
      46             : 
      47       14740 : TcpSession *SslServer::AllocSession(bool server_session) {
      48             :     SslSession *session;
      49       14740 :     if (server_session) {
      50        6615 :         session = AllocSession(so_ssl_accept_.get());
      51             : 
      52             :         // if session allocate succeeds release ownership to so_accept.
      53        6615 :         if (session != NULL) {
      54        6615 :             so_ssl_accept_.release();
      55             :         }
      56             :     } else {
      57        8125 :         SslSocket *socket = new SslSocket(*event_manager()->io_service(),
      58        8125 :                                           context_);
      59        8125 :         session = AllocSession(socket);
      60             :     }
      61             : 
      62       14740 :     return session;
      63             : }
      64             : 
      65        6615 : void SslServer::AcceptHandlerComplete(TcpSessionPtr session) {
      66        6615 :     SslSession *ssl = static_cast<SslSession*>(session.get());
      67        6615 :     if (ssl->IsSslDisabled() || ssl->IsSslHandShakeDelayed()) {
      68        6610 :         TcpServer::AcceptHandlerComplete(session);
      69             :     } else {
      70             :         // trigger ssl server handshake
      71           5 :         std::srand(static_cast<unsigned>(std::time(0)));
      72           5 :         ssl->ssl_handshake_in_progress_ = true;
      73             :         ssl->ssl_socket_->async_handshake
      74          10 :             (boost::asio::ssl::stream_base::server,
      75          10 :              boost::bind(&SslServer::AcceptHandShakeHandler,
      76          10 :                          TcpServerPtr(this), TcpSessionPtr(ssl),
      77             :                          boost::asio::placeholders::error));
      78             :     }
      79        6615 : }
      80             : 
      81           5 : void SslServer::AcceptHandShakeHandler(TcpServerPtr server,
      82             :                                        TcpSessionPtr session,
      83             :                                        const boost::system::error_code& error) {
      84           5 :     SslServer *ssl_server = static_cast<SslServer *>(server.get());
      85           5 :     SslSession *ssl_session = static_cast<SslSession *>(session.get());
      86           5 :     ssl_session->ssl_handshake_in_progress_ = false;
      87           5 :     if (!error) {
      88             :         // on successful handshake continue with tcp server state machine.
      89           3 :         ssl_session->SetSslHandShakeSuccess();
      90           3 :         ssl_server->TcpServer::AcceptHandlerComplete(session);
      91             :     } else {
      92             :         // close session on failure
      93           2 :         ssl_session->SetSslHandShakeFailure();
      94           2 :         TCP_SESSION_LOG_ERROR(ssl_session, TCP_DIR_OUT,
      95             :                               "SSL Handshake failed due to error: "
      96             :                               << error.value() << " category: "
      97             :                               << error.category().name()
      98             :                               << " message: " << error.message());
      99           2 :         ssl_session->CloseInternal(error, false, false);
     100             :     }
     101           5 : }
     102             : 
     103        6665 : void SslServer::ConnectHandlerComplete(TcpSessionPtr session) {
     104        6665 :     SslSession *ssl = static_cast<SslSession*>(session.get());
     105        6665 :     if (ssl->IsSslDisabled() || ssl->IsSslHandShakeDelayed()) {
     106        6659 :         TcpServer::ConnectHandlerComplete(session);
     107             :     } else {
     108             :         // trigger ssl client handshake
     109           6 :         std::srand(static_cast<unsigned>(std::time(0)));
     110           6 :         ssl->ssl_handshake_in_progress_ = true;
     111             :         ssl->ssl_socket_->async_handshake
     112          12 :             (boost::asio::ssl::stream_base::client,
     113          12 :              boost::bind(&SslServer::ConnectHandShakeHandler,
     114          12 :                          TcpServerPtr(this), TcpSessionPtr(ssl),
     115             :                          boost::asio::placeholders::error));
     116             :     }
     117        6665 : }
     118             : 
     119           6 : void SslServer::ConnectHandShakeHandler(TcpServerPtr server,
     120             :         TcpSessionPtr session, const boost::system::error_code& error) {
     121           6 :     SslServer *ssl_server = static_cast<SslServer *>(server.get());
     122           6 :     SslSession *ssl_session = static_cast<SslSession *>(session.get());
     123           6 :     ssl_session->ssl_handshake_in_progress_ = false;
     124           6 :     if (!error) {
     125             :         // on successful handshake continue with tcp server state machine.
     126           4 :         ssl_session->SetSslHandShakeSuccess();
     127           4 :         ssl_server->TcpServer::ConnectHandlerComplete(session);
     128             :     } else {
     129             :         // report connect failure and close the session
     130           2 :         ssl_session->SetSslHandShakeFailure();
     131           2 :         ssl_session->CloseInternal(error, false, false);
     132           2 :         TCP_SESSION_LOG_ERROR(ssl_session, TCP_DIR_OUT,
     133             :                               "SSL Handshake failed due to error: "
     134             :                               << error.value() << " category: "
     135             :                               << error.category().name()
     136             :                               << " message: " << error.message());
     137           2 :         ssl_session->ConnectFailed();
     138             :     }
     139           6 : }
     140             : 
     141       15514 : TcpServer::Socket *SslServer::accept_socket() const {
     142             :     // return tcp socket
     143       15514 :     return &(so_ssl_accept_->next_layer());
     144             : }
     145             : 
     146        8899 : void SslServer::set_accept_socket() {
     147       17798 :     so_ssl_accept_.reset(new SslSocket(*event_manager()->io_service(),
     148        8899 :                                        context_));
     149        8899 : }

Generated by: LCOV version 1.14