nghttpx: Create NPN prefs only once

This commit is contained in:
Tatsuhiro Tsujikawa 2014-06-10 23:15:29 +09:00
parent 7b0ed5d9bd
commit c204861dec
4 changed files with 31 additions and 27 deletions

View File

@ -1189,6 +1189,8 @@ int main(int argc, char **argv)
mod_config()->tls_proto_mask = mod_config()->tls_proto_mask =
ssl::create_tls_proto_mask(get_config()->tls_proto_list); ssl::create_tls_proto_mask(get_config()->tls_proto_list);
mod_config()->alpn_prefs = ssl::set_alpn_prefs(get_config()->npn_list);
if(!get_config()->subcerts.empty()) { if(!get_config()->subcerts.empty()) {
mod_config()->cert_tree = ssl::cert_lookup_tree_new(); mod_config()->cert_tree = ssl::cert_lookup_tree_new();
} }

View File

@ -152,6 +152,7 @@ struct Config {
std::vector<std::pair<std::string, std::string>> subcerts; std::vector<std::pair<std::string, std::string>> subcerts;
std::vector<AltSvc> altsvcs; std::vector<AltSvc> altsvcs;
std::vector<std::pair<std::string, std::string>> add_response_headers; std::vector<std::pair<std::string, std::string>> add_response_headers;
std::vector<unsigned char> alpn_prefs;
sockaddr_union downstream_addr; sockaddr_union downstream_addr;
// binary form of http proxy host and port // binary form of http proxy host and port
sockaddr_union downstream_http_proxy_addr; sockaddr_union downstream_http_proxy_addr;

View File

@ -57,18 +57,13 @@ namespace shrpx {
namespace ssl { namespace ssl {
namespace {
std::pair<unsigned char*, size_t> next_proto;
unsigned char proto_list[256];
} // namespace
namespace { namespace {
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len, int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
void *arg) void *arg)
{ {
auto next_proto = static_cast<std::pair<unsigned char*, size_t>*>(arg); auto& prefs = get_config()->alpn_prefs;
*data = next_proto->first; *data = prefs.data();
*len = next_proto->second; *len = prefs.size();
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
} }
} // namespace } // namespace
@ -87,21 +82,26 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
} }
} // namespace } // namespace
namespace { std::vector<unsigned char> set_alpn_prefs(const std::vector<char*>& protos)
size_t set_npn_prefs(unsigned char *out, const std::vector<char*>& protos)
{ {
unsigned char *ptr = out; unsigned char out[256];
size_t listlen = 0; auto ptr = out;
auto end = ptr + sizeof(out);
for(auto proto : protos) { for(auto proto : protos) {
auto plen = strlen(proto); auto plen = strlen(proto);
if(ptr + plen + 1 > end) {
LOG(FATAL) << "Too long alpn list";
DIE();
}
*ptr = plen; *ptr = plen;
memcpy(ptr+1, proto, *ptr); memcpy(ptr + 1, proto, plen);
ptr += *ptr+1; ptr += plen + 1;
listlen += 1 + plen;
} }
return listlen; return std::vector<unsigned char>(out, ptr);
} }
} // namespace
namespace { namespace {
int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data)
@ -361,11 +361,7 @@ SSL_CTX* create_ssl_context(const char *private_key_file,
SSL_CTX_set_info_callback(ssl_ctx, info_callback); SSL_CTX_set_info_callback(ssl_ctx, info_callback);
// NPN advertisement // NPN advertisement
auto proto_list_len = set_npn_prefs(proto_list, get_config()->npn_list); SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, nullptr);
next_proto.first = proto_list;
next_proto.second = proto_list_len;
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, &next_proto);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L #if OPENSSL_VERSION_NUMBER >= 0x10002000L
// ALPN selection callback // ALPN selection callback
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, nullptr); SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, nullptr);
@ -456,12 +452,15 @@ SSL_CTX* create_ssl_client_context()
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, nullptr); SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, nullptr);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L #if OPENSSL_VERSION_NUMBER >= 0x10002000L
// ALPN advertisement // ALPN advertisement; We only advertise HTTP/2
auto proto_list_len = set_npn_prefs(proto_list, get_config()->npn_list); unsigned char proto_list[256];
next_proto.first = proto_list; proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
next_proto.second = proto_list_len; memcpy(proto_list + 1, NGHTTP2_PROTO_VERSION_ID,
SSL_CTX_set_alpn_protos(ssl_ctx, proto_list, proto_list[0] + 1); NGHTTP2_PROTO_VERSION_ID_LEN);
auto proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
SSL_CTX_set_alpn_protos(ssl_ctx, proto_list, proto_list_len);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
return ssl_ctx; return ssl_ctx;

View File

@ -136,6 +136,8 @@ bool check_http2_requirement(SSL *ssl);
// passed to SSL_CTX_set_options(). // passed to SSL_CTX_set_options().
long int create_tls_proto_mask(const std::vector<char*>& tls_proto_list); long int create_tls_proto_mask(const std::vector<char*>& tls_proto_list);
std::vector<unsigned char> set_alpn_prefs(const std::vector<char*>& protos);
} // namespace ssl } // namespace ssl
} // namespace shrpx } // namespace shrpx