Skip to content

Commit

Permalink
Merge "Fix session object reference management for SSL"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Sep 1, 2015
2 parents 1723926 + 8e52d70 commit efecd7c
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 114 deletions.
82 changes: 82 additions & 0 deletions src/io/ssl_server.cc
Expand Up @@ -2,10 +2,15 @@
* Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
*/

#include <boost/asio.hpp>
#include <boost/bind.hpp>

#include "ssl_server.h"
#include "ssl_session.h"

#include "io/event_manager.h"
#include "io/io_utils.h"
#include "io/io_log.h"

SslServer::SslServer(EventManager *evm, boost::asio::ssl::context::method m,
bool ssl_enabled, bool ssl_handshake_delayed)
Expand Down Expand Up @@ -44,6 +49,83 @@ TcpSession *SslServer::AllocSession(bool server_session) {
return session;
}

void SslServer::AcceptHandlerComplete(TcpSessionPtr &session) {
SslSession *ssl= static_cast<SslSession*>(session.get());
if (ssl->IsSslDisabled() || ssl->IsSslHandShakeDelayed()) {
TcpServer::AcceptHandlerComplete(session);
} else {
// trigger ssl server handshake
std::srand(std::time(0));
ssl->ssl_handshake_in_progress_ = true;
ssl->ssl_socket_->async_handshake
(boost::asio::ssl::stream_base::server,
boost::bind(&SslServer::AcceptHandShakeHandler,
TcpServerPtr(this), TcpSessionPtr(ssl),
boost::asio::placeholders::error));
}
}

void SslServer::AcceptHandShakeHandler(TcpServerPtr server,
TcpSessionPtr session,
const boost::system::error_code& error) {
SslServer *ssl_server = static_cast<SslServer *>(server.get());
SslSession *ssl_session = static_cast<SslSession *>(session.get());
ssl_session->ssl_handshake_in_progress_ = false;
if (!error) {
// on successful handshake continue with tcp server state machine.
ssl_session->SetSslHandShakeSuccess();
ssl_server->TcpServer::AcceptHandlerComplete(session);
} else {
// close session on failure
ssl_session->SetSslHandShakeFailure();
TCP_SESSION_LOG_ERROR(ssl_session, TCP_DIR_OUT,
"SSL Handshake failed due to error: "
<< error.value() << " category: "
<< error.category().name()
<< " message: " << error.message());
ssl_session->CloseInternal(error, false);
}
}

void SslServer::ConnectHandlerComplete(TcpSessionPtr &session) {
SslSession *ssl= static_cast<SslSession*>(session.get());
if (ssl->IsSslDisabled() || ssl->IsSslHandShakeDelayed()) {
TcpServer::ConnectHandlerComplete(session);
} else {
// trigger ssl client handshake
std::srand(std::time(0));
ssl->ssl_handshake_in_progress_ = true;
ssl->ssl_socket_->async_handshake
(boost::asio::ssl::stream_base::client,
boost::bind(&SslServer::ConnectHandShakeHandler,
TcpServerPtr(this), TcpSessionPtr(ssl),
boost::asio::placeholders::error));
}
}

void SslServer::ConnectHandShakeHandler(TcpServerPtr server,
TcpSessionPtr session,
const boost::system::error_code& error) {
SslServer *ssl_server = static_cast<SslServer *>(server.get());
SslSession *ssl_session = static_cast<SslSession *>(session.get());
ssl_session->ssl_handshake_in_progress_ = false;
if (!error) {
// on successful handshake continue with tcp server state machine.
ssl_session->SetSslHandShakeSuccess();
ssl_server->TcpServer::ConnectHandlerComplete(session);
} else {
// report connect failure and close the session
ssl_session->SetSslHandShakeFailure();
ssl_session->CloseInternal(error, false);
TCP_SESSION_LOG_ERROR(ssl_session, TCP_DIR_OUT,
"SSL Handshake failed due to error: "
<< error.value() << " category: "
<< error.category().name()
<< " message: " << error.message());
ssl_session->ConnectFailed();
}
}

