Commit 20877b11 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

nghttpx: Don't allow application protocol not listed in --npn-list option

parent 78e51494
......@@ -602,7 +602,7 @@ void print_help(std::ostream& out)
<< " Path to file that contains DH parameters in\n"
<< " PEM format. Without this option, DHE cipher\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"
<< " most desirable protocol comes first.\n"
<< " The parameter must be delimited by a single\n"
......
......@@ -34,6 +34,7 @@
#include "shrpx_http_downstream_connection.h"
#include "shrpx_http2_downstream_connection.h"
#include "shrpx_accesslog.h"
#include "shrpx_ssl.h"
#ifdef HAVE_SPDYLAY
#include "shrpx_spdy_upstream.h"
#endif // HAVE_SPDYLAY
......@@ -108,7 +109,10 @@ void upstream_eventcb(bufferevent *bev, short events, void *arg)
if(LOG_ENABLED(INFO)) {
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(SSL_session_reused(handler->get_ssl())) {
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);
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 &&
memcmp(NGHTTP2_PROTO_VERSION_ID, next_proto,
NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
......@@ -320,6 +329,10 @@ int ClientHandler::validate_next_proto()
return 0;
}
#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;
}
......@@ -331,14 +344,15 @@ int ClientHandler::validate_next_proto()
}
if(!next_proto) {
if(LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "No proto negotiated.";
CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1";
}
upstream_ = util::make_unique<HttpsUpstream>(this);
return 0;
}
if(LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Use HTTP/1.1";
CLOG(INFO, this) << "The negotiated protocol is not supported";
}
upstream_ = util::make_unique<HttpsUpstream>(this);
return 0;
return -1;
}
int ClientHandler::on_read()
......
......@@ -147,8 +147,9 @@ struct Config {
char *downstream_http_proxy_host;
// Rate limit configuration
ev_token_bucket_cfg *rate_limit_cfg;
// Comma delimited list of NPN protocol strings in the order of
// preference.
// list of supported NPN/ALPN protocol strings in the order of
// preference. The each element of this list is a NULL-terminated
// string.
char **npn_list;
// Path to file containing CA certificate solely used for client
// certificate validation
......
......@@ -831,6 +831,18 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx,
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 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,
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 shrpx
......
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