ALPN: Do not negotiate HTTP/2 unless TLSv1.2 or TLSv1.1 was used
This commit is contained in:
parent
cd69ed20c3
commit
6c66bd5c7c
|
@ -155,6 +155,24 @@ void info_callback(const SSL *ssl, int where, int ret)
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
namespace {
|
||||||
|
// Returns true if ALPN identifier list |in| of length |inlen|
|
||||||
|
// contains http/1.1.
|
||||||
|
bool check_http1_available_in_alpn_list(const unsigned char *in,
|
||||||
|
unsigned int inlen)
|
||||||
|
{
|
||||||
|
for(unsigned int i = 0; i < inlen; i += 1 + in[i]) {
|
||||||
|
if(in[i] == 8 && i + 1 + in[i] <= inlen &&
|
||||||
|
memcmp("http/1.1", &in[i + 1], in[i]) == 0) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int alpn_select_proto_cb(SSL* ssl,
|
int alpn_select_proto_cb(SSL* ssl,
|
||||||
const unsigned char **out,
|
const unsigned char **out,
|
||||||
|
@ -164,31 +182,36 @@ int alpn_select_proto_cb(SSL* ssl,
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = nghttp2_select_next_protocol
|
if(check_http2_requirement(ssl)) {
|
||||||
(const_cast<unsigned char**>(out), outlen, in, inlen);
|
|
||||||
|
|
||||||
if(rv == 1) {
|
rv = nghttp2_select_next_protocol
|
||||||
// HTTP/2 was selected
|
(const_cast<unsigned char**>(out), outlen, in, inlen);
|
||||||
return SSL_TLSEXT_ERR_OK;
|
|
||||||
|
if(rv == 1) {
|
||||||
|
// HTTP/2 was selected
|
||||||
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
}
|
||||||
|
} else if(check_http1_available_in_alpn_list(in, inlen)) {
|
||||||
|
*out = reinterpret_cast<const unsigned char*>("http/1.1");
|
||||||
|
*outlen = strlen("http/1.1");
|
||||||
|
|
||||||
|
rv = 0;
|
||||||
|
} else {
|
||||||
|
rv = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SPDYLAY
|
#ifdef HAVE_SPDYLAY
|
||||||
rv = spdylay_select_next_protocol
|
rv = spdylay_select_next_protocol
|
||||||
(const_cast<unsigned char**>(out), outlen, in, inlen);
|
(const_cast<unsigned char**>(out), outlen, in, inlen);
|
||||||
|
|
||||||
if(rv > 0) {
|
|
||||||
// SPDY was selected
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
|
||||||
}
|
|
||||||
#endif // HAVE_SPDYLAY
|
#endif // HAVE_SPDYLAY
|
||||||
|
|
||||||
if(rv == -1) {
|
if(rv == -1) {
|
||||||
// No selection was made
|
// No selection was made
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We selected http/1.1
|
// We selected http/1.1
|
||||||
return SSL_TLSEXT_ERR_NOACK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
@ -895,6 +918,26 @@ bool in_proto_list(char **protos, size_t len,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool check_http2_requirement(SSL *ssl)
|
||||||
|
{
|
||||||
|
auto tls_ver = SSL_version(ssl);
|
||||||
|
|
||||||
|
switch(tls_ver) {
|
||||||
|
case TLS1_1_VERSION:
|
||||||
|
case TLS1_2_VERSION:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG(INFO) << "TLSv1.2 or TLSv1.1 was not negotiated. "
|
||||||
|
<< "HTTP/2 must not be negotiated.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Figure out that ECDHE or DHE was negotiated and their key
|
||||||
|
// size. SSL_get_server_tmp_key() cannot be used on server side.
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ssl
|
} // namespace ssl
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -129,6 +129,9 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx,
|
||||||
bool in_proto_list(char **protos, size_t len,
|
bool in_proto_list(char **protos, size_t len,
|
||||||
const unsigned char *proto, size_t protolen);
|
const unsigned char *proto, size_t protolen);
|
||||||
|
|
||||||
|
// Returns true if security requirement for HTTP/2 is fulfilled.
|
||||||
|
bool check_http2_requirement(SSL *ssl);
|
||||||
|
|
||||||
} // namespace ssl
|
} // namespace ssl
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
Loading…
Reference in New Issue