Merge branch 'nghttpx-more-tls-options'

This commit is contained in:
Tatsuhiro Tsujikawa 2017-01-08 22:57:21 +09:00
commit 95dd908834
7 changed files with 69 additions and 9 deletions

View File

@ -155,6 +155,8 @@ OPTIONS = [
"frontend-keep-alive-timeout", "frontend-keep-alive-timeout",
"psk-secrets", "psk-secrets",
"client-psk-secrets", "client-psk-secrets",
"client-no-http2-cipher-black-list",
"client-ciphers",
] ]
LOGVARS = [ LOGVARS = [

View File

@ -1896,8 +1896,11 @@ Timeout:
SSL/TLS: SSL/TLS:
--ciphers=<SUITE> --ciphers=<SUITE>
Set allowed cipher list. The format of the string is Set allowed cipher list for frontend connection. The
described in OpenSSL ciphers(1). format of the string is described in OpenSSL ciphers(1).
--client-ciphers=<SUITE>
Set allowed cipher list for backend connection. The
format of the string is described in OpenSSL ciphers(1).
--ecdh-curves=<LIST> --ecdh-curves=<LIST>
Set supported curve list for frontend connections. Set supported curve list for frontend connections.
<LIST> is a colon separated list of curve NID or names <LIST> is a colon separated list of curve NID or names
@ -2091,9 +2094,15 @@ SSL/TLS:
Default: )" Default: )"
<< util::duration_str(config->tls.dyn_rec.idle_timeout) << R"( << util::duration_str(config->tls.dyn_rec.idle_timeout) << R"(
--no-http2-cipher-black-list --no-http2-cipher-black-list
Allow black listed cipher suite on HTTP/2 connection. Allow black listed cipher suite on frontend HTTP/2
See https://tools.ietf.org/html/rfc7540#appendix-A for connection. See
the complete HTTP/2 cipher suites black list. https://tools.ietf.org/html/rfc7540#appendix-A for the
complete HTTP/2 cipher suites black list.
--client-no-http2-cipher-black-list
Allow black listed cipher suite on backend HTTP/2
connection. See
https://tools.ietf.org/html/rfc7540#appendix-A for the
complete HTTP/2 cipher suites black list.
--tls-sct-dir=<DIR> --tls-sct-dir=<DIR>
Specifies the directory where *.sct files exist. All Specifies the directory where *.sct files exist. All
*.sct files in <DIR> are read, and sent as *.sct files in <DIR> are read, and sent as
@ -3096,6 +3105,9 @@ int main(int argc, char **argv) {
&flag, 146}, &flag, 146},
{SHRPX_OPT_PSK_SECRETS.c_str(), required_argument, &flag, 147}, {SHRPX_OPT_PSK_SECRETS.c_str(), required_argument, &flag, 147},
{SHRPX_OPT_CLIENT_PSK_SECRETS.c_str(), required_argument, &flag, 148}, {SHRPX_OPT_CLIENT_PSK_SECRETS.c_str(), required_argument, &flag, 148},
{SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST.c_str(), no_argument,
&flag, 149},
{SHRPX_OPT_CLIENT_CIPHERS.c_str(), required_argument, &flag, 150},
{nullptr, 0, nullptr, 0}}; {nullptr, 0, nullptr, 0}};
int option_index = 0; int option_index = 0;
@ -3794,6 +3806,15 @@ int main(int argc, char **argv) {
// --client-psk-secrets // --client-psk-secrets
cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PSK_SECRETS, StringRef{optarg}); cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PSK_SECRETS, StringRef{optarg});
break; break;
case 149:
// --client-no-http2-cipher-black-list
cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST,
StringRef::from_lit("yes"));
break;
case 150:
// --client-ciphers
cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_CIPHERS, StringRef{optarg});
break;
default: default:
break; break;
} }

View File

@ -1585,6 +1585,9 @@ int option_lookup_token(const char *name, size_t namelen) {
if (util::strieq_l("backend-no-tl", name, 13)) { if (util::strieq_l("backend-no-tl", name, 13)) {
return SHRPX_OPTID_BACKEND_NO_TLS; return SHRPX_OPTID_BACKEND_NO_TLS;
} }
if (util::strieq_l("client-cipher", name, 13)) {
return SHRPX_OPTID_CLIENT_CIPHERS;
}
break; break;
case 't': case 't':
if (util::strieq_l("tls-proto-lis", name, 13)) { if (util::strieq_l("tls-proto-lis", name, 13)) {
@ -2004,6 +2007,11 @@ int option_lookup_token(const char *name, size_t namelen) {
return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL; return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL;
} }
break; break;
case 't':
if (util::strieq_l("client-no-http2-cipher-black-lis", name, 32)) {
return SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST;
}
break;
} }
break; break;
case 34: case 34:
@ -3274,6 +3282,15 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return parse_psk_secrets(config, optarg); return parse_psk_secrets(config, optarg);
case SHRPX_OPTID_CLIENT_PSK_SECRETS: case SHRPX_OPTID_CLIENT_PSK_SECRETS:
return parse_client_psk_secrets(config, optarg); return parse_client_psk_secrets(config, optarg);
case SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST:
config->tls.client.no_http2_cipher_black_list =
util::strieq_l("yes", optarg);
return 0;
case SHRPX_OPTID_CLIENT_CIPHERS:
config->tls.client.ciphers = make_string_ref(config->balloc, optarg);
return 0;
case SHRPX_OPTID_CONF: case SHRPX_OPTID_CONF:
LOG(WARN) << "conf: ignored"; LOG(WARN) << "conf: ignored";

