Commit dd7d175a authored by Samuel Miller's avatar Samuel Miller Committed by Facebook GitHub Bot

Factor ticket key manager into handler interface

Summary:
I've created an abstract class called `OpenSSLTicketHandler` to which the
server's ssl context dispatches ticket crypto preparation. This means that
changing the configuration of how tickets are encrypted can be changed by
using a different implementation of the handler.

This abstraction is sort of broken by all the set and get APIs on the context
that modify ticket secrets, rather than properly abstracting this detail into
a concrete impl of the handler (e.g. a `TLSTicketKeyManager` can manage secrets
from a file and not require users to pass all these secrets down from the
acceptors). For now though we rely on (checked!) dynamic casts to get a
`TLSTicketKeyManager` from which we can freely modify the secrets.

Reviewed By: mingtaoy

Differential Revision: D24686664

fbshipit-source-id: fb30941982fb3114e2aba531372a9d35ccc0ee48
parent d4241c98
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <folly/SharedMutex.h> #include <folly/SharedMutex.h>
#include <folly/SpinLock.h> #include <folly/SpinLock.h>
#include <folly/ssl/Init.h> #include <folly/ssl/Init.h>
#include <folly/ssl/OpenSSLTicketHandler.h>
#include <folly/ssl/SSLSessionManager.h> #include <folly/ssl/SSLSessionManager.h>
#include <folly/system/ThreadId.h> #include <folly/system/ThreadId.h>
...@@ -102,6 +103,24 @@ void configureProtocolVersion(SSL_CTX* ctx, SSLContext::SSLVersion version) { ...@@ -102,6 +103,24 @@ void configureProtocolVersion(SSL_CTX* ctx, SSLContext::SSLVersion version) {
DCHECK((newOpt & opt) == opt); DCHECK((newOpt & opt) == opt);
#endif // FOLLY_OPENSSL_PREREQ(1, 1, 0) #endif // FOLLY_OPENSSL_PREREQ(1, 1, 0)
} }
static int dispatchTicketCrypto(
SSL* ssl,
unsigned char* keyName,
unsigned char* iv,
EVP_CIPHER_CTX* cipherCtx,
HMAC_CTX* hmacCtx,
int encrypt) {
auto ctx = folly::SSLContext::getFromSSLCtx(SSL_get_SSL_CTX(ssl));
DCHECK(ctx);
auto handler = ctx->getTicketHandler();
if (!handler) {
LOG(FATAL) << "Null OpenSSLTicketHandler in callback";
}
return handler->ticketCallback(ssl, keyName, iv, cipherCtx, hmacCtx, encrypt);
}
} // namespace } // namespace
// //
...@@ -854,6 +873,14 @@ void SSLContext::setAllowNoDheKex(bool flag) { ...@@ -854,6 +873,14 @@ void SSLContext::setAllowNoDheKex(bool flag) {
} }
#endif // FOLLY_OPENSSL_PREREQ(1, 1, 1) #endif // FOLLY_OPENSSL_PREREQ(1, 1, 1)
void SSLContext::setTicketHandler(
std::unique_ptr<OpenSSLTicketHandler> handler) {
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
ticketHandler_ = std::move(handler);
SSL_CTX_set_tlsext_ticket_key_cb(ctx_, dispatchTicketCrypto);
#endif
}
std::ostream& operator<<(std::ostream& os, const PasswordCollector& collector) { std::ostream& operator<<(std::ostream& os, const PasswordCollector& collector) {
os << collector.describe(); os << collector.describe();
return os; return os;
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
namespace folly { namespace folly {
class OpenSSLTicketHandler;
/** /**
* Override the default password collector. * Override the default password collector.
*/ */
...@@ -580,6 +582,10 @@ class SSLContext { ...@@ -580,6 +582,10 @@ class SSLContext {
const SSLAcceptRunner* sslAcceptRunner() { return sslAcceptRunner_.get(); } const SSLAcceptRunner* sslAcceptRunner() { return sslAcceptRunner_.get(); }
void setTicketHandler(std::unique_ptr<OpenSSLTicketHandler> handler);
OpenSSLTicketHandler* getTicketHandler() { return ticketHandler_.get(); }
/** /**
* Helper to match a hostname versus a pattern. * Helper to match a hostname versus a pattern.
*/ */
...@@ -650,6 +656,7 @@ class SSLContext { ...@@ -650,6 +656,7 @@ class SSLContext {
static bool initialized_; static bool initialized_;
std::unique_ptr<SSLAcceptRunner> sslAcceptRunner_; std::unique_ptr<SSLAcceptRunner> sslAcceptRunner_;
std::unique_ptr<OpenSSLTicketHandler> ticketHandler_;
#if FOLLY_OPENSSL_HAS_ALPN #if FOLLY_OPENSSL_HAS_ALPN
......
/*
* 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 <folly/portability/OpenSSL.h>
namespace folly {
/**
* The OpenSSLTicketHandler handles TLS ticket encryption and decryption.
*
* This is meant to be used within an SSLContext to configure ticket resumption
* for the SSL_CTX by leveraging the SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB API. Note
* that the interface here is constrained by the API OpenSSL exposes and is
* therefore not intended for other TLS implementations.
*
* An OpenSSLTicketHandler should be used in only one thread, and should be
* unique to each SSLContext.
*/
class OpenSSLTicketHandler {
public:
virtual ~OpenSSLTicketHandler() = default;
/**
* Method to setup encryption/decryption context for a TLS Ticket.
*
* For encrypt=1, return < 0 on error, >= 0 for successfully initialized
* For encrypt=0, return < 0 on error, 0 on key not found
* 1 on key found, 2 renew_ticket
*
* where renew_ticket means a new ticket will be issued.
*/
virtual int ticketCallback(
SSL* ssl,
unsigned char* keyName,
unsigned char* iv,
EVP_CIPHER_CTX* cipherCtx,
HMAC_CTX* hmacCtx,
int encrypt) = 0;
};
} // 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