Commit 0ad1b3bb authored by Andrew Huang's avatar Andrew Huang Committed by Facebook GitHub Bot

Refactor AsyncSSLSocket session code into SSLSessionManager

Summary: Refactor AsyncSSLSocket session code into a new class called SSLSessionManager, which is a member of AsyncSSLSocket. Will allow for SSLContext to interact with SSLSession through SSLSessionManager, without depending on AsyncSSLSocket.

Reviewed By: yfeldblum, mingtaoy

Differential Revision: D21164020

fbshipit-source-id: e6b38336127fb000587bfe6948c2274afe8d85e0
parent abde1c0d
......@@ -19,7 +19,6 @@
#include <folly/io/async/EventBase.h>
#include <folly/portability/Sockets.h>
#include <boost/variant.hpp>
#include <fcntl.h>
#include <sys/types.h>
#include <cerrno>
......@@ -38,14 +37,13 @@
#include <folly/lang/Bits.h>
#include <folly/portability/OpenSSL.h>
#include <folly/ssl/SSLSession.h>
#include <folly/ssl/detail/OpenSSLSession.h>
#include <folly/ssl/SSLSessionManager.h>
using std::shared_ptr;
using folly::SpinLock;
using folly::io::Cursor;
using folly::ssl::SSLSessionUniquePtr;
using folly::ssl::detail::OpenSSLSession;
namespace {
using folly::AsyncSSLSocket;
......@@ -123,48 +121,6 @@ void* initsslBioMethod() {
namespace folly {
/**
* Variant visitors. Will be removed once sslSession_ is converted
* to a non-variant type.
*/
class RawSessionRetrievalVisitor : boost::static_visitor<SSLSessionUniquePtr> {
public:
SSLSessionUniquePtr operator()(const SSLSessionUniquePtr& sessionPtr) const {
if (!sessionPtr) {
return SSLSessionUniquePtr();
}
SSL_SESSION* session = sessionPtr.get();
if (session) {
SSL_SESSION_up_ref(session);
}
return SSLSessionUniquePtr(session);
}
SSLSessionUniquePtr operator()(
const shared_ptr<OpenSSLSession>& session) const {
if (!session) {
return ssl::SSLSessionUniquePtr();
}
return session->getActiveSession();
}
};
class SSLSessionRetrievalVisitor
: boost::static_visitor<shared_ptr<OpenSSLSession>> {
public:
shared_ptr<OpenSSLSession> operator()(const SSLSessionUniquePtr&) const {
return nullptr;
}
shared_ptr<OpenSSLSession> operator()(
const shared_ptr<OpenSSLSession>& session) const {
return session;
}
};
class AsyncSSLSocketConnector : public AsyncSocket::ConnectCallback,
public AsyncSSLSocket::HandshakeCB {
private:
......@@ -359,7 +315,6 @@ void AsyncSSLSocket::init() {
(void)sslBioMethodInitializer;
setup_SSL_CTX(ctx_->getSSLCtx());
sslSession_ = std::make_shared<OpenSSLSession>();
}
void AsyncSSLSocket::closeNow() {
......@@ -866,7 +821,7 @@ void AsyncSSLSocket::sslConn(
return failHandshake(__func__, *ex);
}
SSLSessionUniquePtr sessionPtr = getRawSSLSession();
SSLSessionUniquePtr sessionPtr = sslSessionManager_.getRawSession();
if (sessionPtr) {
sessionResumptionAttempted_ = true;
SSL_set_session(ssl_.get(), sessionPtr.get());
......@@ -900,11 +855,11 @@ SSL_SESSION* AsyncSSLSocket::getSSLSession() {
return SSL_get1_session(ssl_.get());
}
return getRawSSLSession().release();
return sslSessionManager_.getRawSession().release();
}
shared_ptr<ssl::SSLSession> AsyncSSLSocket::getSSLSessionV2() {
return getAbstractSSLSession();
return sslSessionManager_.getSession();
}
const SSL* AsyncSSLSocket::getSSL() const {
......@@ -917,14 +872,11 @@ void AsyncSSLSocket::setSSLSession(SSL_SESSION* session, bool takeOwnership) {
// This API exists in BoringSSL and OpenSSL 1.1.0
SSL_SESSION_up_ref(session);
}
sslSession_ = SSLSessionUniquePtr(session);
sslSessionManager_.setRawSession(SSLSessionUniquePtr(session));
}
void AsyncSSLSocket::setSSLSessionV2(shared_ptr<ssl::SSLSession> session) {
auto openSSLSession = std::dynamic_pointer_cast<OpenSSLSession>(session);
if (openSSLSession) {
sslSession_ = openSSLSession;
}
sslSessionManager_.setSession(session);
}
void AsyncSSLSocket::getSelectedNextProtocol(
......@@ -2125,14 +2077,4 @@ void AsyncSSLSocket::getSSLServerCiphers(std::string& serverCiphers) const {
}
}
SSLSessionUniquePtr AsyncSSLSocket::getRawSSLSession() const {
static auto visitor = RawSessionRetrievalVisitor();
return boost::apply_visitor(visitor, sslSession_);
}
shared_ptr<OpenSSLSession> AsyncSSLSocket::getAbstractSSLSession() const {
static auto visitor = SSLSessionRetrievalVisitor();
return boost::apply_visitor(visitor, sslSession_);
}
} // namespace folly
......@@ -16,7 +16,6 @@
#pragma once
#include <boost/variant.hpp>
#include <iomanip>
#include <folly/Optional.h>
......@@ -37,17 +36,12 @@
#include <folly/portability/Sockets.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
#include <folly/ssl/SSLSession.h>
#include <folly/ssl/SSLSessionManager.h>
namespace folly {
class AsyncSSLSocketConnector;
namespace ssl {
namespace detail {
class OpenSSLSession;
} // namespace detail
} // namespace ssl
/**
* A class for performing asynchronous I/O on an SSL connection.
*
......@@ -914,10 +908,6 @@ class AsyncSSLSocket : public virtual AsyncSocket {
static void sslInfoCallback(const SSL* ssl, int where, int ret);
folly::ssl::SSLSessionUniquePtr getRawSSLSession() const;
std::shared_ptr<folly::ssl::detail::OpenSSLSession> getAbstractSSLSession()
const;
// Whether the current write to the socket should use MSG_MORE.
bool corkCurrentWrite_{false};
// SSL related members.
......@@ -933,13 +923,6 @@ class AsyncSSLSocket : public virtual AsyncSocket {
// Callback for SSL_accept() or SSL_connect()
HandshakeCB* handshakeCallback_{nullptr};
ssl::SSLUniquePtr ssl_;
// The SSL session. Which type the variant contains depends on the
// session API that is used. Is only intended to temporarily be a variant.
// Will be converted to a non-variant once SSL session APIs are merged.
boost::variant<
folly::ssl::SSLSessionUniquePtr,
std::shared_ptr<folly::ssl::detail::OpenSSLSession>>
sslSession_;
Timeout handshakeTimeout_;
Timeout connectionTimeout_;
......@@ -1004,6 +987,8 @@ class AsyncSSLSocket : public virtual AsyncSocket {
std::unique_ptr<ReadCallback> asyncOperationFinishCallback_;
// Whether this socket is currently waiting on SSL_accept
bool waitingOnAccept_{false};
// Manages the session for the socket
folly::ssl::SSLSessionManager sslSessionManager_;
};
} // namespace folly
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/ssl/SSLSessionManager.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
#include <folly/ssl/detail/OpenSSLSession.h>
using folly::ssl::SSLSessionUniquePtr;
using folly::ssl::detail::OpenSSLSession;
using std::shared_ptr;
namespace {
/**
* Variant visitors. Will be removed once session_ is converted
* to a non-variant type.
*/
class RawSessionRetrievalVisitor : boost::static_visitor<SSLSessionUniquePtr> {
public:
SSLSessionUniquePtr operator()(const SSLSessionUniquePtr& sessionPtr) const {
SSL_SESSION* session = sessionPtr.get();
if (session) {
SSL_SESSION_up_ref(session);
}
return SSLSessionUniquePtr(session);
}
SSLSessionUniquePtr operator()(
const shared_ptr<OpenSSLSession>& session) const {
if (!session) {
return SSLSessionUniquePtr();
}
return session->getActiveSession();
}
};
class SSLSessionRetrievalVisitor
: boost::static_visitor<shared_ptr<OpenSSLSession>> {
public:
shared_ptr<OpenSSLSession> operator()(const SSLSessionUniquePtr&) const {
return nullptr;
}
shared_ptr<OpenSSLSession> operator()(
const shared_ptr<OpenSSLSession>& session) const {
return session;
}
};
} // namespace
namespace folly {
namespace ssl {
SSLSessionManager::SSLSessionManager() {
session_ = std::make_shared<OpenSSLSession>();
}
void SSLSessionManager::setSession(shared_ptr<SSLSession> session) {
if (session == nullptr) {
session_ = std::shared_ptr<OpenSSLSession>(nullptr);
return;
}
auto openSSLSession = std::dynamic_pointer_cast<OpenSSLSession>(session);
if (openSSLSession) {
session_ = openSSLSession;
}
}
void SSLSessionManager::setRawSession(SSLSessionUniquePtr session) {
session_ = std::move(session);
}
SSLSessionUniquePtr SSLSessionManager::getRawSession() const {
auto visitor = RawSessionRetrievalVisitor();
return boost::apply_visitor(visitor, session_);
}
shared_ptr<SSLSession> SSLSessionManager::getSession() const {
auto visitor = SSLSessionRetrievalVisitor();
return boost::apply_visitor(visitor, session_);
}
} // namespace ssl
} // namespace folly
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <boost/variant.hpp>
#include <folly/ssl/OpenSSLPtrTypes.h>
#include <folly/ssl/SSLSession.h>
namespace folly {
namespace ssl {
namespace detail {
class OpenSSLSession;
} // namespace detail
/**
* A class that manages one SSL session.
*
* Only intended to temporarily handle both raw session and
* abstract session types, until session APIs are merged in
* in AsyncSSLSocket. Afterwards, it will only manage an
* abstract session.
*/
class SSLSessionManager {
public:
SSLSessionManager();
~SSLSessionManager() = default;
void setSession(std::shared_ptr<folly::ssl::SSLSession> session);
std::shared_ptr<folly::ssl::SSLSession> getSession() const;
void setRawSession(folly::ssl::SSLSessionUniquePtr session);
folly::ssl::SSLSessionUniquePtr getRawSession() const;
private:
// The SSL session. Which type the variant contains depends on the
// session API that is used.
boost::variant<
folly::ssl::SSLSessionUniquePtr,
std::shared_ptr<folly::ssl::detail::OpenSSLSession>>
session_;
};
} // namespace ssl
} // namespace folly
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <folly/portability/OpenSSL.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
#include <folly/ssl/SSLSessionManager.h>
#include <folly/ssl/detail/OpenSSLSession.h>
using folly::ssl::SSLSessionManager;
using folly::ssl::SSLSessionUniquePtr;
using folly::ssl::detail::OpenSSLSession;
namespace folly {
TEST(SSLSessionManagerTest, InitialStateTest) {
SSLSessionManager manager;
EXPECT_EQ(nullptr, manager.getRawSession().get());
EXPECT_NE(nullptr, manager.getSession());
}
TEST(SSLSessionManagerTest, SetSessionTest) {
SSLSessionManager manager;
auto newSession = std::make_shared<OpenSSLSession>();
manager.setSession(newSession);
EXPECT_EQ(nullptr, manager.getRawSession().get());
EXPECT_EQ(newSession, manager.getSession());
EXPECT_EQ(newSession.get(), manager.getSession().get());
manager.setSession(nullptr);
EXPECT_EQ(nullptr, manager.getRawSession().get());
EXPECT_EQ(nullptr, manager.getSession());
EXPECT_EQ(nullptr, manager.getSession().get());
}
TEST(SSLSessionManagerTest, SetRawSesionTest) {
SSLSessionManager manager;
auto sslSession = SSL_SESSION_new();
SSL_SESSION_up_ref(sslSession);
auto newSession = SSLSessionUniquePtr(sslSession);
manager.setRawSession(std::move(newSession));
EXPECT_EQ(nullptr, manager.getSession());
EXPECT_EQ(sslSession, manager.getRawSession().get());
SSL_SESSION_free(sslSession);
manager.setRawSession(nullptr);
EXPECT_EQ(nullptr, manager.getSession());
EXPECT_EQ(nullptr, manager.getRawSession().get());
}
} // namespace folly
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment