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