TcpServer::Socket *SslServer::accept_socket() const {
// return tcp socket
return &(so_ssl_accept_->next_layer());
Expand Down
13 changes: 13 additions & 0 deletions src/io/ssl_server.h
Expand Up @@ -30,12 +30,25 @@ class SslServer : public TcpServer {
private:
friend class SslSession;

static void AcceptHandShakeHandler(TcpServerPtr server,
TcpSessionPtr session,
const boost::system::error_code& error);
static void ConnectHandShakeHandler(TcpServerPtr server,
TcpSessionPtr session,
const boost::system::error_code& error);

// suppress AllocSession method using tcp socket, not valid for
// ssl server.
TcpSession *AllocSession(Socket *socket) { return NULL; }

TcpSession *AllocSession(bool server_session);

// override accept complete handler to trigger handshake
virtual void AcceptHandlerComplete(TcpSessionPtr &session);

// override connect complete handler to trigger handshake
void ConnectHandlerComplete(TcpSessionPtr &session);

Socket *accept_socket() const;
void set_accept_socket();

Expand Down
79 changes: 0 additions & 79 deletions src/io/ssl_session.cc
Expand Up @@ -70,85 +70,6 @@ TcpSession::Socket *SslSession::socket() const {
return &ssl_socket_->next_layer();
}

bool SslSession::Connected(Endpoint remote) {
if (IsClosed()) {
return false;
}

if (IsSslDisabled() || IsSslHandShakeDelayed()) {
return (TcpSession::Connected(remote));
} else {
// trigger ssl client handshake
std::srand(std::time(0));
ssl_handshake_in_progress_ = true;
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() {

if (IsSslDisabled() || IsSslHandShakeDelayed()) {
return (TcpSession::Accepted());
} else {
// trigger ssl server handshake
std::srand(std::time(0));
ssl_handshake_in_progress_ = true;
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());
ssl_session->ssl_handshake_in_progress_ = false;
if (!error) {
// on successful handshake continue with tcp session state machine.
ssl_session->SetSslHandShakeSuccess();
ssl_session->TcpSession::Accepted();
} else {
// close session on failure
ssl_session->SetSslHandShakeFailure();
TCP_SESSION_LOG_ERROR(ssl_session, TCP_DIR_OUT,
"SSL Handshake failed due to error: "
<< error.value() << " category: "
<< error.category().name()
<< " message: " << error.message());
ssl_session->CloseInternal(error, false);
}
}

void SslSession::ConnectHandShakeHandler(TcpSessionPtr session, Endpoint remote,
const boost::system::error_code& error) {

SslSession *ssl_session = static_cast<SslSession *>(session.get());
ssl_session->ssl_handshake_in_progress_ = false;
bool ret = false;
if (!error) {
// on successful handshake continue with tcp session state machine.
ssl_session->SetSslHandShakeSuccess();
ret = ssl_session->TcpSession::Connected(remote);
}
if (ret == false) {
// report connect failure and close the session
ssl_session->SetSslHandShakeFailure();
TCP_SESSION_LOG_ERROR(ssl_session, TCP_DIR_OUT,
"SSL Handshake failed due to error: "
<< error.value() << " category: "
<< error.category().name()
<< " message: " << error.message());
ssl_session->ConnectFailed();
ssl_session->CloseInternal(error, false);
}
}

bool SslSession::AsyncReadHandlerProcess(boost::asio::mutable_buffer buffer,
size_t &bytes_transferred,
boost::system::error_code &error) {
Expand Down
12 changes: 1 addition & 11 deletions src/io/ssl_session.h
Expand Up @@ -23,12 +23,6 @@ class SslSession : public TcpSession {

virtual Socket *socket() const;

// Override to trigger handshake
virtual bool Connected(Endpoint remote);

// Override to trigger handshake
virtual void Accepted();

// Trigger delayed SslHandShake
void TriggerSslHandShake(SslHandShakeCallbackHandler);

Expand Down Expand Up @@ -65,11 +59,7 @@ class SslSession : public TcpSession {

private:
class SslReader;
friend class Sslserver;
static void AcceptHandShakeHandler(TcpSessionPtr session,
const boost::system::error_code& error);
static void ConnectHandShakeHandler(TcpSessionPtr session, Endpoint remote,
const boost::system::error_code& error);
friend class SslServer;

// SslSession do actual ssl socket read for data in this context with
// session mutex held, to avoid concurrent read and write operations
Expand Down
29 changes: 19 additions & 10 deletions src/io/tcp_server.cc
Expand Up @@ -343,6 +343,17 @@ void TcpServer::AcceptHandlerInternal(TcpServerPtr server,
}

session->SessionEstablished(remote, TcpSession::PASSIVE);
AcceptHandlerComplete(session);

done:
if (need_close) {
session->CloseInternal(ec, false, false);
}
AsyncAccept();
}

void TcpServer::AcceptHandlerComplete(TcpSessionPtr &session) {
tcp::endpoint remote = session->remote_endpoint();
{
tbb::mutex::scoped_lock lock(mutex_);
if (AcceptSession(session.get())) {
Expand All @@ -357,18 +368,13 @@ void TcpServer::AcceptHandlerInternal(TcpServerPtr server,
"Rejected session from "
<< remote.address().to_string()
<< ":" << remote.port());
need_close = true;
goto done;
boost::system::error_code ec;
session->CloseInternal(ec, false, false);
return;
}
}

session->Accepted();

done:
if (need_close) {
session->CloseInternal(ec, false, false);
}
AsyncAccept();
}

TcpSession *TcpServer::GetSession(Endpoint remote) {
Expand All @@ -389,10 +395,14 @@ void TcpServer::ConnectHandler(TcpServerPtr server, TcpSessionPtr session,
return;
}

ConnectHandlerComplete(session);
}

void TcpServer::ConnectHandlerComplete(TcpSessionPtr &session) {
boost::system::error_code ec;
Endpoint remote = session->socket()->remote_endpoint(ec);
if (ec) {
TCP_SERVER_LOG_INFO(server, TCP_DIR_OUT,
TCP_SERVER_LOG_INFO(this, TCP_DIR_OUT,
"Connect getsockaddr: " << ec.message());
session->ConnectFailed();
return;
Expand All @@ -408,7 +418,6 @@ void TcpServer::ConnectHandler(TcpServerPtr server, TcpSessionPtr session,
if (!session->Connected(remote)) {
tbb::mutex::scoped_lock lock(mutex_);
RemoveSessionFromMap(remote, session.get());
return;
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/io/tcp_server.h
Expand Up @@ -85,6 +85,7 @@ class TcpServer {
const std::string &md5_password);

protected:
typedef boost::intrusive_ptr<TcpServer> TcpServerPtr;
typedef boost::intrusive_ptr<TcpSession> TcpSessionPtr;

// Create a session object.
Expand Down Expand Up @@ -112,14 +113,17 @@ class TcpServer {

Endpoint LocalEndpoint() const;

virtual void AcceptHandlerComplete(TcpSessionPtr &session);
virtual void ConnectHandlerComplete(TcpSessionPtr &session);


private:
friend class TcpSession;
friend class TcpMessageWriter;
friend class BgpServerUnitTest;
friend void intrusive_ptr_add_ref(TcpServer *server);
friend void intrusive_ptr_release(TcpServer *server);

typedef boost::intrusive_ptr<TcpServer> TcpServerPtr;
struct TcpSessionPtrCmp {
bool operator()(const TcpSessionPtr &lhs,
const TcpSessionPtr &rhs) const {
Expand Down
23 changes: 23 additions & 0 deletions src/io/test/ssl_client_cert.pem
@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDwjCCAqoCCQCorP94MWXbMjANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC
VVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlQYWxvIEFsdG8xFTATBgNVBAoTDE9w
ZW4gdlN3aXRjaDEfMB0GA1UECxMWT3BlbiB2U3dpdGNoIGNlcnRpZmllcjE6MDgG
A1UEAxMxdG9yLWFnZW50IGlkOmNhMzE4ZjI2LTAxMmItNDE3MC1iYmJkLTA5YmE2
NjFmZDU1NzAeFw0xNTAyMDkwODE2MTBaFw0yNTAyMDYwODE2MTBaMIGiMQswCQYD
VQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0bzEVMBMGA1UE
ChMMT3BlbiB2U3dpdGNoMR8wHQYDVQQLExZPcGVuIHZTd2l0Y2ggY2VydGlmaWVy
MTowOAYDVQQDEzF0b3ItYWdlbnQgaWQ6Y2EzMThmMjYtMDEyYi00MTcwLWJiYmQt
MDliYTY2MWZkNTU3MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6sn0
a5F0mIb3pbUoIRIRGx7rBebYqH5IxiHBXBSjr8cRyZFQk+iQhJ3bCLYKhsrXrrMG
0MZjlmGwhqm94LbkU4ZvMoT1yTfHyfgcFbLnBUY4hrfdYb8lfnB9naghk6jxY7Gv
BPrd2Rr/Xb50uY09/kW/BycKQ9WxAObpJn98lJstavUkd7RBVxQTYQJt/kfukfQM
MgbHEYzJrIjPmTInrZ1P4+KH8C4/GcT4+BolIsy089GI5Pw0Io/dB0NF/e1N/daq
egAuvSlgLfZwaPuCp/H/eMaslyvolgr2N7TishZi0hNgfu783Oxu9W2kCp6cJN1E
IRTyf1yUUd25ezpK6wIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQDQ+UvwBMv5vGFu
9qTmhQiEfGz2GSANs+0RgDuqh71Tr1CBNAHAXXbZApOrHXG5GYcdkWpAMc6yDWrB
CArCKLQ8pMZse/cGh2wqDmgTLvNxP/cWc3y6AldNgVXCSeaBllL8Q8oq1IEYGbSS
sElyRKMnZthSi6ulkLBs12jzKr+dbuuk+N0URriW+x8L2AmG8F0jMSjcytVrlbCg
i6CdRC3Gj/F+ZfDfSjxlOO/vMCly2ul14zg6PuuZsyqHBTgvbY8NZml74EOgjvQr
wUOJ0zmgaMLL5KeNl1ZZeKE3JXSU3MSo0/Zc6MZRjdm3TMtbnzqr9R9Z8nm3DzKu
IMjDCqFr
-----END CERTIFICATE-----
27 changes: 27 additions & 0 deletions src/io/test/ssl_client_privkey.pem
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA6sn0a5F0mIb3pbUoIRIRGx7rBebYqH5IxiHBXBSjr8cRyZFQ
k+iQhJ3bCLYKhsrXrrMG0MZjlmGwhqm94LbkU4ZvMoT1yTfHyfgcFbLnBUY4hrfd
Yb8lfnB9naghk6jxY7GvBPrd2Rr/Xb50uY09/kW/BycKQ9WxAObpJn98lJstavUk
d7RBVxQTYQJt/kfukfQMMgbHEYzJrIjPmTInrZ1P4+KH8C4/GcT4+BolIsy089GI
5Pw0Io/dB0NF/e1N/daqegAuvSlgLfZwaPuCp/H/eMaslyvolgr2N7TishZi0hNg
fu783Oxu9W2kCp6cJN1EIRTyf1yUUd25ezpK6wIDAQABAoIBAQCxR0PyZKWw9VfQ
GvTt44JfA/1ZO3Cj6JZyY9JoAH2Hn7vigoJg690TBU35Sdqw5D/ufObMhL91MNXl
GA1yuyWzm3IipxoekKud6GTsTWT6KodL0VCrGXTp/24ZuHWB1LJPID6SeAlCgIwI
8GGaKPeCIo+WivfJOHSpxbCNjP04BnDAhRvtAuNnKUW8mK1DjkjyvwM0kGXierkG
CREdCzu7mkNAWiU3JUW+dodyWFgc1E8uObACSGLlodCZJ/IBrRvO5/4mPV/76QKC
wqrCLmhdUed+2FQDtmPbiBunHrFKS0MrnO3OakxTm8C53Bd5+MEdb/I9QwavjGnO
AkZRy3pBAoGBAP889ZciTX8DPg7xwBeZvIcCbpEJAqVCZI2CxUXbDRKx20eiXqMA
TUAwFWyXvNtxkBIeJ45HS5pznBk0Usr8qykTvi0nwS84RLTHE3xTmfCRLxUCF7L9
LVRN4y7en7fIDfyfsrmpHB9wac0XFZ4Swn7EPWROt9EeivLzBDY5AbsZAoGBAOt9
Xn3n6v0gwsSF8o3e+E/nDiwyH5Rqetik1pnqCLpPbq89SVgXCfbiliB0esi+pOPh
zn3Vf5I5KSnZOjdJhlz5JBKNOaXOTxAzj3fAkqnOHYIPjDc6C/MRsKu54AD2l0fY
XCyvQBeQGlB48PEZMinNjMacWNjaypZpPMcssLqjAoGBALmFga19DX9IyA7swYdm
A5bOubdKKVYd0CDb8LA57GKuTIjhCJDKY1xIlwn7sRaAkQvaRz4vrFBzv/7B/Xv1
9CNDanQ/9TdxWt9b5Fn2Gmq13NcUUk2ToSMqCfvDbayUCTaajbpNpVdkykJ8iQYA
9MZXtZf3b7zcynqVEXaoMQ3hAoGAerHNY8hMFSrWj9JCeEyuD+OQ7NIIxilcbDgm
X/ciKQBt6PwDlNQcKvgPxEUsHB/IhbsG/WUZnLQPkHBP9rJmQVbFxqyyVoNRil1y
6K/7OmHb2gIDylqCE1kqNa8Y2Seh1psSG24L9LruGvOIhfXcvw8LxAd9+y6z0v5t
3lCYnAUCgYEAi9uR3Zq2lUaS42E69mqiUYd/E1U9tqUOxPmxnB+qNPRh1t+eNay8
g1mmKQT4RPrb1aWghcNvLAxmKp1XEtXggttFQM/lANNp3RGW+f9MxriDvduk4m5t
dgPiji/iMlOwEKx4m3MU0Fns0+RKjB0du0m5ALJGcXlU9fTuaGlG6Ts=
-----END RSA PRIVATE KEY-----

0 comments on commit efecd7c

Please sign in to comment.