nghttpx: Add client auth options for session cache memcached TLS connection

This commit is contained in:
Tatsuhiro Tsujikawa 2016-02-13 00:20:38 +09:00
parent f1580f95d4
commit 3297a303bf
8 changed files with 89 additions and 20 deletions

View File

@ -115,7 +115,9 @@ OPTIONS = [
"max-header-fields", "max-header-fields",
"no-http2-cipher-black-list", "no-http2-cipher-black-list",
"backend-http1-tls", "backend-http1-tls",
"backend-tls-session-cache-per-worker" "backend-tls-session-cache-per-worker",
"tls-session-cache-memcached-cert-file",
"tls-session-cache-memcached-private-key-file"
] ]
LOGVARS = [ LOGVARS = [

View File

@ -1567,6 +1567,12 @@ SSL/TLS:
--tls-session-cache-memcached-tls --tls-session-cache-memcached-tls
Enable SSL/TLS on memcached connections to store session Enable SSL/TLS on memcached connections to store session
cache. cache.
--tls-session-cache-memcached-cert-file=<PATH>
Path to client certificate for memcached connections to
store session cache.
--tls-session-cache-memcached-private-key-file=<PATH>
Path to client private key for memcached connections to
store session cache.
--tls-dyn-rec-warmup-threshold=<SIZE> --tls-dyn-rec-warmup-threshold=<SIZE>
Specify the threshold size for TLS dynamic record size Specify the threshold size for TLS dynamic record size
behaviour. During a TLS session, after the threshold behaviour. During a TLS session, after the threshold
@ -2404,6 +2410,10 @@ int main(int argc, char **argv) {
{SHRPX_OPT_BACKEND_TLS_SESSION_CACHE_PER_WORKER, required_argument, {SHRPX_OPT_BACKEND_TLS_SESSION_CACHE_PER_WORKER, required_argument,
&flag, 107}, &flag, 107},
{SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, no_argument, &flag, 108}, {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, no_argument, &flag, 108},
{SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE, required_argument,
&flag, 109},
{SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE,
required_argument, &flag, 110},
{nullptr, 0, nullptr, 0}}; {nullptr, 0, nullptr, 0}};
int option_index = 0; int option_index = 0;
@ -2866,6 +2876,16 @@ int main(int argc, char **argv) {
// --tls-session-cache-memcached-tls // --tls-session-cache-memcached-tls
cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, "yes"); cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, "yes");
break; break;
case 109:
// --tls-session-cache-memcached-cert-file
cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE,
optarg);
break;
case 110:
// --tls-session-cache-memcached-private-key-file
cmdcfgs.emplace_back(
SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE, optarg);
break;
default: default:
break; break;
} }

View File

@ -758,6 +758,8 @@ enum {
SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD, SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD,
SHRPX_OPTID_TLS_PROTO_LIST, SHRPX_OPTID_TLS_PROTO_LIST,
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED, SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED,
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE,
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE,
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS, SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS,
SHRPX_OPTID_TLS_TICKET_KEY_CIPHER, SHRPX_OPTID_TLS_TICKET_KEY_CIPHER,
SHRPX_OPTID_TLS_TICKET_KEY_FILE, SHRPX_OPTID_TLS_TICKET_KEY_FILE,
@ -1406,6 +1408,11 @@ int option_lookup_token(const char *name, size_t namelen) {
break; break;
case 37: case 37:
switch (name[36]) { switch (name[36]) {
case 'e':
if (util::strieq_l("tls-session-cache-memcached-cert-fil", name, 36)) {
return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE;
}
break;
case 's': case 's':
if (util::strieq_l("frontend-http2-connection-window-bit", name, 36)) { if (util::strieq_l("frontend-http2-connection-window-bit", name, 36)) {
return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS; return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS;
@ -1422,6 +1429,16 @@ int option_lookup_token(const char *name, size_t namelen) {
break; break;
} }
break; break;
case 44:
switch (name[43]) {
case 'e':
if (util::strieq_l("tls-session-cache-memcached-private-key-fil", name,
43)) {
return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE;
}
break;
}
break;
} }
return -1; return -1;
} }
@ -2242,6 +2259,14 @@ int parse_config(const char *opt, const char *optarg,
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS: case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS:
mod_config()->tls.session_cache.memcached.tls = util::strieq(optarg, "yes"); mod_config()->tls.session_cache.memcached.tls = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE:
mod_config()->tls.session_cache.memcached.cert_file = optarg;
return 0;
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE:
mod_config()->tls.session_cache.memcached.private_key_file = optarg;
return 0; return 0;
case SHRPX_OPTID_CONF: case SHRPX_OPTID_CONF:
LOG(WARN) << "conf: ignored"; LOG(WARN) << "conf: ignored";

View File

@ -211,6 +211,10 @@ constexpr char SHRPX_OPT_BACKEND_TLS_SESSION_CACHE_PER_WORKER[] =
"backend-tls-session-cache-per-worker"; "backend-tls-session-cache-per-worker";
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS[] = constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS[] =
"tls-session-cache-memcached-tls"; "tls-session-cache-memcached-tls";
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE[] =
"tls-session-cache-memcached-cert-file";
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE[] =
"tls-session-cache-memcached-private-key-file";
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@ -357,6 +361,9 @@ struct TLSConfig {
Address addr; Address addr;
uint16_t port; uint16_t port;
std::unique_ptr<char[]> host; std::unique_ptr<char[]> host;
// Client private key and certificate for authentication
ImmutableString private_key_file;
ImmutableString cert_file;
bool tls; bool tls;
} memcached; } memcached;
} session_cache; } session_cache;

