Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge "Support for SSL server/session infrastructure"
- Loading branch information
Showing
13 changed files
with
727 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. | ||
*/ | ||
|
||
#include "ssl_server.h" | ||
#include "ssl_session.h" | ||
|
||
#include "io/event_manager.h" | ||
|
||
SslServer::SslServer(EventManager *evm, boost::asio::ssl::context::method m) | ||
: TcpServer(evm), context_(*evm->io_service(), m) { | ||
boost::system::error_code ec; | ||
// By default set verify mode to none, to be set by derived class later. | ||
context_.set_verify_mode(boost::asio::ssl::context::verify_none, ec); | ||
assert(ec.value() == 0); | ||
context_.set_options(boost::asio::ssl::context::default_workarounds, ec); | ||
assert(ec.value() == 0); | ||
} | ||
|
||
SslServer::~SslServer() { | ||
} | ||
|
||
boost::asio::ssl::context *SslServer::context() { | ||
return &context_; | ||
} | ||
|
||
TcpSession *SslServer::AllocSession(bool server_session) { | ||
SslSession *session; | ||
if (server_session) { | ||
session = AllocSession(so_ssl_accept_.get()); | ||
|
||
// if session allocate succeeds release ownership to so_accept. | ||
if (session != NULL) { | ||
so_ssl_accept_.release(); | ||
} | ||
} else { | ||
SslSocket *socket = new SslSocket(*event_manager()->io_service(), | ||
context_); | ||
session = AllocSession(socket); | ||
} | ||
|
||
return session; | ||
} | ||
|
||
TcpServer::Socket *SslServer::accept_socket() const { | ||
// return tcp socket | ||
return &(so_ssl_accept_->next_layer()); | ||
} | ||
|
||
void SslServer::set_accept_socket() { | ||
so_ssl_accept_.reset(new SslSocket(*event_manager()->io_service(), | ||
context_)); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. | ||
*/ | ||
|
||
#ifndef __src_io_ssl_server_h__ | ||
#define __src_io_ssl_server_h__ | ||
|
||
#include <boost/asio/ssl.hpp> | ||
|
||
#include "io/tcp_server.h" | ||
|
||
class SslSession; | ||
|
||
class SslServer : public TcpServer { | ||
public: | ||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SslSocket; | ||
|
||
explicit SslServer(EventManager *evm, boost::asio::ssl::context::method m); | ||
virtual ~SslServer(); | ||
|
||
protected: | ||
// given SSL socket, Create a session object. | ||
virtual SslSession *AllocSession(SslSocket *socket) = 0; | ||
|
||
// boost ssl context accessor to setup ssl context variables. | ||
boost::asio::ssl::context *context(); | ||
|
||
private: | ||
// suppress AllocSession method using tcp socket, not valid for | ||
// ssl server. | ||
TcpSession *AllocSession(Socket *socket) { return NULL; } | ||
|
||
TcpSession *AllocSession(bool server_session); | ||
|
||
Socket *accept_socket() const; | ||
void set_accept_socket(); | ||
|
||
boost::asio::ssl::context context_; | ||
std::auto_ptr<SslSocket> so_ssl_accept_; // SSL socket used in async_accept | ||
DISALLOW_COPY_AND_ASSIGN(SslServer); | ||
}; | ||
|
||
#endif //__src_io_ssl_server_h__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. | ||
*/ | ||
|
||
#include <boost/asio.hpp> | ||
#include <boost/bind.hpp> | ||
|
||
#include "ssl_session.h" | ||
|
||
using namespace boost::asio; | ||
|
||
SslSession::SslSession(SslServer *server, SslSocket *socket, | ||
bool async_read_ready) : | ||
TcpSession(server, NULL, async_read_ready), | ||
ssl_socket_(socket) { | ||
} | ||
|
||
SslSession::~SslSession() { | ||
} | ||
|
||
TcpSession::Socket *SslSession::socket() const { | ||
// return tcp socket | ||
return &ssl_socket_->next_layer(); | ||
} | ||
|
||
bool SslSession::Connected(Endpoint remote) { | ||
if (IsClosed()) { | ||
return false; | ||
} | ||
|
||
// trigger ssl client handshake | ||
std::srand(std::time(0)); | ||
ssl_socket_->async_handshake | ||
(boost::asio::ssl::stream_base::client, | ||
boost::bind(&SslSession::ConnectHandShakeHandler, TcpSessionPtr(this), | ||
remote, boost::asio::placeholders::error)); | ||
return true; | ||
} | ||
|
||
void SslSession::Accepted() { | ||
// trigger ssl server handshake | ||
std::srand(std::time(0)); | ||
ssl_socket_->async_handshake | ||
(boost::asio::ssl::stream_base::server, | ||
boost::bind(&SslSession::AcceptHandShakeHandler, TcpSessionPtr(this), | ||
boost::asio::placeholders::error)); | ||
} | ||
|
||
void SslSession::AcceptHandShakeHandler(TcpSessionPtr session, | ||
const boost::system::error_code& error) { | ||
SslSession *ssl_session = static_cast<SslSession *>(session.get()); | ||
if (!error) { | ||
// on successful handshake continue with tcp session state machine. | ||
ssl_session->TcpSession::Accepted(); | ||
} else { | ||
// close session on failure | ||
ssl_session->CloseInternal(false); | ||
} | ||
} | ||
|
||
void SslSession::ConnectHandShakeHandler(TcpSessionPtr session, Endpoint remote, | ||
const boost::system::error_code& error) { | ||
SslSession *ssl_session = static_cast<SslSession *>(session.get()); | ||
bool ret = false; | ||
if (!error) { | ||
// on successful handshake continue with tcp session state machine. | ||
ret = ssl_session->TcpSession::Connected(remote); | ||
} | ||
if (ret == false) { | ||
// report connect failure and close the session | ||
ssl_session->ConnectFailed(); | ||
ssl_session->CloseInternal(false); | ||
} | ||
} | ||
|
||
|
||
void SslSession::AsyncReadSome(boost::asio::mutable_buffer buffer) { | ||
ssl_socket_->async_read_some(mutable_buffers_1(buffer), | ||
boost::bind(&TcpSession::AsyncReadHandler, TcpSessionPtr(this), buffer, | ||
boost::asio::placeholders::error, | ||
boost::asio::placeholders::bytes_transferred)); | ||
} | ||
|
||
std::size_t SslSession::WriteSome(const uint8_t *data, std::size_t len, | ||
boost::system::error_code &error) { | ||
return ssl_socket_->write_some(boost::asio::buffer(data, len), error); | ||
} | ||
|
||
void SslSession::AsyncWrite(const u_int8_t *data, std::size_t size) { | ||
boost::asio::async_write( | ||
*ssl_socket_.get(), buffer(data, size), | ||
boost::bind(&TcpSession::AsyncWriteHandler, TcpSessionPtr(this), | ||
boost::asio::placeholders::error)); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. | ||
*/ | ||
|
||
#ifndef __src_io_ssl_session_h__ | ||
#define __src_io_ssl_session_h__ | ||
|
||
#include "io/tcp_session.h" | ||
#include "io/ssl_server.h" | ||
|
||
class SslSession : public TcpSession { | ||
public: | ||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SslSocket; | ||
|
||
// SslSession constructor takes ownership of socket. | ||
SslSession(SslServer *server, SslSocket *socket, | ||
bool async_read_ready = true); | ||
|
||
virtual Socket *socket() const; | ||
|
||
// Override to trigger handshake | ||
virtual bool Connected(Endpoint remote); | ||
|
||
// Override to trigger handshake | ||
virtual void Accepted(); | ||
|
||
|
||
protected: | ||
virtual ~SslSession(); | ||
|
||
private: | ||
static void AcceptHandShakeHandler(TcpSessionPtr session, | ||
const boost::system::error_code& error); | ||
static void ConnectHandShakeHandler(TcpSessionPtr session, Endpoint remote, | ||
const boost::system::error_code& error); | ||
|
||
void AsyncReadSome(boost::asio::mutable_buffer buffer); | ||
std::size_t WriteSome(const uint8_t *data, std::size_t len, | ||
boost::system::error_code &error); | ||
void AsyncWrite(const u_int8_t *data, std::size_t size); | ||
|
||
boost::scoped_ptr<SslSocket> ssl_socket_; | ||
DISALLOW_COPY_AND_ASSIGN(SslSession); | ||
}; | ||
|
||
#endif // __src_io_ssl_session_h__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.