Merge branch 'nghttpx-certs-per-sigalg'
This commit is contained in:
commit
a231874e1e
|
@ -72,8 +72,8 @@ int main(int argc, char *argv[]) {
|
||||||
// add the tests to the suite
|
// add the tests to the suite
|
||||||
if (!CU_add_test(pSuite, "ssl_create_lookup_tree",
|
if (!CU_add_test(pSuite, "ssl_create_lookup_tree",
|
||||||
shrpx::test_shrpx_ssl_create_lookup_tree) ||
|
shrpx::test_shrpx_ssl_create_lookup_tree) ||
|
||||||
!CU_add_test(pSuite, "ssl_cert_lookup_tree_add_cert_from_x509",
|
!CU_add_test(pSuite, "ssl_cert_lookup_tree_add_ssl_ctx",
|
||||||
shrpx::test_shrpx_ssl_cert_lookup_tree_add_cert_from_x509) ||
|
shrpx::test_shrpx_ssl_cert_lookup_tree_add_ssl_ctx) ||
|
||||||
!CU_add_test(pSuite, "ssl_tls_hostname_match",
|
!CU_add_test(pSuite, "ssl_tls_hostname_match",
|
||||||
shrpx::test_shrpx_ssl_tls_hostname_match) ||
|
shrpx::test_shrpx_ssl_tls_hostname_match) ||
|
||||||
!CU_add_test(pSuite, "http2_add_header", shrpx::test_http2_add_header) ||
|
!CU_add_test(pSuite, "http2_add_header", shrpx::test_http2_add_header) ||
|
||||||
|
|
11
src/shrpx.cc
11
src/shrpx.cc
|
@ -1943,9 +1943,14 @@ SSL/TLS:
|
||||||
--subcert=<KEYPATH>:<CERTPATH>[[;<PARAM>]...]
|
--subcert=<KEYPATH>:<CERTPATH>[[;<PARAM>]...]
|
||||||
Specify additional certificate and private key file.
|
Specify additional certificate and private key file.
|
||||||
nghttpx will choose certificates based on the hostname
|
nghttpx will choose certificates based on the hostname
|
||||||
indicated by client using TLS SNI extension. This
|
indicated by client using TLS SNI extension. If nghttpx
|
||||||
option can be used multiple times. To make OCSP
|
is built with OpenSSL >= 1.0.2, signature algorithms
|
||||||
stapling work, <CERTPATH> must be absolute path.
|
(e.g., ECDSA+SHA256, RSA+SHA256) presented by client are
|
||||||
|
also taken into consideration. This allows nghttpx to
|
||||||
|
send ECDSA certificate to modern clients, while sending
|
||||||
|
RSA based certificate to older clients. This option can
|
||||||
|
be used multiple times. To make OCSP stapling work,
|
||||||
|
<CERTPATH> must be absolute path.
|
||||||
|
|
||||||
Additional parameter can be specified in <PARAM>. The
|
Additional parameter can be specified in <PARAM>. The
|
||||||
available <PARAM> is "sct-dir=<DIR>".
|
available <PARAM> is "sct-dir=<DIR>".
|
||||||
|
|
|
@ -199,12 +199,13 @@ void ConnectionHandler::worker_replace_downstream(
|
||||||
|
|
||||||
int ConnectionHandler::create_single_worker() {
|
int ConnectionHandler::create_single_worker() {
|
||||||
cert_tree_ = ssl::create_cert_lookup_tree();
|
cert_tree_ = ssl::create_cert_lookup_tree();
|
||||||
auto sv_ssl_ctx = ssl::setup_server_ssl_context(all_ssl_ctx_, cert_tree_.get()
|
auto sv_ssl_ctx = ssl::setup_server_ssl_context(
|
||||||
|
all_ssl_ctx_, indexed_ssl_ctx_, cert_tree_.get()
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
,
|
,
|
||||||
nb_.get()
|
nb_.get()
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
);
|
);
|
||||||
auto cl_ssl_ctx = ssl::setup_downstream_client_ssl_context(
|
auto cl_ssl_ctx = ssl::setup_downstream_client_ssl_context(
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
nb_.get()
|
nb_.get()
|
||||||
|
@ -247,12 +248,13 @@ int ConnectionHandler::create_worker_thread(size_t num) {
|
||||||
assert(workers_.size() == 0);
|
assert(workers_.size() == 0);
|
||||||
|
|
||||||
cert_tree_ = ssl::create_cert_lookup_tree();
|
cert_tree_ = ssl::create_cert_lookup_tree();
|
||||||
auto sv_ssl_ctx = ssl::setup_server_ssl_context(all_ssl_ctx_, cert_tree_.get()
|
auto sv_ssl_ctx = ssl::setup_server_ssl_context(
|
||||||
|
all_ssl_ctx_, indexed_ssl_ctx_, cert_tree_.get()
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
,
|
,
|
||||||
nb_.get()
|
nb_.get()
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
);
|
);
|
||||||
auto cl_ssl_ctx = ssl::setup_downstream_client_ssl_context(
|
auto cl_ssl_ctx = ssl::setup_downstream_client_ssl_context(
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
nb_.get()
|
nb_.get()
|
||||||
|
@ -841,4 +843,9 @@ SSL_CTX *ConnectionHandler::get_ssl_ctx(size_t idx) const {
|
||||||
return all_ssl_ctx_[idx];
|
return all_ssl_ctx_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<SSL_CTX *> &
|
||||||
|
ConnectionHandler::get_indexed_ssl_ctx(size_t idx) const {
|
||||||
|
return indexed_ssl_ctx_[idx];
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -156,6 +156,8 @@ public:
|
||||||
// array bound checking.
|
// array bound checking.
|
||||||
SSL_CTX *get_ssl_ctx(size_t idx) const;
|
SSL_CTX *get_ssl_ctx(size_t idx) const;
|
||||||
|
|
||||||
|
const std::vector<SSL_CTX *> &get_indexed_ssl_ctx(size_t idx) const;
|
||||||
|
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
void set_neverbleed(std::unique_ptr<neverbleed_t> nb);
|
void set_neverbleed(std::unique_ptr<neverbleed_t> nb);
|
||||||
neverbleed_t *get_neverbleed() const;
|
neverbleed_t *get_neverbleed() const;
|
||||||
|
@ -175,6 +177,12 @@ public:
|
||||||
private:
|
private:
|
||||||
// Stores all SSL_CTX objects.
|
// Stores all SSL_CTX objects.
|
||||||
std::vector<SSL_CTX *> all_ssl_ctx_;
|
std::vector<SSL_CTX *> all_ssl_ctx_;
|
||||||
|
// Stores all SSL_CTX objects in a way that its index is stored in
|
||||||
|
// cert_tree. The SSL_CTXs stored in the same index share the same
|
||||||
|
// hostname, but could have different signature algorithm. The
|
||||||
|
// selection among them are performed by hostname presented by SNI,
|
||||||
|
// and signature algorithm presented by client.
|
||||||
|
std::vector<std::vector<SSL_CTX *>> indexed_ssl_ctx_;
|
||||||
OCSPUpdateContext ocsp_;
|
OCSPUpdateContext ocsp_;
|
||||||
std::mt19937 gen_;
|
std::mt19937 gen_;
|
||||||
// ev_loop for each worker
|
// ev_loop for each worker
|
||||||
|
|
|
@ -69,7 +69,7 @@ void Router::add_node(RNode *node, const char *pattern, size_t patlen,
|
||||||
add_next_node(node, std::move(new_node));
|
add_next_node(node, std::move(new_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Router::add_route(const StringRef &pattern, size_t index) {
|
size_t Router::add_route(const StringRef &pattern, size_t index) {
|
||||||
auto node = &root_;
|
auto node = &root_;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ bool Router::add_route(const StringRef &pattern, size_t index) {
|
||||||
auto next_node = find_next_node(node, pattern[i]);
|
auto next_node = find_next_node(node, pattern[i]);
|
||||||
if (next_node == nullptr) {
|
if (next_node == nullptr) {
|
||||||
add_node(node, pattern.c_str() + i, pattern.size() - i, index);
|
add_node(node, pattern.c_str() + i, pattern.size() - i, index);
|
||||||
return true;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = next_node;
|
node = next_node;
|
||||||
|
@ -93,11 +93,11 @@ bool Router::add_route(const StringRef &pattern, size_t index) {
|
||||||
if (slen == node->len) {
|
if (slen == node->len) {
|
||||||
// Complete match
|
// Complete match
|
||||||
if (node->index != -1) {
|
if (node->index != -1) {
|
||||||
// Don't allow duplicate
|
// Return the existing index for duplicates.
|
||||||
return false;
|
return node->index;
|
||||||
}
|
}
|
||||||
node->index = index;
|
node->index = index;
|
||||||
return true;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slen > node->len) {
|
if (slen > node->len) {
|
||||||
|
@ -122,7 +122,7 @@ bool Router::add_route(const StringRef &pattern, size_t index) {
|
||||||
|
|
||||||
if (slen == j) {
|
if (slen == j) {
|
||||||
node->index = index;
|
node->index = index;
|
||||||
return true;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ bool Router::add_route(const StringRef &pattern, size_t index) {
|
||||||
assert(pattern.size() > i);
|
assert(pattern.size() > i);
|
||||||
add_node(node, pattern.c_str() + i, pattern.size() - i, index);
|
add_node(node, pattern.c_str() + i, pattern.size() - i, index);
|
||||||
|
|
||||||
return true;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,9 @@ public:
|
||||||
Router &operator=(Router &&) = default;
|
Router &operator=(Router &&) = default;
|
||||||
Router &operator=(const Router &) = delete;
|
Router &operator=(const Router &) = delete;
|
||||||
|
|
||||||
// Adds route |pattern| with its |index|.
|
// Adds route |pattern| with its |index|. If same pattern has
|
||||||
bool add_route(const StringRef &pattern, size_t index);
|
// already been added, the existing index is returned.
|
||||||
|
size_t add_route(const StringRef &pattern, size_t index);
|
||||||
// Returns the matched index of pattern. -1 if there is no match.
|
// Returns the matched index of pattern. -1 if there is no match.
|
||||||
ssize_t match(const StringRef &host, const StringRef &path) const;
|
ssize_t match(const StringRef &host, const StringRef &path) const;
|
||||||
// Returns the matched index of pattern |s|. -1 if there is no
|
// Returns the matched index of pattern |s|. -1 if there is no
|
||||||
|
|
127
src/shrpx_ssl.cc
127
src/shrpx_ssl.cc
|
@ -183,9 +183,34 @@ int servername_callback(SSL *ssl, int *al, void *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto conn_handler = worker->get_connection_handler();
|
auto conn_handler = worker->get_connection_handler();
|
||||||
auto ssl_ctx = conn_handler->get_ssl_ctx(idx);
|
|
||||||
|
|
||||||
SSL_set_SSL_CTX(ssl, ssl_ctx);
|
const auto &ssl_ctx_list = conn_handler->get_indexed_ssl_ctx(idx);
|
||||||
|
assert(!ssl_ctx_list.empty());
|
||||||
|
|
||||||
|
#if !defined(OPENSSL_IS_BORINGSSL) && !defined(LIBRESSL_VERSION_NUMBER) && \
|
||||||
|
OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
// boringssl removed SSL_get_sigalgs.
|
||||||
|
auto num_sigalg =
|
||||||
|
SSL_get_sigalgs(ssl, 0, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
|
for (auto i = 0; i < num_sigalg; ++i) {
|
||||||
|
int sigalg;
|
||||||
|
SSL_get_sigalgs(ssl, i, nullptr, nullptr, &sigalg, nullptr, nullptr);
|
||||||
|
for (auto ssl_ctx : ssl_ctx_list) {
|
||||||
|
auto cert = SSL_CTX_get0_certificate(ssl_ctx);
|
||||||
|
// X509_get_signature_nid is available since OpenSSL 1.0.2.
|
||||||
|
auto cert_sigalg = X509_get_signature_nid(cert);
|
||||||
|
|
||||||
|
if (sigalg == cert_sigalg) {
|
||||||
|
SSL_set_SSL_CTX(ssl, ssl_ctx);
|
||||||
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // !defined(OPENSSL_IS_BORINGSSL) && !defined(LIBRESSL_VERSION_NUMBER) &&
|
||||||
|
// OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
|
||||||
|
SSL_set_SSL_CTX(ssl, ssl_ctx_list[0]);
|
||||||
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
|
@ -1239,12 +1264,12 @@ int check_cert(SSL *ssl, const DownstreamAddr *addr, const Address *raddr) {
|
||||||
|
|
||||||
CertLookupTree::CertLookupTree() {}
|
CertLookupTree::CertLookupTree() {}
|
||||||
|
|
||||||
void CertLookupTree::add_cert(const StringRef &hostname, size_t idx) {
|
ssize_t CertLookupTree::add_cert(const StringRef &hostname, size_t idx) {
|
||||||
std::array<uint8_t, NI_MAXHOST> buf;
|
std::array<uint8_t, NI_MAXHOST> buf;
|
||||||
|
|
||||||
// NI_MAXHOST includes terminal NULL byte
|
// NI_MAXHOST includes terminal NULL byte
|
||||||
if (hostname.empty() || hostname.size() + 1 > buf.size()) {
|
if (hostname.empty() || hostname.size() + 1 > buf.size()) {
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto wildcard_it = std::find(std::begin(hostname), std::end(hostname), '*');
|
auto wildcard_it = std::find(std::begin(hostname), std::end(hostname), '*');
|
||||||
|
@ -1260,8 +1285,8 @@ void CertLookupTree::add_cert(const StringRef &hostname, size_t idx) {
|
||||||
|
|
||||||
WildcardPattern *wpat;
|
WildcardPattern *wpat;
|
||||||
|
|
||||||
if (!rev_wildcard_router_.add_route(rev_suffix,
|
if (wildcard_patterns_.size() !=
|
||||||
wildcard_patterns_.size())) {
|
rev_wildcard_router_.add_route(rev_suffix, wildcard_patterns_.size())) {
|
||||||
auto wcidx = rev_wildcard_router_.match(rev_suffix);
|
auto wcidx = rev_wildcard_router_.match(rev_suffix);
|
||||||
|
|
||||||
assert(wcidx != -1);
|
assert(wcidx != -1);
|
||||||
|
@ -1277,12 +1302,18 @@ void CertLookupTree::add_cert(const StringRef &hostname, size_t idx) {
|
||||||
std::end(wildcard_prefix),
|
std::end(wildcard_prefix),
|
||||||
std::begin(buf))};
|
std::begin(buf))};
|
||||||
|
|
||||||
|
for (auto &p : wpat->rev_prefix) {
|
||||||
|
if (p.prefix == rev_prefix) {
|
||||||
|
return p.idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wpat->rev_prefix.emplace_back(rev_prefix, idx);
|
wpat->rev_prefix.emplace_back(rev_prefix, idx);
|
||||||
|
|
||||||
return;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
router_.add_route(hostname, idx);
|
return router_.add_route(hostname, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t CertLookupTree::lookup(const StringRef &hostname) {
|
ssize_t CertLookupTree::lookup(const StringRef &hostname) {
|
||||||
|
@ -1357,10 +1388,24 @@ void CertLookupTree::dump() const {
|
||||||
rev_wildcard_router_.dump();
|
rev_wildcard_router_.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
int cert_lookup_tree_add_cert_from_x509(CertLookupTree *lt, size_t idx,
|
int cert_lookup_tree_add_ssl_ctx(
|
||||||
X509 *cert) {
|
CertLookupTree *lt, std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
|
||||||
|
SSL_CTX *ssl_ctx) {
|
||||||
std::array<uint8_t, NI_MAXHOST> buf;
|
std::array<uint8_t, NI_MAXHOST> buf;
|
||||||
|
|
||||||
|
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
auto cert = SSL_CTX_get0_certificate(ssl_ctx);
|
||||||
|
#else // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER <
|
||||||
|
// 0x10002000L
|
||||||
|
auto tls_ctx_data =
|
||||||
|
static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
|
||||||
|
auto cert = load_certificate(tls_ctx_data->cert_file);
|
||||||
|
auto cert_deleter = defer(X509_free, cert);
|
||||||
|
#endif // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER <
|
||||||
|
// 0x10002000L
|
||||||
|
|
||||||
|
auto idx = indexed_ssl_ctx.size();
|
||||||
|
|
||||||
auto altnames = static_cast<GENERAL_NAMES *>(
|
auto altnames = static_cast<GENERAL_NAMES *>(
|
||||||
X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
|
X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
|
||||||
if (altnames) {
|
if (altnames) {
|
||||||
|
@ -1403,7 +1448,17 @@ int cert_lookup_tree_add_cert_from_x509(CertLookupTree *lt, size_t idx,
|
||||||
auto end_buf = std::copy_n(name, len, std::begin(buf));
|
auto end_buf = std::copy_n(name, len, std::begin(buf));
|
||||||
util::inp_strlower(std::begin(buf), end_buf);
|
util::inp_strlower(std::begin(buf), end_buf);
|
||||||
|
|
||||||
lt->add_cert(StringRef{std::begin(buf), end_buf}, idx);
|
auto nidx = lt->add_cert(StringRef{std::begin(buf), end_buf}, idx);
|
||||||
|
if (nidx == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
idx = nidx;
|
||||||
|
if (idx < indexed_ssl_ctx.size()) {
|
||||||
|
indexed_ssl_ctx[idx].push_back(ssl_ctx);
|
||||||
|
} else {
|
||||||
|
assert(idx == indexed_ssl_ctx.size());
|
||||||
|
indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't bother CN if we have dNSName.
|
// Don't bother CN if we have dNSName.
|
||||||
|
@ -1433,7 +1488,17 @@ int cert_lookup_tree_add_cert_from_x509(CertLookupTree *lt, size_t idx,
|
||||||
|
|
||||||
util::inp_strlower(std::begin(buf), end_buf);
|
util::inp_strlower(std::begin(buf), end_buf);
|
||||||
|
|
||||||
lt->add_cert(StringRef{std::begin(buf), end_buf}, idx);
|
auto nidx = lt->add_cert(StringRef{std::begin(buf), end_buf}, idx);
|
||||||
|
if (nidx == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
idx = nidx;
|
||||||
|
if (idx < indexed_ssl_ctx.size()) {
|
||||||
|
indexed_ssl_ctx[idx].push_back(ssl_ctx);
|
||||||
|
} else {
|
||||||
|
assert(idx == indexed_ssl_ctx.size());
|
||||||
|
indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx});
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1474,13 +1539,15 @@ X509 *load_certificate(const char *filename) {
|
||||||
return cert;
|
return cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
SSL_CTX *
|
||||||
CertLookupTree *cert_tree
|
setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
|
std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
|
||||||
|
CertLookupTree *cert_tree
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
,
|
,
|
||||||
neverbleed_t *nb
|
neverbleed_t *nb
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
) {
|
) {
|
||||||
if (!upstream_tls_enabled()) {
|
if (!upstream_tls_enabled()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1508,17 +1575,8 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
if (ssl::cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx, ssl_ctx) ==
|
||||||
auto cert = SSL_CTX_get0_certificate(ssl_ctx);
|
-1) {
|
||||||
#else // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER <
|
|
||||||
// 0x10002000L
|
|
||||||
auto cert = load_certificate(tlsconf.cert_file.c_str());
|
|
||||||
auto cert_deleter = defer(X509_free, cert);
|
|
||||||
#endif // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER <
|
|
||||||
// 0x10002000L
|
|
||||||
|
|
||||||
if (ssl::cert_lookup_tree_add_cert_from_x509(
|
|
||||||
cert_tree, all_ssl_ctx.size() - 1, cert) == -1) {
|
|
||||||
LOG(FATAL) << "Failed to add default certificate.";
|
LOG(FATAL) << "Failed to add default certificate.";
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
@ -1533,17 +1591,8 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
);
|
);
|
||||||
all_ssl_ctx.push_back(ssl_ctx);
|
all_ssl_ctx.push_back(ssl_ctx);
|
||||||
|
|
||||||
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
if (ssl::cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx,
|
||||||
auto cert = SSL_CTX_get0_certificate(ssl_ctx);
|
ssl_ctx) == -1) {
|
||||||
#else // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER <
|
|
||||||
// 0x10002000L
|
|
||||||
auto cert = load_certificate(c.cert_file.c_str());
|
|
||||||
auto cert_deleter = defer(X509_free, cert);
|
|
||||||
#endif // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER <
|
|
||||||
// 0x10002000L
|
|
||||||
|
|
||||||
if (ssl::cert_lookup_tree_add_cert_from_x509(
|
|
||||||
cert_tree, all_ssl_ctx.size() - 1, cert) == -1) {
|
|
||||||
LOG(FATAL) << "Failed to add sub certificate.";
|
LOG(FATAL) << "Failed to add sub certificate.";
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,13 +136,20 @@ public:
|
||||||
// |index| is returned. We support wildcard pattern. The left most
|
// |index| is returned. We support wildcard pattern. The left most
|
||||||
// '*' is considered as wildcard character, and it must match at
|
// '*' is considered as wildcard character, and it must match at
|
||||||
// least one character. If the same pattern has been already added,
|
// least one character. If the same pattern has been already added,
|
||||||
// this function is noop.
|
// this function does not alter the tree, and returns the existing
|
||||||
|
// matching index.
|
||||||
//
|
//
|
||||||
// The caller should lower-case |hostname| since this function does
|
// The caller should lower-case |hostname| since this function does
|
||||||
// do that, and lookup function performs case-sensitive match.
|
// do that, and lookup function performs case-sensitive match.
|
||||||
//
|
//
|
||||||
// TODO Treat wildcard pattern described as RFC 6125.
|
// TODO Treat wildcard pattern described as RFC 6125.
|
||||||
void add_cert(const StringRef &hostname, size_t index);
|
//
|
||||||
|
// This function returns the index. It returns -1 if it fails
|
||||||
|
// (e.g., hostname is too long). If the returned index equals to
|
||||||
|
// |index|, then hostname is added to the tree with the value
|
||||||
|
// |index|. If it is not -1, and does not equal to |index|, same
|
||||||
|
// hostname has already been added to the tree.
|
||||||
|
ssize_t add_cert(const StringRef &hostname, size_t index);
|
||||||
|
|
||||||
// Looks up index using the given |hostname|. The exact match takes
|
// Looks up index using the given |hostname|. The exact match takes
|
||||||
// precedence over wildcard match. For wildcard match, longest
|
// precedence over wildcard match. For wildcard match, longest
|
||||||
|
@ -166,12 +173,14 @@ private:
|
||||||
std::vector<WildcardPattern> wildcard_patterns_;
|
std::vector<WildcardPattern> wildcard_patterns_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Adds hostnames in |cert| to lookup tree |lt|. The subjectAltNames
|
// Adds hostnames in certificate in |ssl_ctx| to lookup tree |lt|.
|
||||||
// and commonName are considered as eligible hostname. If there is at
|
// The subjectAltNames and commonName are considered as eligible
|
||||||
// least one dNSName in subjectAltNames, commonName is not considered.
|
// hostname. If there is at least one dNSName in subjectAltNames,
|
||||||
// This function returns 0 if it succeeds, or -1.
|
// commonName is not considered. |ssl_ctx| is also added to
|
||||||
int cert_lookup_tree_add_cert_from_x509(CertLookupTree *lt, size_t idx,
|
// |indexed_ssl_ctx|. This function returns 0 if it succeeds, or -1.
|
||||||
X509 *cert);
|
int cert_lookup_tree_add_ssl_ctx(
|
||||||
|
CertLookupTree *lt, std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
|
||||||
|
SSL_CTX *ssl_ctx);
|
||||||
|
|
||||||
// Returns true if |proto| is included in the
|
// Returns true if |proto| is included in the
|
||||||
// protocol list |protos|.
|
// protocol list |protos|.
|
||||||
|
@ -194,14 +203,18 @@ int set_alpn_prefs(std::vector<unsigned char> &out,
|
||||||
// construct default SSL_CTX. If subcerts are available
|
// construct default SSL_CTX. If subcerts are available
|
||||||
// (get_config()->subcerts), caller should provide CertLookupTree
|
// (get_config()->subcerts), caller should provide CertLookupTree
|
||||||
// object as |cert_tree| parameter, otherwise SNI does not work. All
|
// object as |cert_tree| parameter, otherwise SNI does not work. All
|
||||||
// the created SSL_CTX is stored into |all_ssl_ctx|.
|
// the created SSL_CTX is stored into |all_ssl_ctx|. They are also
|
||||||
SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
// added to |indexed_ssl_ctx|. |cert_tree| uses its index to
|
||||||
CertLookupTree *cert_tree
|
// associate hostname to the SSL_CTX.
|
||||||
|
SSL_CTX *
|
||||||
|
setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
|
std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
|
||||||
|
CertLookupTree *cert_tree
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
,
|
,
|
||||||
neverbleed_t *nb
|
neverbleed_t *nb
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
);
|
);
|
||||||
|
|
||||||
// Setups client side SSL_CTX.
|
// Setups client side SSL_CTX.
|
||||||
SSL_CTX *setup_downstream_client_ssl_context(
|
SSL_CTX *setup_downstream_client_ssl_context(
|
||||||
|
|
|
@ -115,24 +115,39 @@ void test_shrpx_ssl_create_lookup_tree(void) {
|
||||||
// -config=ca-config.json -profile=server test.example.com.csr |
|
// -config=ca-config.json -profile=server test.example.com.csr |
|
||||||
// cfssljson -bare test.example.com
|
// cfssljson -bare test.example.com
|
||||||
//
|
//
|
||||||
void test_shrpx_ssl_cert_lookup_tree_add_cert_from_x509(void) {
|
void test_shrpx_ssl_cert_lookup_tree_add_ssl_ctx(void) {
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
constexpr char nghttp2_certfile[] = NGHTTP2_SRC_DIR "/test.nghttp2.org.pem";
|
constexpr char nghttp2_certfile[] = NGHTTP2_SRC_DIR "/test.nghttp2.org.pem";
|
||||||
auto nghttp2_cert = ssl::load_certificate(nghttp2_certfile);
|
auto nghttp2_ssl_ctx = SSL_CTX_new(SSLv23_server_method());
|
||||||
auto nghttp2_cert_deleter = defer(X509_free, nghttp2_cert);
|
auto nghttp2_ssl_ctx_del = defer(SSL_CTX_free, nghttp2_ssl_ctx);
|
||||||
|
auto nghttp2_tls_ctx_data = make_unique<ssl::TLSContextData>();
|
||||||
|
nghttp2_tls_ctx_data->cert_file = nghttp2_certfile;
|
||||||
|
SSL_CTX_set_app_data(nghttp2_ssl_ctx, nghttp2_tls_ctx_data.get());
|
||||||
|
rv = SSL_CTX_use_certificate_chain_file(nghttp2_ssl_ctx, nghttp2_certfile);
|
||||||
|
|
||||||
|
CU_ASSERT(1 == rv);
|
||||||
|
|
||||||
constexpr char examples_certfile[] = NGHTTP2_SRC_DIR "/test.example.com.pem";
|
constexpr char examples_certfile[] = NGHTTP2_SRC_DIR "/test.example.com.pem";
|
||||||
auto examples_cert = ssl::load_certificate(examples_certfile);
|
auto examples_ssl_ctx = SSL_CTX_new(SSLv23_server_method());
|
||||||
auto examples_cert_deleter = defer(X509_free, examples_cert);
|
auto examples_ssl_ctx_del = defer(SSL_CTX_free, examples_ssl_ctx);
|
||||||
|
auto examples_tls_ctx_data = make_unique<ssl::TLSContextData>();
|
||||||
|
examples_tls_ctx_data->cert_file = examples_certfile;
|
||||||
|
SSL_CTX_set_app_data(examples_ssl_ctx, examples_tls_ctx_data.get());
|
||||||
|
rv = SSL_CTX_use_certificate_chain_file(examples_ssl_ctx, examples_certfile);
|
||||||
|
|
||||||
|
CU_ASSERT(1 == rv);
|
||||||
|
|
||||||
ssl::CertLookupTree tree;
|
ssl::CertLookupTree tree;
|
||||||
|
std::vector<std::vector<SSL_CTX *>> indexed_ssl_ctx;
|
||||||
|
|
||||||
rv = ssl::cert_lookup_tree_add_cert_from_x509(&tree, 0, nghttp2_cert);
|
rv = ssl::cert_lookup_tree_add_ssl_ctx(&tree, indexed_ssl_ctx,
|
||||||
|
nghttp2_ssl_ctx);
|
||||||
|
|
||||||
CU_ASSERT(0 == rv);
|
CU_ASSERT(0 == rv);
|
||||||
|
|
||||||
rv = ssl::cert_lookup_tree_add_cert_from_x509(&tree, 1, examples_cert);
|
rv = ssl::cert_lookup_tree_add_ssl_ctx(&tree, indexed_ssl_ctx,
|
||||||
|
examples_ssl_ctx);
|
||||||
|
|
||||||
CU_ASSERT(0 == rv);
|
CU_ASSERT(0 == rv);
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
void test_shrpx_ssl_create_lookup_tree(void);
|
void test_shrpx_ssl_create_lookup_tree(void);
|
||||||
void test_shrpx_ssl_cert_lookup_tree_add_cert_from_x509(void);
|
void test_shrpx_ssl_cert_lookup_tree_add_ssl_ctx(void);
|
||||||
void test_shrpx_ssl_tls_hostname_match(void);
|
void test_shrpx_ssl_tls_hostname_match(void);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
Loading…
Reference in New Issue