View File

@ -193,15 +193,18 @@ int ConnectionHandler::create_single_worker() {
all_ssl_ctx_.push_back(cl_ssl_ctx); all_ssl_ctx_.push_back(cl_ssl_ctx);
} }
auto &session_cacheconf = get_config()->tls.session_cache; auto &tlsconf = get_config()->tls;
auto &memcachedconf = get_config()->tls.session_cache.memcached;
SSL_CTX *session_cache_ssl_ctx = nullptr; SSL_CTX *session_cache_ssl_ctx = nullptr;
if (session_cacheconf.memcached.tls) { if (memcachedconf.tls) {
session_cache_ssl_ctx = ssl::create_ssl_client_context( session_cache_ssl_ctx = ssl::create_ssl_client_context(
#ifdef HAVE_NEVERBLEED #ifdef HAVE_NEVERBLEED
nb_.get(), nb_.get(),
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
nullptr, nullptr, nullptr, StringRef(), nullptr); StringRef::from_maybe_nullptr(tlsconf.cacert.get()),
StringRef(memcachedconf.cert_file),
StringRef(memcachedconf.private_key_file), StringRef(), nullptr);
all_ssl_ctx_.push_back(session_cache_ssl_ctx); all_ssl_ctx_.push_back(session_cache_ssl_ctx);
} }
@ -238,18 +241,21 @@ int ConnectionHandler::create_worker_thread(size_t num) {
all_ssl_ctx_.push_back(cl_ssl_ctx); all_ssl_ctx_.push_back(cl_ssl_ctx);
} }
auto &session_cacheconf = get_config()->tls.session_cache; auto &tlsconf = get_config()->tls;
auto &memcachedconf = get_config()->tls.session_cache.memcached;
for (size_t i = 0; i < num; ++i) { for (size_t i = 0; i < num; ++i) {
auto loop = ev_loop_new(0); auto loop = ev_loop_new(0);
SSL_CTX *session_cache_ssl_ctx = nullptr; SSL_CTX *session_cache_ssl_ctx = nullptr;
if (session_cacheconf.memcached.tls) { if (memcachedconf.tls) {
session_cache_ssl_ctx = ssl::create_ssl_client_context( session_cache_ssl_ctx = ssl::create_ssl_client_context(
#ifdef HAVE_NEVERBLEED #ifdef HAVE_NEVERBLEED
nb_.get(), nb_.get(),
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
nullptr, nullptr, nullptr, StringRef(), nullptr); StringRef::from_maybe_nullptr(tlsconf.cacert.get()),
StringRef(memcachedconf.cert_file),
StringRef(memcachedconf.private_key_file), StringRef(), nullptr);
all_ssl_ctx_.push_back(session_cache_ssl_ctx); all_ssl_ctx_.push_back(session_cache_ssl_ctx);
} }
auto worker = auto worker =

View File

@ -662,8 +662,8 @@ SSL_CTX *create_ssl_client_context(
#ifdef HAVE_NEVERBLEED #ifdef HAVE_NEVERBLEED
neverbleed_t *nb, neverbleed_t *nb,
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
const char *cacert, const char *cert_file, const char *private_key_file, const StringRef &cacert, const StringRef &cert_file,
const StringRef &alpn, const StringRef &private_key_file, const StringRef &alpn,
int (*next_proto_select_cb)(SSL *s, unsigned char **out, int (*next_proto_select_cb)(SSL *s, unsigned char **out,
unsigned char *outlen, const unsigned char *in, unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg)) { unsigned int inlen, void *arg)) {
@ -702,8 +702,8 @@ SSL_CTX *create_ssl_client_context(
<< ERR_error_string(ERR_get_error(), nullptr); << ERR_error_string(ERR_get_error(), nullptr);
} }
if (cacert) { if (!cacert.empty()) {
if (SSL_CTX_load_verify_locations(ssl_ctx, cacert, nullptr) != 1) { if (SSL_CTX_load_verify_locations(ssl_ctx, cacert.c_str(), nullptr) != 1) {
LOG(FATAL) << "Could not load trusted ca certificates from " << cacert LOG(FATAL) << "Could not load trusted ca certificates from " << cacert
<< ": " << ERR_error_string(ERR_get_error(), nullptr); << ": " << ERR_error_string(ERR_get_error(), nullptr);
@ -711,8 +711,8 @@ SSL_CTX *create_ssl_client_context(
} }
} }
if (cert_file) { if (!cert_file.empty()) {
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) { if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file.c_str()) != 1) {
LOG(FATAL) << "Could not load client certificate from " << cert_file LOG(FATAL) << "Could not load client certificate from " << cert_file
<< ": " << ERR_error_string(ERR_get_error(), nullptr); << ": " << ERR_error_string(ERR_get_error(), nullptr);
@ -720,9 +720,9 @@ SSL_CTX *create_ssl_client_context(
} }
} }
if (private_key_file) { if (!private_key_file.empty()) {
#ifndef HAVE_NEVERBLEED #ifndef HAVE_NEVERBLEED
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file, if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file.c_str(),
SSL_FILETYPE_PEM) != 1) { SSL_FILETYPE_PEM) != 1) {
LOG(FATAL) << "Could not load client private key from " LOG(FATAL) << "Could not load client private key from "
<< private_key_file << ": " << private_key_file << ": "
@ -731,7 +731,7 @@ SSL_CTX *create_ssl_client_context(
} }
#else // HAVE_NEVERBLEED #else // HAVE_NEVERBLEED
std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf; std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file, if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file.c_str(),
errbuf.data()) != 1) { errbuf.data()) != 1) {
LOG(FATAL) << "neverbleed_load_private_key_file: could not load client " LOG(FATAL) << "neverbleed_load_private_key_file: could not load client "
"private key from " << private_key_file << ": " "private key from " << private_key_file << ": "
@ -1323,8 +1323,10 @@ SSL_CTX *setup_downstream_client_ssl_context(
#ifdef HAVE_NEVERBLEED #ifdef HAVE_NEVERBLEED
nb, nb,
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
tlsconf.cacert.get(), tlsconf.client.cert_file.get(), StringRef::from_maybe_nullptr(tlsconf.cacert.get()),
tlsconf.client.private_key_file.get(), alpn, next_proto_select_cb); StringRef::from_maybe_nullptr(tlsconf.client.cert_file.get()),
StringRef::from_maybe_nullptr(tlsconf.client.private_key_file.get()),
alpn, next_proto_select_cb);
} }
CertLookupTree *create_cert_lookup_tree() { CertLookupTree *create_cert_lookup_tree() {

View File

@ -75,8 +75,8 @@ SSL_CTX *create_ssl_client_context(
#ifdef HAVE_NEVERBLEED #ifdef HAVE_NEVERBLEED
neverbleed_t *nb, neverbleed_t *nb,
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
const char *cacert, const char *cert_file, const char *private_key_file, const StringRef &cacert, const StringRef &cert_file,
const StringRef &alpn, const StringRef &private_key_file, const StringRef &alpn,
int (*next_proto_select_cb)(SSL *s, unsigned char **out, int (*next_proto_select_cb)(SSL *s, unsigned char **out,
unsigned char *outlen, const unsigned char *in, unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg)); unsigned int inlen, void *arg));

View File

@ -402,6 +402,13 @@ public:
static StringRef from_lit(const CharT(&s)[N]) { static StringRef from_lit(const CharT(&s)[N]) {
return StringRef(s, N - 1); return StringRef(s, N - 1);
} }
static StringRef from_maybe_nullptr(const char *s) {
if (s == nullptr) {
return StringRef();
}
return StringRef(s);
}
const_iterator begin() const { return base; }; const_iterator begin() const { return base; };
const_iterator cbegin() const { return base; }; const_iterator cbegin() const { return base; };