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

Generated by: LCOV version 1.14