Commit 2ee65365 authored by Andrew Huang's avatar Andrew Huang Committed by Facebook GitHub Bot

Give ownership of new session callbacks to SSLContext

Summary: Giving SSLContext ownership over the new session callback attached to SSL_CTX, so that it may do additional work with the new session (i.e. forward the session to its corresponding abstracted SSLSession).

Reviewed By: yfeldblum

Differential Revision: D21021333

fbshipit-source-id: f1dc8bd17150d45498ae1c22ef4eed1d2ca00c01
parent d908fe0b
......@@ -35,10 +35,6 @@ int getExDataIndex() {
return index;
}
void setExData(folly::SSLContext* context, SSL_CTX* ctx) {
SSL_CTX_set_ex_data(ctx, getExDataIndex(), context);
}
} // namespace
namespace folly {
......@@ -92,7 +88,7 @@ SSLContext::SSLContext(SSLVersion version) {
sslAcceptRunner_ = std::make_unique<SSLAcceptRunner>();
setExData(this, ctx_);
setupCtx(ctx_);
#if FOLLY_OPENSSL_HAS_SNI
SSL_CTX_set_tlsext_servername_callback(ctx_, baseServerNameOpenSSLCallback);
......@@ -159,7 +155,7 @@ void SSLContext::setServerECCurve(const std::string& curveName) {
}
SSLContext::SSLContext(SSL_CTX* ctx) : ctx_(ctx) {
setExData(this, ctx);
setupCtx(ctx);
if (SSL_CTX_up_ref(ctx) == 0) {
throw std::runtime_error("Failed to increment SSL_CTX refcount");
}
......@@ -672,10 +668,43 @@ void SSLContext::enableTLS13() {
#endif
}
void SSLContext::setupCtx(SSL_CTX* ctx) {
// Client caching required for receiving sessions in TLS 1.3
// Default value from OpenSSL is SSL_SESS_CACHE_SERVER
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
SSL_CTX_set_ex_data(ctx, getExDataIndex(), this);
SSL_CTX_sess_set_new_cb(ctx, SSLContext::newSessionCallback);
}
SSLContext* SSLContext::getFromSSLCtx(const SSL_CTX* ctx) {
return static_cast<SSLContext*>(SSL_CTX_get_ex_data(ctx, getExDataIndex()));
}
int SSLContext::newSessionCallback(SSL* ssl, SSL_SESSION* session) {
SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
SSLContext* context = getFromSSLCtx(ctx);
auto& cb = context->sessionLifecycleCallbacks_;
if (cb != nullptr && cb) {
SSL_SESSION_up_ref(session);
auto sessionPtr = folly::ssl::SSLSessionUniquePtr(session);
cb->onNewSession(ssl, std::move(sessionPtr));
}
SSL_SESSION_free(session);
return 1;
}
void SSLContext::attachSessionLifecycleCallbacks(
std::unique_ptr<SessionLifecycleCallbacks> cb) {
sessionLifecycleCallbacks_ = std::move(cb);
}
void SSLContext::removeSessionLifecycleCallbacks() {
sessionLifecycleCallbacks_ = nullptr;
}
std::ostream& operator<<(std::ostream& os, const PasswordCollector& collector) {
os << collector.describe();
return os;
......
......@@ -84,6 +84,11 @@ class SSLAcceptRunner {
*/
class SSLContext {
public:
struct SessionLifecycleCallbacks {
virtual void onNewSession(SSL*, folly::ssl::SSLSessionUniquePtr) = 0;
virtual ~SessionLifecycleCallbacks() = default;
};
enum SSLVersion {
SSLv2,
SSLv3,
......@@ -564,6 +569,11 @@ class SSLContext {
*/
static SSLContext* getFromSSLCtx(const SSL_CTX* ctx);
void attachSessionLifecycleCallbacks(
std::unique_ptr<SessionLifecycleCallbacks> cb);
void removeSessionLifecycleCallbacks();
[[deprecated("Use folly::ssl::init")]] static void initializeOpenSSL();
protected:
......@@ -638,6 +648,13 @@ class SSLContext {
#endif
std::string providedCiphersString_;
void setupCtx(SSL_CTX* ctx);
std::unique_ptr<SessionLifecycleCallbacks> sessionLifecycleCallbacks_{
nullptr};
static int newSessionCallback(SSL* ssl, SSL_SESSION* session);
};
typedef std::shared_ptr<SSLContext> SSLContextPtr;
......
......@@ -30,18 +30,18 @@ using folly::ssl::detail::OpenSSLSession;
namespace folly {
class SimpleCallbackManager {
class SimpleCallbackManager
: public folly::SSLContext::SessionLifecycleCallbacks {
public:
static int sessionCallback(SSL* ssl, SSL_SESSION* session) {
auto sessionPtr = folly::ssl::SSLSessionUniquePtr(session);
void onNewSession(SSL* ssl, folly::ssl::SSLSessionUniquePtr session)
override {
auto socket = folly::AsyncSSLSocket::getFromSSL(ssl);
auto sslSession =
std::dynamic_pointer_cast<folly::ssl::detail::OpenSSLSession>(
socket->getSSLSessionV2());
if (sslSession) {
sslSession->setActiveSession(std::move(sessionPtr));
sslSession->setActiveSession(std::move(session));
}
return 1;
}
};
......@@ -62,13 +62,8 @@ void getctx(
std::shared_ptr<folly::SSLContext> serverCtx) {
clientCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
clientCtx->loadTrustedCertificates(kTestCA);
auto clientCtx_ = clientCtx->getSSLCtx();
// The following two actions (setting session cache mode and
// setting the session callback) will eventually be done in
// SSLContext instead
SSL_CTX_set_session_cache_mode(clientCtx_, SSL_SESS_CACHE_CLIENT);
SSL_CTX_sess_set_new_cb(clientCtx_, SimpleCallbackManager::sessionCallback);
clientCtx->attachSessionLifecycleCallbacks(
std::make_unique<SimpleCallbackManager>());
serverCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
serverCtx->loadCertificate(kTestCert);
......@@ -176,7 +171,6 @@ TEST_F(SSLSessionTest, BasicRegressionTest) {
sslSession = clientPtr->getSSLSession();
ASSERT_NE(sslSession, nullptr);
SSL_SESSION_free(sslSession);
}
// Session resumption
......@@ -198,6 +192,7 @@ TEST_F(SSLSessionTest, BasicRegressionTest) {
eventBase.loop();
ASSERT_TRUE(client.handshakeSuccess_);
ASSERT_TRUE(clientPtr->getSSLSessionReused());
SSL_SESSION_free(sslSession);
}
}
......
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