nghttpx: Add --tls-proto-list option to enable SSL/TLS protocol selectively

This commit is contained in:
Tatsuhiro Tsujikawa 2014-01-02 11:49:38 +09:00
parent 3e21bed4f9
commit 7ce3065f32
4 changed files with 65 additions and 2 deletions

View File

@ -329,6 +329,10 @@ const char *DEFAULT_NPN_LIST = NGHTTP2_PROTO_VERSION_ID ","
"http/1.1";
} // namespace
namespace {
const char *DEFAULT_TLS_PROTO_LIST = "TLSv1.2,TLSv1.1,TLSv1.0";
} // namespace
namespace {
void fill_default_config()
{
@ -622,6 +626,17 @@ void print_help(std::ostream& out)
<< " Path to file that contains client\n"
<< " certificate used in backend client\n"
<< " authentication.\n"
<< " --tls-proto-list=<LIST>\n"
<< " Comma delimited list of SSL/TLS protocol to\n"
<< " be enabled.\n"
<< " The following protocols are available:\n"
<< " TLSv1.2, TLSv1.1, TLSv1.0, SSLv3\n"
<< " The name matching is done in case-insensitive\n"
<< " manner.\n"
<< " The parameter must be delimited by a single\n"
<< " comma only and any white spaces are treated\n"
<< " as a part of protocol string.\n"
<< " Default: " << DEFAULT_TLS_PROTO_LIST << "\n"
<< "\n"
<< " HTTP/2.0 and SPDY:\n"
<< " -c, --http2-max-concurrent-streams=<NUM>\n"
@ -798,6 +813,7 @@ int main(int argc, char **argv)
{"http2-no-cookie-crumbling", no_argument, &flag, 45},
{"frontend-http2-connection-window-bits", required_argument, &flag, 46},
{"backend-http2-connection-window-bits", required_argument, &flag, 47},
{"tls-proto-list", required_argument, &flag, 48},
{nullptr, 0, nullptr, 0 }
};
@ -1049,6 +1065,10 @@ int main(int argc, char **argv)
(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS,
optarg));
break;
case 48:
// --tls-proto-list
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_TLS_PROTO_LIST, optarg));
break;
default:
break;
}
@ -1091,6 +1111,10 @@ int main(int argc, char **argv)
mod_config()->npn_list = parse_config_str_list(&mod_config()->npn_list_len,
DEFAULT_NPN_LIST);
}
if(!get_config()->tls_proto_list) {
mod_config()->tls_proto_list = parse_config_str_list
(&mod_config()->tls_proto_list_len, DEFAULT_TLS_PROTO_LIST);
}
if(!get_config()->subcerts.empty()) {
mod_config()->cert_tree = ssl::cert_lookup_tree_new();

View File

@ -105,6 +105,7 @@ const char SHRPX_OPT_READ_BURST[] = "read-burst";
const char SHRPX_OPT_WRITE_RATE[] = "write-rate";
const char SHRPX_OPT_WRITE_BURST[] = "write-burst";
const char SHRPX_OPT_NPN_LIST[] = "npn-list";
const char SHRPX_OPT_TLS_PROTO_LIST[] = "tls-proto-list";
const char SHRPX_OPT_VERIFY_CLIENT[] = "verify-client";
const char SHRPX_OPT_VERIFY_CLIENT_CACERT[] = "verify-client-cacert";
const char SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE[] = "client-private-key-file";
@ -453,6 +454,10 @@ int parse_config(const char *opt, const char *optarg)
delete [] mod_config()->npn_list;
mod_config()->npn_list = parse_config_str_list(&mod_config()->npn_list_len,
optarg);
} else if(util::strieq(opt, SHRPX_OPT_TLS_PROTO_LIST)) {
delete [] mod_config()->tls_proto_list;
mod_config()->tls_proto_list = parse_config_str_list
(&mod_config()->tls_proto_list_len, optarg);
} else if(util::strieq(opt, SHRPX_OPT_VERIFY_CLIENT)) {
mod_config()->verify_client = util::strieq(optarg, "yes");
} else if(util::strieq(opt, SHRPX_OPT_VERIFY_CLIENT_CACERT)) {

View File

@ -94,6 +94,7 @@ extern const char SHRPX_OPT_READ_BURST[];
extern const char SHRPX_OPT_WRITE_RATE[];
extern const char SHRPX_OPT_WRITE_BURST[];
extern const char SHRPX_OPT_NPN_LIST[];
extern const char SHRPX_OPT_TLS_PROTO_LIST[];
extern const char SHRPX_OPT_VERIFY_CLIENT[];
extern const char SHRPX_OPT_VERIFY_CLIENT_CACERT[];
extern const char SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE[];
@ -151,6 +152,9 @@ struct Config {
// preference. The each element of this list is a NULL-terminated
// string.
char **npn_list;
// list of supported SSL/TLS protocol strings. The each element of
// this list is a NULL-terminated string.
char **tls_proto_list;
// Path to file containing CA certificate solely used for client
// certificate validation
char *verify_client_cacert;
@ -173,6 +177,8 @@ struct Config {
size_t write_burst;
// The number of elements in npn_list
size_t npn_list_len;
// The number of elements in tls_proto_list
size_t tls_proto_list_len;
// downstream protocol; this will be determined by given options.
shrpx_proto downstream_proto;
int syslog_facility;

View File

@ -149,6 +149,29 @@ int alpn_select_proto_cb(SSL* ssl,
} // namespace
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
namespace {
const char *names[] = { "TLSv1.2", "TLSv1.1", "TLSv1.0", "SSLv3" };
const size_t namelen = sizeof(names)/sizeof(names[0]);
const long int masks[] = { SSL_OP_NO_TLSv1_2, SSL_OP_NO_TLSv1_1,
SSL_OP_NO_TLSv1, SSL_OP_NO_SSLv3 };
long int create_tls_proto_mask(char **tls_proto_list, size_t len)
{
long int res = 0;
for(size_t i = 0; i < namelen; ++i) {
size_t j;
for(j = 0; j < len; ++j) {
if(strcasecmp(names[i], tls_proto_list[j]) == 0) {
break;
}
}
if(j == len) {
res |= masks[i];
}
}
return res;
}
} // namespace
SSL_CTX* create_ssl_context(const char *private_key_file,
const char *cert_file)
{
@ -158,11 +181,14 @@ SSL_CTX* create_ssl_context(const char *private_key_file,
LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr);
DIE();
}
SSL_CTX_set_options(ssl_ctx,
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
SSL_OP_SINGLE_ECDH_USE | SSL_OP_SINGLE_DH_USE |
SSL_OP_NO_TICKET);
SSL_OP_NO_TICKET |
create_tls_proto_mask(get_config()->tls_proto_list,
get_config()->tls_proto_list_len));
const unsigned char sid_ctx[] = "shrpx";
SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx)-1);
@ -295,7 +321,9 @@ SSL_CTX* create_ssl_client_context()
}
SSL_CTX_set_options(ssl_ctx,
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
create_tls_proto_mask(get_config()->tls_proto_list,
get_config()->tls_proto_list_len));
if(get_config()->ciphers) {
if(SSL_CTX_set_cipher_list(ssl_ctx, get_config()->ciphers) == 0) {