OpenSDN source code
ssl_server.cc
Go to the documentation of this file.
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 SslServer::SslServer(EventManager *evm, boost::asio::ssl::context::method m,
18  bool ssl_enabled, bool ssl_handshake_delayed)
19  : TcpServer(evm), context_(m),
20  ssl_enabled_(ssl_enabled), ssl_handshake_delayed_(ssl_handshake_delayed) {
21  boost::system::error_code ec;
22  // By default set verify mode to none, to be set by derived class later.
23  context_.set_verify_mode(boost::asio::ssl::context::verify_none, ec);
24  assert(ec.value() == 0);
25  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  assert(ec.value() == 0);
31 
32 #if BOOST_VERSION >= 105400
33  if (getenv("CONTRAIL_SSL_SOCKET_COMPRESSION_ENABLE")) {
34  context_.clear_options(boost::asio::ssl::context::no_compression, ec);
35  assert(ec.value() == 0);
36  }
37 #endif
38 }
39 
41 }
42 
43 boost::asio::ssl::context *SslServer::context() {
44  return &context_;
45 }
46 
47 TcpSession *SslServer::AllocSession(bool server_session) {
48  SslSession *session;
49  if (server_session) {
50  session = AllocSession(so_ssl_accept_.get());
51 
52  // if session allocate succeeds release ownership to so_accept.
53  if (session != NULL) {
54  so_ssl_accept_.release();
55  }
56  } else {
57  SslSocket *socket = new SslSocket(*event_manager()->io_service(),
58  context_);
59  session = AllocSession(socket);
60  }
61 
62  return session;
63 }
64 
66  SslSession *ssl = static_cast<SslSession*>(session.get());
67  if (ssl->IsSslDisabled() || ssl->IsSslHandShakeDelayed()) {
69  } else {
70  // trigger ssl server handshake
71  std::srand(static_cast<unsigned>(std::time(0)));
72  ssl->ssl_handshake_in_progress_ = true;
73  ssl->ssl_socket_->async_handshake
74  (boost::asio::ssl::stream_base::server,
76  TcpServerPtr(this), TcpSessionPtr(ssl),
77  boost::asio::placeholders::error));
78  }
79 }
80 
82  TcpSessionPtr session,
83  const boost::system::error_code& error) {
84  SslServer *ssl_server = static_cast<SslServer *>(server.get());
85  SslSession *ssl_session = static_cast<SslSession *>(session.get());
86  ssl_session->ssl_handshake_in_progress_ = false;
87  if (!error) {
88  // on successful handshake continue with tcp server state machine.
89  ssl_session->SetSslHandShakeSuccess();
90  ssl_server->TcpServer::AcceptHandlerComplete(session);
91  } else {
92  // close session on failure
93  ssl_session->SetSslHandShakeFailure();
95  "SSL Handshake failed due to error: "
96  << error.value() << " category: "
97  << error.category().name()
98  << " message: " << error.message());
99  ssl_session->CloseInternal(error, false, false);
100  }
101 }
102 
104  SslSession *ssl = static_cast<SslSession*>(session.get());
105  if (ssl->IsSslDisabled() || ssl->IsSslHandShakeDelayed()) {
107  } else {
108  // trigger ssl client handshake
109  std::srand(static_cast<unsigned>(std::time(0)));
110  ssl->ssl_handshake_in_progress_ = true;
111  ssl->ssl_socket_->async_handshake
112  (boost::asio::ssl::stream_base::client,
114  TcpServerPtr(this), TcpSessionPtr(ssl),
115  boost::asio::placeholders::error));
116  }
117 }
118 
120  TcpSessionPtr session, const boost::system::error_code& error) {
121  SslServer *ssl_server = static_cast<SslServer *>(server.get());
122  SslSession *ssl_session = static_cast<SslSession *>(session.get());
123  ssl_session->ssl_handshake_in_progress_ = false;
124  if (!error) {
125  // on successful handshake continue with tcp server state machine.
126  ssl_session->SetSslHandShakeSuccess();
127  ssl_server->TcpServer::ConnectHandlerComplete(session);
128  } else {
129  // report connect failure and close the session
130  ssl_session->SetSslHandShakeFailure();
131  ssl_session->CloseInternal(error, false, false);
132  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  ssl_session->ConnectFailed();
138  }
139 }
140 
142  // return tcp socket
143  return &(so_ssl_accept_->next_layer());
144 }
145 
147  so_ssl_accept_.reset(new SslSocket(*event_manager()->io_service(),
148  context_));
149 }
Socket * accept_socket() const
Definition: ssl_server.cc:141
virtual void AcceptHandlerComplete(TcpSessionPtr session)
Definition: ssl_server.cc:65
void set_accept_socket()
Definition: ssl_server.cc:146
virtual ~SslServer()
Definition: ssl_server.cc:40
SslServer(EventManager *evm, boost::asio::ssl::context::method m, bool ssl_enabled=true, bool ssl_handshake_delayed=false)
Definition: ssl_server.cc:17
boost::asio::ssl::stream< boost::asio::ip::tcp::socket > SslSocket
Definition: ssl_server.h:16
void ConnectHandlerComplete(TcpSessionPtr session)
Definition: ssl_server.cc:103
static void ConnectHandShakeHandler(TcpServerPtr server, TcpSessionPtr session, const boost::system::error_code &error)
Definition: ssl_server.cc:119
boost::asio::ssl::context * context()
Definition: ssl_server.cc:43
static void AcceptHandShakeHandler(TcpServerPtr server, TcpSessionPtr session, const boost::system::error_code &error)
Definition: ssl_server.cc:81
virtual SslSession * AllocSession(SslSocket *socket)=0
boost::asio::ssl::context context_
Definition: ssl_server.h:55
std::unique_ptr< SslSocket > so_ssl_accept_
Definition: ssl_server.h:56
void SetSslHandShakeSuccess()
Definition: ssl_session.h:82
bool IsSslHandShakeDelayed()
Definition: ssl_session.h:36
bool IsSslDisabled()
Definition: ssl_session.h:32
void SetSslHandShakeFailure()
Definition: ssl_session.h:87
boost::scoped_ptr< SslSocket > ssl_socket_
Definition: ssl_session.h:94
bool ssl_handshake_in_progress_
Definition: ssl_session.h:97
boost::intrusive_ptr< TcpServer > TcpServerPtr
Definition: tcp_server.h:110
EventManager * event_manager()
Definition: tcp_server.h:76
boost::intrusive_ptr< TcpSession > TcpSessionPtr
Definition: tcp_server.h:111
boost::asio::ip::tcp::socket Socket
Definition: tcp_server.h:31
virtual void ConnectHandlerComplete(TcpSessionPtr session)
Definition: tcp_server.cc:453
virtual void AcceptHandlerComplete(TcpSessionPtr session)
Definition: tcp_server.cc:407
void ConnectFailed()
Definition: tcp_session.cc:298
void CloseInternal(const boost::system::error_code &ec, bool call_observer, bool notify_server=true)
Definition: tcp_session.cc:306
static EventManager evm
#define TCP_DIR_OUT
Definition: io_log.h:46
#define TCP_SESSION_LOG_ERROR(session, dir, arg)
Definition: io_log.h:117