nghttpx: Don't allow application protocol not listed in --npn-list option
This commit is contained in:
parent
78e5149495
commit
20877b1107
|
@ -602,7 +602,7 @@ void print_help(std::ostream& out)
|
||||||
<< " Path to file that contains DH parameters in\n"
|
<< " Path to file that contains DH parameters in\n"
|
||||||
<< " PEM format. Without this option, DHE cipher\n"
|
<< " PEM format. Without this option, DHE cipher\n"
|
||||||
<< " suites are not available.\n"
|
<< " suites are not available.\n"
|
||||||
<< " --npn-list=<LIST> Comma delimited list of NPN protocol sorted\n"
|
<< " --npn-list=<LIST> Comma delimited list of NPN/ALPN protocol sorted\n"
|
||||||
<< " in the order of preference. That means\n"
|
<< " in the order of preference. That means\n"
|
||||||
<< " most desirable protocol comes first.\n"
|
<< " most desirable protocol comes first.\n"
|
||||||
<< " The parameter must be delimited by a single\n"
|
<< " The parameter must be delimited by a single\n"
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "shrpx_http_downstream_connection.h"
|
#include "shrpx_http_downstream_connection.h"
|
||||||
#include "shrpx_http2_downstream_connection.h"
|
#include "shrpx_http2_downstream_connection.h"
|
||||||
#include "shrpx_accesslog.h"
|
#include "shrpx_accesslog.h"
|
||||||
|
#include "shrpx_ssl.h"
|
||||||
#ifdef HAVE_SPDYLAY
|
#ifdef HAVE_SPDYLAY
|
||||||
#include "shrpx_spdy_upstream.h"
|
#include "shrpx_spdy_upstream.h"
|
||||||
#endif // HAVE_SPDYLAY
|
#endif // HAVE_SPDYLAY
|
||||||
|
@ -108,7 +109,10 @@ void upstream_eventcb(bufferevent *bev, short events, void *arg)
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
CLOG(INFO, handler) << "SSL/TLS handleshake completed";
|
CLOG(INFO, handler) << "SSL/TLS handleshake completed";
|
||||||
}
|
}
|
||||||
handler->validate_next_proto();
|
if(handler->validate_next_proto() != 0) {
|
||||||
|
delete handler;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
if(SSL_session_reused(handler->get_ssl())) {
|
if(SSL_session_reused(handler->get_ssl())) {
|
||||||
CLOG(INFO, handler) << "SSL/TLS session reused";
|
CLOG(INFO, handler) << "SSL/TLS session reused";
|
||||||
|
@ -305,6 +309,11 @@ int ClientHandler::validate_next_proto()
|
||||||
std::string proto(next_proto, next_proto+next_proto_len);
|
std::string proto(next_proto, next_proto+next_proto_len);
|
||||||
CLOG(INFO, this) << "The negotiated next protocol: " << proto;
|
CLOG(INFO, this) << "The negotiated next protocol: " << proto;
|
||||||
}
|
}
|
||||||
|
if(!ssl::in_proto_list(get_config()->npn_list,
|
||||||
|
get_config()->npn_list_len,
|
||||||
|
next_proto, next_proto_len)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(next_proto_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
|
if(next_proto_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
|
||||||
memcmp(NGHTTP2_PROTO_VERSION_ID, next_proto,
|
memcmp(NGHTTP2_PROTO_VERSION_ID, next_proto,
|
||||||
NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
|
NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
|
||||||
|
@ -320,6 +329,10 @@ int ClientHandler::validate_next_proto()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif // HAVE_SPDYLAY
|
#endif // HAVE_SPDYLAY
|
||||||
|
if(next_proto_len == 8 && memcmp("http/1.1", next_proto, 8) == 0) {
|
||||||
|
upstream_ = util::make_unique<HttpsUpstream>(this);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -331,15 +344,16 @@ int ClientHandler::validate_next_proto()
|
||||||
}
|
}
|
||||||
if(!next_proto) {
|
if(!next_proto) {
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
CLOG(INFO, this) << "No proto negotiated.";
|
CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1";
|
||||||
}
|
|
||||||
}
|
|
||||||
if(LOG_ENABLED(INFO)) {
|
|
||||||
CLOG(INFO, this) << "Use HTTP/1.1";
|
|
||||||
}
|
}
|
||||||
upstream_ = util::make_unique<HttpsUpstream>(this);
|
upstream_ = util::make_unique<HttpsUpstream>(this);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if(LOG_ENABLED(INFO)) {
|
||||||
|
CLOG(INFO, this) << "The negotiated protocol is not supported";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int ClientHandler::on_read()
|
int ClientHandler::on_read()
|
||||||
{
|
{
|
||||||
|
|
|
@ -147,8 +147,9 @@ struct Config {
|
||||||
char *downstream_http_proxy_host;
|
char *downstream_http_proxy_host;
|
||||||
// Rate limit configuration
|
// Rate limit configuration
|
||||||
ev_token_bucket_cfg *rate_limit_cfg;
|
ev_token_bucket_cfg *rate_limit_cfg;
|
||||||
// Comma delimited list of NPN protocol strings in the order of
|
// list of supported NPN/ALPN protocol strings in the order of
|
||||||
// preference.
|
// preference. The each element of this list is a NULL-terminated
|
||||||
|
// string.
|
||||||
char **npn_list;
|
char **npn_list;
|
||||||
// Path to file containing CA certificate solely used for client
|
// Path to file containing CA certificate solely used for client
|
||||||
// certificate validation
|
// certificate validation
|
||||||
|
|
|
@ -831,6 +831,18 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool in_proto_list(char **protos, size_t len,
|
||||||
|
const unsigned char *proto, size_t protolen)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < len; ++i) {
|
||||||
|
if(strlen(protos[i]) == protolen &&
|
||||||
|
memcmp(protos[i], proto, protolen) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ssl
|
} // namespace ssl
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -126,6 +126,12 @@ SSL_CTX* cert_lookup_tree_lookup(CertLookupTree *lt, const char *hostname,
|
||||||
int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx,
|
int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx,
|
||||||
const char *certfile);
|
const char *certfile);
|
||||||
|
|
||||||
|
// Returns true if |proto| which has |protolen| bytes is included in
|
||||||
|
// the protocol list |protos|, which has |len| elements. The format of
|
||||||
|
// the |protos| is the one used in Config::npn_list.
|
||||||
|
bool in_proto_list(char **protos, size_t len,
|
||||||
|
const unsigned char *proto, size_t protolen);
|
||||||
|
|
||||||
} // namespace ssl
|
} // namespace ssl
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
Loading…
Reference in New Issue