View File

@ -322,6 +322,9 @@ constexpr auto SHRPX_OPT_FRONTEND_KEEP_ALIVE_TIMEOUT =
constexpr auto SHRPX_OPT_PSK_SECRETS = StringRef::from_lit("psk-secrets"); constexpr auto SHRPX_OPT_PSK_SECRETS = StringRef::from_lit("psk-secrets");
constexpr auto SHRPX_OPT_CLIENT_PSK_SECRETS = constexpr auto SHRPX_OPT_CLIENT_PSK_SECRETS =
StringRef::from_lit("client-psk-secrets"); StringRef::from_lit("client-psk-secrets");
constexpr auto SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST =
StringRef::from_lit("client-no-http2-cipher-black-list");
constexpr auto SHRPX_OPT_CLIENT_CIPHERS = StringRef::from_lit("client-ciphers");
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@ -556,6 +559,8 @@ struct TLSConfig {
} psk; } psk;
StringRef private_key_file; StringRef private_key_file;
StringRef cert_file; StringRef cert_file;
StringRef ciphers;
bool no_http2_cipher_black_list;
} client; } client;
// PSK secrets. The key is identity, and the associated value is // PSK secrets. The key is identity, and the associated value is
@ -924,6 +929,8 @@ enum {
SHRPX_OPTID_CIPHERS, SHRPX_OPTID_CIPHERS,
SHRPX_OPTID_CLIENT, SHRPX_OPTID_CLIENT,
SHRPX_OPTID_CLIENT_CERT_FILE, SHRPX_OPTID_CLIENT_CERT_FILE,
SHRPX_OPTID_CLIENT_CIPHERS,
SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST,
SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE, SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE,
SHRPX_OPTID_CLIENT_PROXY, SHRPX_OPTID_CLIENT_PROXY,
SHRPX_OPTID_CLIENT_PSK_SECRETS, SHRPX_OPTID_CLIENT_PSK_SECRETS,

View File

@ -141,7 +141,10 @@ void Connection::disconnect() {
void Connection::prepare_client_handshake() { SSL_set_connect_state(tls.ssl); } void Connection::prepare_client_handshake() { SSL_set_connect_state(tls.ssl); }
void Connection::prepare_server_handshake() { SSL_set_accept_state(tls.ssl); } void Connection::prepare_server_handshake() {
SSL_set_accept_state(tls.ssl);
tls.server_handshake = true;
}
// BIO implementation is inspired by openldap implementation: // BIO implementation is inspired by openldap implementation:
// http://www.openldap.org/devel/cvsweb.cgi/~checkout~/libraries/libldap/tls_o.c // http://www.openldap.org/devel/cvsweb.cgi/~checkout~/libraries/libldap/tls_o.c
@ -530,7 +533,15 @@ int Connection::check_http2_requirement() {
} }
return -1; return -1;
} }
if (!get_config()->tls.no_http2_cipher_black_list &&
auto check_black_list = false;
if (tls.server_handshake) {
check_black_list = !get_config()->tls.no_http2_cipher_black_list;
} else {
check_black_list = !get_config()->tls.client.no_http2_cipher_black_list;
}
if (check_black_list &&
nghttp2::ssl::check_http2_cipher_black_list(tls.ssl)) { nghttp2::ssl::check_http2_cipher_black_list(tls.ssl)) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
LOG(INFO) << "The negotiated cipher suite is in HTTP/2 cipher suite " LOG(INFO) << "The negotiated cipher suite is in HTTP/2 cipher suite "

View File

@ -64,6 +64,8 @@ struct TLSConnection {
int handshake_state; int handshake_state;
bool initial_handshake_done; bool initial_handshake_done;
bool reneg_started; bool reneg_started;
// true if ssl is prepared to do handshake as server.
bool server_handshake;
}; };
struct TCPHint { struct TCPHint {

View File

@ -874,8 +874,8 @@ SSL_CTX *create_ssl_client_context(
SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask); SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
const char *ciphers; const char *ciphers;
if (!tlsconf.ciphers.empty()) { if (!tlsconf.client.ciphers.empty()) {
ciphers = tlsconf.ciphers.c_str(); ciphers = tlsconf.client.ciphers.c_str();
} else { } else {
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST; ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
} }