12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2012 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#include "shrpx_tls.h" 262c593315Sopenharmony_ci 272c593315Sopenharmony_ci#ifdef HAVE_SYS_SOCKET_H 282c593315Sopenharmony_ci# include <sys/socket.h> 292c593315Sopenharmony_ci#endif // HAVE_SYS_SOCKET_H 302c593315Sopenharmony_ci#ifdef HAVE_NETDB_H 312c593315Sopenharmony_ci# include <netdb.h> 322c593315Sopenharmony_ci#endif // HAVE_NETDB_H 332c593315Sopenharmony_ci#include <netinet/tcp.h> 342c593315Sopenharmony_ci#include <pthread.h> 352c593315Sopenharmony_ci#include <sys/types.h> 362c593315Sopenharmony_ci 372c593315Sopenharmony_ci#include <vector> 382c593315Sopenharmony_ci#include <string> 392c593315Sopenharmony_ci#include <iomanip> 402c593315Sopenharmony_ci 412c593315Sopenharmony_ci#include <iostream> 422c593315Sopenharmony_ci 432c593315Sopenharmony_ci#include "ssl_compat.h" 442c593315Sopenharmony_ci 452c593315Sopenharmony_ci#include <openssl/crypto.h> 462c593315Sopenharmony_ci#include <openssl/x509.h> 472c593315Sopenharmony_ci#include <openssl/x509v3.h> 482c593315Sopenharmony_ci#include <openssl/rand.h> 492c593315Sopenharmony_ci#include <openssl/dh.h> 502c593315Sopenharmony_ci#ifndef OPENSSL_NO_OCSP 512c593315Sopenharmony_ci# include <openssl/ocsp.h> 522c593315Sopenharmony_ci#endif // OPENSSL_NO_OCSP 532c593315Sopenharmony_ci#if OPENSSL_3_0_0_API 542c593315Sopenharmony_ci# include <openssl/params.h> 552c593315Sopenharmony_ci# include <openssl/core_names.h> 562c593315Sopenharmony_ci# include <openssl/decoder.h> 572c593315Sopenharmony_ci#endif // OPENSSL_3_0_0_API 582c593315Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL 592c593315Sopenharmony_ci# include <openssl/hmac.h> 602c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL 612c593315Sopenharmony_ci 622c593315Sopenharmony_ci#include <nghttp2/nghttp2.h> 632c593315Sopenharmony_ci 642c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 652c593315Sopenharmony_ci# include <ngtcp2/ngtcp2.h> 662c593315Sopenharmony_ci# include <ngtcp2/ngtcp2_crypto.h> 672c593315Sopenharmony_ci# ifdef HAVE_LIBNGTCP2_CRYPTO_QUICTLS 682c593315Sopenharmony_ci# include <ngtcp2/ngtcp2_crypto_quictls.h> 692c593315Sopenharmony_ci# endif // HAVE_LIBNGTCP2_CRYPTO_QUICTLS 702c593315Sopenharmony_ci# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL 712c593315Sopenharmony_ci# include <ngtcp2/ngtcp2_crypto_boringssl.h> 722c593315Sopenharmony_ci# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL 732c593315Sopenharmony_ci#endif // ENABLE_HTTP3 742c593315Sopenharmony_ci 752c593315Sopenharmony_ci#include "shrpx_log.h" 762c593315Sopenharmony_ci#include "shrpx_client_handler.h" 772c593315Sopenharmony_ci#include "shrpx_config.h" 782c593315Sopenharmony_ci#include "shrpx_worker.h" 792c593315Sopenharmony_ci#include "shrpx_downstream_connection_pool.h" 802c593315Sopenharmony_ci#include "shrpx_http2_session.h" 812c593315Sopenharmony_ci#include "shrpx_memcached_request.h" 822c593315Sopenharmony_ci#include "shrpx_memcached_dispatcher.h" 832c593315Sopenharmony_ci#include "shrpx_connection_handler.h" 842c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 852c593315Sopenharmony_ci# include "shrpx_http3_upstream.h" 862c593315Sopenharmony_ci#endif // ENABLE_HTTP3 872c593315Sopenharmony_ci#include "util.h" 882c593315Sopenharmony_ci#include "tls.h" 892c593315Sopenharmony_ci#include "template.h" 902c593315Sopenharmony_ci#include "timegm.h" 912c593315Sopenharmony_ci 922c593315Sopenharmony_ciusing namespace nghttp2; 932c593315Sopenharmony_ciusing namespace std::chrono_literals; 942c593315Sopenharmony_ci 952c593315Sopenharmony_cinamespace shrpx { 962c593315Sopenharmony_ci 972c593315Sopenharmony_cinamespace tls { 982c593315Sopenharmony_ci 992c593315Sopenharmony_ci#if !OPENSSL_1_1_API 1002c593315Sopenharmony_cinamespace { 1012c593315Sopenharmony_ciconst unsigned char *ASN1_STRING_get0_data(ASN1_STRING *x) { 1022c593315Sopenharmony_ci return ASN1_STRING_data(x); 1032c593315Sopenharmony_ci} 1042c593315Sopenharmony_ci} // namespace 1052c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API 1062c593315Sopenharmony_ci 1072c593315Sopenharmony_ci#ifndef OPENSSL_NO_NEXTPROTONEG 1082c593315Sopenharmony_cinamespace { 1092c593315Sopenharmony_ciint next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len, 1102c593315Sopenharmony_ci void *arg) { 1112c593315Sopenharmony_ci auto &prefs = get_config()->tls.alpn_prefs; 1122c593315Sopenharmony_ci *data = prefs.data(); 1132c593315Sopenharmony_ci *len = prefs.size(); 1142c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 1152c593315Sopenharmony_ci} 1162c593315Sopenharmony_ci} // namespace 1172c593315Sopenharmony_ci#endif // !OPENSSL_NO_NEXTPROTONEG 1182c593315Sopenharmony_ci 1192c593315Sopenharmony_cinamespace { 1202c593315Sopenharmony_ciint verify_callback(int preverify_ok, X509_STORE_CTX *ctx) { 1212c593315Sopenharmony_ci if (!preverify_ok) { 1222c593315Sopenharmony_ci int err = X509_STORE_CTX_get_error(ctx); 1232c593315Sopenharmony_ci int depth = X509_STORE_CTX_get_error_depth(ctx); 1242c593315Sopenharmony_ci if (err == X509_V_ERR_CERT_HAS_EXPIRED && depth == 0 && 1252c593315Sopenharmony_ci get_config()->tls.client_verify.tolerate_expired) { 1262c593315Sopenharmony_ci LOG(INFO) << "The client certificate has expired, but is accepted by " 1272c593315Sopenharmony_ci "configuration"; 1282c593315Sopenharmony_ci return 1; 1292c593315Sopenharmony_ci } 1302c593315Sopenharmony_ci LOG(ERROR) << "client certificate verify error:num=" << err << ":" 1312c593315Sopenharmony_ci << X509_verify_cert_error_string(err) << ":depth=" << depth; 1322c593315Sopenharmony_ci } 1332c593315Sopenharmony_ci return preverify_ok; 1342c593315Sopenharmony_ci} 1352c593315Sopenharmony_ci} // namespace 1362c593315Sopenharmony_ci 1372c593315Sopenharmony_ciint set_alpn_prefs(std::vector<unsigned char> &out, 1382c593315Sopenharmony_ci const std::vector<StringRef> &protos) { 1392c593315Sopenharmony_ci size_t len = 0; 1402c593315Sopenharmony_ci 1412c593315Sopenharmony_ci for (const auto &proto : protos) { 1422c593315Sopenharmony_ci if (proto.size() > 255) { 1432c593315Sopenharmony_ci LOG(FATAL) << "Too long ALPN identifier: " << proto.size(); 1442c593315Sopenharmony_ci return -1; 1452c593315Sopenharmony_ci } 1462c593315Sopenharmony_ci 1472c593315Sopenharmony_ci len += 1 + proto.size(); 1482c593315Sopenharmony_ci } 1492c593315Sopenharmony_ci 1502c593315Sopenharmony_ci if (len > (1 << 16) - 1) { 1512c593315Sopenharmony_ci LOG(FATAL) << "Too long ALPN identifier list: " << len; 1522c593315Sopenharmony_ci return -1; 1532c593315Sopenharmony_ci } 1542c593315Sopenharmony_ci 1552c593315Sopenharmony_ci out.resize(len); 1562c593315Sopenharmony_ci auto ptr = out.data(); 1572c593315Sopenharmony_ci 1582c593315Sopenharmony_ci for (const auto &proto : protos) { 1592c593315Sopenharmony_ci *ptr++ = proto.size(); 1602c593315Sopenharmony_ci ptr = std::copy(std::begin(proto), std::end(proto), ptr); 1612c593315Sopenharmony_ci } 1622c593315Sopenharmony_ci 1632c593315Sopenharmony_ci return 0; 1642c593315Sopenharmony_ci} 1652c593315Sopenharmony_ci 1662c593315Sopenharmony_cinamespace { 1672c593315Sopenharmony_ciint ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) { 1682c593315Sopenharmony_ci auto config = static_cast<Config *>(user_data); 1692c593315Sopenharmony_ci auto len = static_cast<int>(config->tls.private_key_passwd.size()); 1702c593315Sopenharmony_ci if (size < len + 1) { 1712c593315Sopenharmony_ci LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size; 1722c593315Sopenharmony_ci return 0; 1732c593315Sopenharmony_ci } 1742c593315Sopenharmony_ci // Copy string including last '\0'. 1752c593315Sopenharmony_ci memcpy(buf, config->tls.private_key_passwd.c_str(), len + 1); 1762c593315Sopenharmony_ci return len; 1772c593315Sopenharmony_ci} 1782c593315Sopenharmony_ci} // namespace 1792c593315Sopenharmony_ci 1802c593315Sopenharmony_cinamespace { 1812c593315Sopenharmony_ci// *al is set to SSL_AD_UNRECOGNIZED_NAME by openssl, so we don't have 1822c593315Sopenharmony_ci// to set it explicitly. 1832c593315Sopenharmony_ciint servername_callback(SSL *ssl, int *al, void *arg) { 1842c593315Sopenharmony_ci auto conn = static_cast<Connection *>(SSL_get_app_data(ssl)); 1852c593315Sopenharmony_ci auto handler = static_cast<ClientHandler *>(conn->data); 1862c593315Sopenharmony_ci auto worker = handler->get_worker(); 1872c593315Sopenharmony_ci 1882c593315Sopenharmony_ci auto rawhost = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); 1892c593315Sopenharmony_ci if (rawhost == nullptr) { 1902c593315Sopenharmony_ci return SSL_TLSEXT_ERR_NOACK; 1912c593315Sopenharmony_ci } 1922c593315Sopenharmony_ci 1932c593315Sopenharmony_ci auto len = strlen(rawhost); 1942c593315Sopenharmony_ci // NI_MAXHOST includes terminal NULL. 1952c593315Sopenharmony_ci if (len == 0 || len + 1 > NI_MAXHOST) { 1962c593315Sopenharmony_ci return SSL_TLSEXT_ERR_NOACK; 1972c593315Sopenharmony_ci } 1982c593315Sopenharmony_ci 1992c593315Sopenharmony_ci std::array<uint8_t, NI_MAXHOST> buf; 2002c593315Sopenharmony_ci 2012c593315Sopenharmony_ci auto end_buf = std::copy_n(rawhost, len, std::begin(buf)); 2022c593315Sopenharmony_ci 2032c593315Sopenharmony_ci util::inp_strlower(std::begin(buf), end_buf); 2042c593315Sopenharmony_ci 2052c593315Sopenharmony_ci auto hostname = StringRef{std::begin(buf), end_buf}; 2062c593315Sopenharmony_ci 2072c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 2082c593315Sopenharmony_ci auto cert_tree = conn->proto == Proto::HTTP3 2092c593315Sopenharmony_ci ? worker->get_quic_cert_lookup_tree() 2102c593315Sopenharmony_ci : worker->get_cert_lookup_tree(); 2112c593315Sopenharmony_ci#else // !ENABLE_HTTP3 2122c593315Sopenharmony_ci auto cert_tree = worker->get_cert_lookup_tree(); 2132c593315Sopenharmony_ci#endif // !ENABLE_HTTP3 2142c593315Sopenharmony_ci 2152c593315Sopenharmony_ci auto idx = cert_tree->lookup(hostname); 2162c593315Sopenharmony_ci if (idx == -1) { 2172c593315Sopenharmony_ci return SSL_TLSEXT_ERR_NOACK; 2182c593315Sopenharmony_ci } 2192c593315Sopenharmony_ci 2202c593315Sopenharmony_ci handler->set_tls_sni(hostname); 2212c593315Sopenharmony_ci 2222c593315Sopenharmony_ci auto conn_handler = worker->get_connection_handler(); 2232c593315Sopenharmony_ci 2242c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 2252c593315Sopenharmony_ci const auto &ssl_ctx_list = conn->proto == Proto::HTTP3 2262c593315Sopenharmony_ci ? conn_handler->get_quic_indexed_ssl_ctx(idx) 2272c593315Sopenharmony_ci : conn_handler->get_indexed_ssl_ctx(idx); 2282c593315Sopenharmony_ci#else // !ENABLE_HTTP3 2292c593315Sopenharmony_ci const auto &ssl_ctx_list = conn_handler->get_indexed_ssl_ctx(idx); 2302c593315Sopenharmony_ci#endif // !ENABLE_HTTP3 2312c593315Sopenharmony_ci 2322c593315Sopenharmony_ci assert(!ssl_ctx_list.empty()); 2332c593315Sopenharmony_ci 2342c593315Sopenharmony_ci#if !defined(OPENSSL_IS_BORINGSSL) && !LIBRESSL_IN_USE && \ 2352c593315Sopenharmony_ci OPENSSL_VERSION_NUMBER >= 0x10002000L 2362c593315Sopenharmony_ci auto num_sigalgs = 2372c593315Sopenharmony_ci SSL_get_sigalgs(ssl, 0, nullptr, nullptr, nullptr, nullptr, nullptr); 2382c593315Sopenharmony_ci 2392c593315Sopenharmony_ci for (idx = 0; idx < num_sigalgs; ++idx) { 2402c593315Sopenharmony_ci int signhash; 2412c593315Sopenharmony_ci 2422c593315Sopenharmony_ci SSL_get_sigalgs(ssl, idx, nullptr, nullptr, &signhash, nullptr, nullptr); 2432c593315Sopenharmony_ci switch (signhash) { 2442c593315Sopenharmony_ci case NID_ecdsa_with_SHA256: 2452c593315Sopenharmony_ci case NID_ecdsa_with_SHA384: 2462c593315Sopenharmony_ci case NID_ecdsa_with_SHA512: 2472c593315Sopenharmony_ci break; 2482c593315Sopenharmony_ci default: 2492c593315Sopenharmony_ci continue; 2502c593315Sopenharmony_ci } 2512c593315Sopenharmony_ci 2522c593315Sopenharmony_ci break; 2532c593315Sopenharmony_ci } 2542c593315Sopenharmony_ci 2552c593315Sopenharmony_ci if (idx == num_sigalgs) { 2562c593315Sopenharmony_ci SSL_set_SSL_CTX(ssl, ssl_ctx_list[0]); 2572c593315Sopenharmony_ci 2582c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 2592c593315Sopenharmony_ci } 2602c593315Sopenharmony_ci 2612c593315Sopenharmony_ci auto num_shared_curves = SSL_get_shared_curve(ssl, -1); 2622c593315Sopenharmony_ci 2632c593315Sopenharmony_ci for (auto i = 0; i < num_shared_curves; ++i) { 2642c593315Sopenharmony_ci auto shared_curve = SSL_get_shared_curve(ssl, i); 2652c593315Sopenharmony_ci# if OPENSSL_3_0_0_API 2662c593315Sopenharmony_ci // It looks like only short name is defined in OpenSSL. No idea 2672c593315Sopenharmony_ci // which one to use because it is unknown that which one 2682c593315Sopenharmony_ci // EVP_PKEY_get_utf8_string_param("group") returns. 2692c593315Sopenharmony_ci auto shared_curve_name = OBJ_nid2sn(shared_curve); 2702c593315Sopenharmony_ci if (shared_curve_name == nullptr) { 2712c593315Sopenharmony_ci continue; 2722c593315Sopenharmony_ci } 2732c593315Sopenharmony_ci# endif // OPENSSL_3_0_0_API 2742c593315Sopenharmony_ci 2752c593315Sopenharmony_ci for (auto ssl_ctx : ssl_ctx_list) { 2762c593315Sopenharmony_ci auto cert = SSL_CTX_get0_certificate(ssl_ctx); 2772c593315Sopenharmony_ci 2782c593315Sopenharmony_ci# if OPENSSL_1_1_API 2792c593315Sopenharmony_ci auto pubkey = X509_get0_pubkey(cert); 2802c593315Sopenharmony_ci# else // !OPENSSL_1_1_API 2812c593315Sopenharmony_ci auto pubkey = X509_get_pubkey(cert); 2822c593315Sopenharmony_ci# endif // !OPENSSL_1_1_API 2832c593315Sopenharmony_ci 2842c593315Sopenharmony_ci if (EVP_PKEY_base_id(pubkey) != EVP_PKEY_EC) { 2852c593315Sopenharmony_ci continue; 2862c593315Sopenharmony_ci } 2872c593315Sopenharmony_ci 2882c593315Sopenharmony_ci# if OPENSSL_3_0_0_API 2892c593315Sopenharmony_ci std::array<char, 64> curve_name; 2902c593315Sopenharmony_ci if (!EVP_PKEY_get_utf8_string_param(pubkey, "group", curve_name.data(), 2912c593315Sopenharmony_ci curve_name.size(), nullptr)) { 2922c593315Sopenharmony_ci continue; 2932c593315Sopenharmony_ci } 2942c593315Sopenharmony_ci 2952c593315Sopenharmony_ci if (strcmp(shared_curve_name, curve_name.data()) == 0) { 2962c593315Sopenharmony_ci SSL_set_SSL_CTX(ssl, ssl_ctx); 2972c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 2982c593315Sopenharmony_ci } 2992c593315Sopenharmony_ci# else // !OPENSSL_3_0_0_API 3002c593315Sopenharmony_ci# if OPENSSL_1_1_API 3012c593315Sopenharmony_ci auto eckey = EVP_PKEY_get0_EC_KEY(pubkey); 3022c593315Sopenharmony_ci# else // !OPENSSL_1_1_API 3032c593315Sopenharmony_ci auto eckey = EVP_PKEY_get1_EC_KEY(pubkey); 3042c593315Sopenharmony_ci# endif // !OPENSSL_1_1_API 3052c593315Sopenharmony_ci 3062c593315Sopenharmony_ci if (eckey == nullptr) { 3072c593315Sopenharmony_ci continue; 3082c593315Sopenharmony_ci } 3092c593315Sopenharmony_ci 3102c593315Sopenharmony_ci auto ecgroup = EC_KEY_get0_group(eckey); 3112c593315Sopenharmony_ci auto cert_curve = EC_GROUP_get_curve_name(ecgroup); 3122c593315Sopenharmony_ci 3132c593315Sopenharmony_ci# if !OPENSSL_1_1_API 3142c593315Sopenharmony_ci EC_KEY_free(eckey); 3152c593315Sopenharmony_ci EVP_PKEY_free(pubkey); 3162c593315Sopenharmony_ci# endif // !OPENSSL_1_1_API 3172c593315Sopenharmony_ci 3182c593315Sopenharmony_ci if (shared_curve == cert_curve) { 3192c593315Sopenharmony_ci SSL_set_SSL_CTX(ssl, ssl_ctx); 3202c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 3212c593315Sopenharmony_ci } 3222c593315Sopenharmony_ci# endif // !OPENSSL_3_0_0_API 3232c593315Sopenharmony_ci } 3242c593315Sopenharmony_ci } 3252c593315Sopenharmony_ci#endif // !defined(OPENSSL_IS_BORINGSSL) && !LIBRESSL_IN_USE && 3262c593315Sopenharmony_ci // OPENSSL_VERSION_NUMBER >= 0x10002000L 3272c593315Sopenharmony_ci 3282c593315Sopenharmony_ci SSL_set_SSL_CTX(ssl, ssl_ctx_list[0]); 3292c593315Sopenharmony_ci 3302c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 3312c593315Sopenharmony_ci} 3322c593315Sopenharmony_ci} // namespace 3332c593315Sopenharmony_ci 3342c593315Sopenharmony_ci#ifndef OPENSSL_IS_BORINGSSL 3352c593315Sopenharmony_cinamespace { 3362c593315Sopenharmony_cistd::shared_ptr<std::vector<uint8_t>> 3372c593315Sopenharmony_ciget_ocsp_data(TLSContextData *tls_ctx_data) { 3382c593315Sopenharmony_ci# ifdef HAVE_ATOMIC_STD_SHARED_PTR 3392c593315Sopenharmony_ci return std::atomic_load_explicit(&tls_ctx_data->ocsp_data, 3402c593315Sopenharmony_ci std::memory_order_acquire); 3412c593315Sopenharmony_ci# else // !HAVE_ATOMIC_STD_SHARED_PTR 3422c593315Sopenharmony_ci std::lock_guard<std::mutex> g(tls_ctx_data->mu); 3432c593315Sopenharmony_ci return tls_ctx_data->ocsp_data; 3442c593315Sopenharmony_ci# endif // !HAVE_ATOMIC_STD_SHARED_PTR 3452c593315Sopenharmony_ci} 3462c593315Sopenharmony_ci} // namespace 3472c593315Sopenharmony_ci 3482c593315Sopenharmony_cinamespace { 3492c593315Sopenharmony_ciint ocsp_resp_cb(SSL *ssl, void *arg) { 3502c593315Sopenharmony_ci auto ssl_ctx = SSL_get_SSL_CTX(ssl); 3512c593315Sopenharmony_ci auto tls_ctx_data = 3522c593315Sopenharmony_ci static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx)); 3532c593315Sopenharmony_ci 3542c593315Sopenharmony_ci auto data = get_ocsp_data(tls_ctx_data); 3552c593315Sopenharmony_ci 3562c593315Sopenharmony_ci if (!data) { 3572c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 3582c593315Sopenharmony_ci } 3592c593315Sopenharmony_ci 3602c593315Sopenharmony_ci auto buf = 3612c593315Sopenharmony_ci static_cast<uint8_t *>(CRYPTO_malloc(data->size(), __FILE__, __LINE__)); 3622c593315Sopenharmony_ci 3632c593315Sopenharmony_ci if (!buf) { 3642c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 3652c593315Sopenharmony_ci } 3662c593315Sopenharmony_ci 3672c593315Sopenharmony_ci std::copy(std::begin(*data), std::end(*data), buf); 3682c593315Sopenharmony_ci 3692c593315Sopenharmony_ci SSL_set_tlsext_status_ocsp_resp(ssl, buf, data->size()); 3702c593315Sopenharmony_ci 3712c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 3722c593315Sopenharmony_ci} 3732c593315Sopenharmony_ci} // namespace 3742c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL 3752c593315Sopenharmony_ci 3762c593315Sopenharmony_ciconstexpr auto MEMCACHED_SESSION_CACHE_KEY_PREFIX = 3772c593315Sopenharmony_ci StringRef::from_lit("nghttpx:tls-session-cache:"); 3782c593315Sopenharmony_ci 3792c593315Sopenharmony_cinamespace { 3802c593315Sopenharmony_ciint tls_session_client_new_cb(SSL *ssl, SSL_SESSION *session) { 3812c593315Sopenharmony_ci auto conn = static_cast<Connection *>(SSL_get_app_data(ssl)); 3822c593315Sopenharmony_ci if (conn->tls.client_session_cache == nullptr) { 3832c593315Sopenharmony_ci return 0; 3842c593315Sopenharmony_ci } 3852c593315Sopenharmony_ci 3862c593315Sopenharmony_ci try_cache_tls_session(conn->tls.client_session_cache, session, 3872c593315Sopenharmony_ci std::chrono::steady_clock::now()); 3882c593315Sopenharmony_ci 3892c593315Sopenharmony_ci return 0; 3902c593315Sopenharmony_ci} 3912c593315Sopenharmony_ci} // namespace 3922c593315Sopenharmony_ci 3932c593315Sopenharmony_cinamespace { 3942c593315Sopenharmony_ciint tls_session_new_cb(SSL *ssl, SSL_SESSION *session) { 3952c593315Sopenharmony_ci auto conn = static_cast<Connection *>(SSL_get_app_data(ssl)); 3962c593315Sopenharmony_ci auto handler = static_cast<ClientHandler *>(conn->data); 3972c593315Sopenharmony_ci auto worker = handler->get_worker(); 3982c593315Sopenharmony_ci auto dispatcher = worker->get_session_cache_memcached_dispatcher(); 3992c593315Sopenharmony_ci auto &balloc = handler->get_block_allocator(); 4002c593315Sopenharmony_ci 4012c593315Sopenharmony_ci#ifdef TLS1_3_VERSION 4022c593315Sopenharmony_ci if (SSL_version(ssl) == TLS1_3_VERSION) { 4032c593315Sopenharmony_ci return 0; 4042c593315Sopenharmony_ci } 4052c593315Sopenharmony_ci#endif // TLS1_3_VERSION 4062c593315Sopenharmony_ci 4072c593315Sopenharmony_ci const unsigned char *id; 4082c593315Sopenharmony_ci unsigned int idlen; 4092c593315Sopenharmony_ci 4102c593315Sopenharmony_ci id = SSL_SESSION_get_id(session, &idlen); 4112c593315Sopenharmony_ci 4122c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4132c593315Sopenharmony_ci LOG(INFO) << "Memcached: cache session, id=" << util::format_hex(id, idlen); 4142c593315Sopenharmony_ci } 4152c593315Sopenharmony_ci 4162c593315Sopenharmony_ci auto req = std::make_unique<MemcachedRequest>(); 4172c593315Sopenharmony_ci req->op = MemcachedOp::ADD; 4182c593315Sopenharmony_ci req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX.str(); 4192c593315Sopenharmony_ci req->key += 4202c593315Sopenharmony_ci util::format_hex(balloc, StringRef{id, static_cast<size_t>(idlen)}); 4212c593315Sopenharmony_ci 4222c593315Sopenharmony_ci auto sessionlen = i2d_SSL_SESSION(session, nullptr); 4232c593315Sopenharmony_ci req->value.resize(sessionlen); 4242c593315Sopenharmony_ci auto buf = &req->value[0]; 4252c593315Sopenharmony_ci i2d_SSL_SESSION(session, &buf); 4262c593315Sopenharmony_ci req->expiry = 12_h; 4272c593315Sopenharmony_ci req->cb = [](MemcachedRequest *req, MemcachedResult res) { 4282c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4292c593315Sopenharmony_ci LOG(INFO) << "Memcached: session cache done. key=" << req->key 4302c593315Sopenharmony_ci << ", status_code=" << static_cast<uint16_t>(res.status_code) 4312c593315Sopenharmony_ci << ", value=" 4322c593315Sopenharmony_ci << std::string(std::begin(res.value), std::end(res.value)); 4332c593315Sopenharmony_ci } 4342c593315Sopenharmony_ci if (res.status_code != MemcachedStatusCode::NO_ERROR) { 4352c593315Sopenharmony_ci LOG(WARN) << "Memcached: failed to cache session key=" << req->key 4362c593315Sopenharmony_ci << ", status_code=" << static_cast<uint16_t>(res.status_code) 4372c593315Sopenharmony_ci << ", value=" 4382c593315Sopenharmony_ci << std::string(std::begin(res.value), std::end(res.value)); 4392c593315Sopenharmony_ci } 4402c593315Sopenharmony_ci }; 4412c593315Sopenharmony_ci assert(!req->canceled); 4422c593315Sopenharmony_ci 4432c593315Sopenharmony_ci dispatcher->add_request(std::move(req)); 4442c593315Sopenharmony_ci 4452c593315Sopenharmony_ci return 0; 4462c593315Sopenharmony_ci} 4472c593315Sopenharmony_ci} // namespace 4482c593315Sopenharmony_ci 4492c593315Sopenharmony_cinamespace { 4502c593315Sopenharmony_ciSSL_SESSION *tls_session_get_cb(SSL *ssl, 4512c593315Sopenharmony_ci#if OPENSSL_1_1_API || LIBRESSL_2_7_API 4522c593315Sopenharmony_ci const unsigned char *id, 4532c593315Sopenharmony_ci#else // !(OPENSSL_1_1_API || LIBRESSL_2_7_API) 4542c593315Sopenharmony_ci unsigned char *id, 4552c593315Sopenharmony_ci#endif // !(OPENSSL_1_1_API || LIBRESSL_2_7_API) 4562c593315Sopenharmony_ci int idlen, int *copy) { 4572c593315Sopenharmony_ci auto conn = static_cast<Connection *>(SSL_get_app_data(ssl)); 4582c593315Sopenharmony_ci auto handler = static_cast<ClientHandler *>(conn->data); 4592c593315Sopenharmony_ci auto worker = handler->get_worker(); 4602c593315Sopenharmony_ci auto dispatcher = worker->get_session_cache_memcached_dispatcher(); 4612c593315Sopenharmony_ci auto &balloc = handler->get_block_allocator(); 4622c593315Sopenharmony_ci 4632c593315Sopenharmony_ci if (idlen == 0) { 4642c593315Sopenharmony_ci return nullptr; 4652c593315Sopenharmony_ci } 4662c593315Sopenharmony_ci 4672c593315Sopenharmony_ci if (conn->tls.cached_session) { 4682c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4692c593315Sopenharmony_ci LOG(INFO) << "Memcached: found cached session, id=" 4702c593315Sopenharmony_ci << util::format_hex(id, idlen); 4712c593315Sopenharmony_ci } 4722c593315Sopenharmony_ci 4732c593315Sopenharmony_ci // This is required, without this, memory leak occurs. 4742c593315Sopenharmony_ci *copy = 0; 4752c593315Sopenharmony_ci 4762c593315Sopenharmony_ci auto session = conn->tls.cached_session; 4772c593315Sopenharmony_ci conn->tls.cached_session = nullptr; 4782c593315Sopenharmony_ci return session; 4792c593315Sopenharmony_ci } 4802c593315Sopenharmony_ci 4812c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4822c593315Sopenharmony_ci LOG(INFO) << "Memcached: get cached session, id=" 4832c593315Sopenharmony_ci << util::format_hex(id, idlen); 4842c593315Sopenharmony_ci } 4852c593315Sopenharmony_ci 4862c593315Sopenharmony_ci auto req = std::make_unique<MemcachedRequest>(); 4872c593315Sopenharmony_ci req->op = MemcachedOp::GET; 4882c593315Sopenharmony_ci req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX.str(); 4892c593315Sopenharmony_ci req->key += 4902c593315Sopenharmony_ci util::format_hex(balloc, StringRef{id, static_cast<size_t>(idlen)}); 4912c593315Sopenharmony_ci req->cb = [conn](MemcachedRequest *, MemcachedResult res) { 4922c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4932c593315Sopenharmony_ci LOG(INFO) << "Memcached: returned status code " 4942c593315Sopenharmony_ci << static_cast<uint16_t>(res.status_code); 4952c593315Sopenharmony_ci } 4962c593315Sopenharmony_ci 4972c593315Sopenharmony_ci // We might stop reading, so start it again 4982c593315Sopenharmony_ci conn->rlimit.startw(); 4992c593315Sopenharmony_ci ev_timer_again(conn->loop, &conn->rt); 5002c593315Sopenharmony_ci 5012c593315Sopenharmony_ci conn->wlimit.startw(); 5022c593315Sopenharmony_ci ev_timer_again(conn->loop, &conn->wt); 5032c593315Sopenharmony_ci 5042c593315Sopenharmony_ci conn->tls.cached_session_lookup_req = nullptr; 5052c593315Sopenharmony_ci if (res.status_code != MemcachedStatusCode::NO_ERROR) { 5062c593315Sopenharmony_ci conn->tls.handshake_state = TLSHandshakeState::CANCEL_SESSION_CACHE; 5072c593315Sopenharmony_ci return; 5082c593315Sopenharmony_ci } 5092c593315Sopenharmony_ci 5102c593315Sopenharmony_ci const uint8_t *p = res.value.data(); 5112c593315Sopenharmony_ci 5122c593315Sopenharmony_ci auto session = d2i_SSL_SESSION(nullptr, &p, res.value.size()); 5132c593315Sopenharmony_ci if (!session) { 5142c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 5152c593315Sopenharmony_ci LOG(INFO) << "cannot materialize session"; 5162c593315Sopenharmony_ci } 5172c593315Sopenharmony_ci conn->tls.handshake_state = TLSHandshakeState::CANCEL_SESSION_CACHE; 5182c593315Sopenharmony_ci return; 5192c593315Sopenharmony_ci } 5202c593315Sopenharmony_ci 5212c593315Sopenharmony_ci conn->tls.cached_session = session; 5222c593315Sopenharmony_ci conn->tls.handshake_state = TLSHandshakeState::GOT_SESSION_CACHE; 5232c593315Sopenharmony_ci }; 5242c593315Sopenharmony_ci 5252c593315Sopenharmony_ci conn->tls.handshake_state = TLSHandshakeState::WAIT_FOR_SESSION_CACHE; 5262c593315Sopenharmony_ci conn->tls.cached_session_lookup_req = req.get(); 5272c593315Sopenharmony_ci 5282c593315Sopenharmony_ci dispatcher->add_request(std::move(req)); 5292c593315Sopenharmony_ci 5302c593315Sopenharmony_ci return nullptr; 5312c593315Sopenharmony_ci} 5322c593315Sopenharmony_ci} // namespace 5332c593315Sopenharmony_ci 5342c593315Sopenharmony_cinamespace { 5352c593315Sopenharmony_ciint ticket_key_cb(SSL *ssl, unsigned char *key_name, unsigned char *iv, 5362c593315Sopenharmony_ci EVP_CIPHER_CTX *ctx, 5372c593315Sopenharmony_ci#if OPENSSL_3_0_0_API 5382c593315Sopenharmony_ci EVP_MAC_CTX *hctx, 5392c593315Sopenharmony_ci#else // !OPENSSL_3_0_0_API 5402c593315Sopenharmony_ci HMAC_CTX *hctx, 5412c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API 5422c593315Sopenharmony_ci int enc) { 5432c593315Sopenharmony_ci auto conn = static_cast<Connection *>(SSL_get_app_data(ssl)); 5442c593315Sopenharmony_ci auto handler = static_cast<ClientHandler *>(conn->data); 5452c593315Sopenharmony_ci auto worker = handler->get_worker(); 5462c593315Sopenharmony_ci auto ticket_keys = worker->get_ticket_keys(); 5472c593315Sopenharmony_ci 5482c593315Sopenharmony_ci if (!ticket_keys) { 5492c593315Sopenharmony_ci // No ticket keys available. 5502c593315Sopenharmony_ci return -1; 5512c593315Sopenharmony_ci } 5522c593315Sopenharmony_ci 5532c593315Sopenharmony_ci auto &keys = ticket_keys->keys; 5542c593315Sopenharmony_ci assert(!keys.empty()); 5552c593315Sopenharmony_ci 5562c593315Sopenharmony_ci if (enc) { 5572c593315Sopenharmony_ci if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) == 0) { 5582c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 5592c593315Sopenharmony_ci CLOG(INFO, handler) << "session ticket key: RAND_bytes failed"; 5602c593315Sopenharmony_ci } 5612c593315Sopenharmony_ci return -1; 5622c593315Sopenharmony_ci } 5632c593315Sopenharmony_ci 5642c593315Sopenharmony_ci auto &key = keys[0]; 5652c593315Sopenharmony_ci 5662c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 5672c593315Sopenharmony_ci CLOG(INFO, handler) << "encrypt session ticket key: " 5682c593315Sopenharmony_ci << util::format_hex(key.data.name); 5692c593315Sopenharmony_ci } 5702c593315Sopenharmony_ci 5712c593315Sopenharmony_ci std::copy(std::begin(key.data.name), std::end(key.data.name), key_name); 5722c593315Sopenharmony_ci 5732c593315Sopenharmony_ci EVP_EncryptInit_ex(ctx, get_config()->tls.ticket.cipher, nullptr, 5742c593315Sopenharmony_ci key.data.enc_key.data(), iv); 5752c593315Sopenharmony_ci#if OPENSSL_3_0_0_API 5762c593315Sopenharmony_ci std::array<OSSL_PARAM, 3> params{ 5772c593315Sopenharmony_ci OSSL_PARAM_construct_octet_string( 5782c593315Sopenharmony_ci OSSL_MAC_PARAM_KEY, key.data.hmac_key.data(), key.hmac_keylen), 5792c593315Sopenharmony_ci OSSL_PARAM_construct_utf8_string( 5802c593315Sopenharmony_ci OSSL_MAC_PARAM_DIGEST, 5812c593315Sopenharmony_ci const_cast<char *>(EVP_MD_get0_name(key.hmac)), 0), 5822c593315Sopenharmony_ci OSSL_PARAM_construct_end(), 5832c593315Sopenharmony_ci }; 5842c593315Sopenharmony_ci if (!EVP_MAC_CTX_set_params(hctx, params.data())) { 5852c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 5862c593315Sopenharmony_ci CLOG(INFO, handler) << "EVP_MAC_CTX_set_params failed"; 5872c593315Sopenharmony_ci } 5882c593315Sopenharmony_ci return -1; 5892c593315Sopenharmony_ci } 5902c593315Sopenharmony_ci#else // !OPENSSL_3_0_0_API 5912c593315Sopenharmony_ci HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac, 5922c593315Sopenharmony_ci nullptr); 5932c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API 5942c593315Sopenharmony_ci return 1; 5952c593315Sopenharmony_ci } 5962c593315Sopenharmony_ci 5972c593315Sopenharmony_ci size_t i; 5982c593315Sopenharmony_ci for (i = 0; i < keys.size(); ++i) { 5992c593315Sopenharmony_ci auto &key = keys[i]; 6002c593315Sopenharmony_ci if (std::equal(std::begin(key.data.name), std::end(key.data.name), 6012c593315Sopenharmony_ci key_name)) { 6022c593315Sopenharmony_ci break; 6032c593315Sopenharmony_ci } 6042c593315Sopenharmony_ci } 6052c593315Sopenharmony_ci 6062c593315Sopenharmony_ci if (i == keys.size()) { 6072c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 6082c593315Sopenharmony_ci CLOG(INFO, handler) << "session ticket key " 6092c593315Sopenharmony_ci << util::format_hex(key_name, 16) << " not found"; 6102c593315Sopenharmony_ci } 6112c593315Sopenharmony_ci return 0; 6122c593315Sopenharmony_ci } 6132c593315Sopenharmony_ci 6142c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 6152c593315Sopenharmony_ci CLOG(INFO, handler) << "decrypt session ticket key: " 6162c593315Sopenharmony_ci << util::format_hex(key_name, 16); 6172c593315Sopenharmony_ci } 6182c593315Sopenharmony_ci 6192c593315Sopenharmony_ci auto &key = keys[i]; 6202c593315Sopenharmony_ci#if OPENSSL_3_0_0_API 6212c593315Sopenharmony_ci std::array<OSSL_PARAM, 3> params{ 6222c593315Sopenharmony_ci OSSL_PARAM_construct_octet_string( 6232c593315Sopenharmony_ci OSSL_MAC_PARAM_KEY, key.data.hmac_key.data(), key.hmac_keylen), 6242c593315Sopenharmony_ci OSSL_PARAM_construct_utf8_string( 6252c593315Sopenharmony_ci OSSL_MAC_PARAM_DIGEST, const_cast<char *>(EVP_MD_get0_name(key.hmac)), 6262c593315Sopenharmony_ci 0), 6272c593315Sopenharmony_ci OSSL_PARAM_construct_end(), 6282c593315Sopenharmony_ci }; 6292c593315Sopenharmony_ci if (!EVP_MAC_CTX_set_params(hctx, params.data())) { 6302c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 6312c593315Sopenharmony_ci CLOG(INFO, handler) << "EVP_MAC_CTX_set_params failed"; 6322c593315Sopenharmony_ci } 6332c593315Sopenharmony_ci return -1; 6342c593315Sopenharmony_ci } 6352c593315Sopenharmony_ci#else // !OPENSSL_3_0_0_API 6362c593315Sopenharmony_ci HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac, 6372c593315Sopenharmony_ci nullptr); 6382c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API 6392c593315Sopenharmony_ci EVP_DecryptInit_ex(ctx, key.cipher, nullptr, key.data.enc_key.data(), iv); 6402c593315Sopenharmony_ci 6412c593315Sopenharmony_ci#ifdef TLS1_3_VERSION 6422c593315Sopenharmony_ci // If ticket_key_cb is not set, OpenSSL always renew ticket for 6432c593315Sopenharmony_ci // TLSv1.3. 6442c593315Sopenharmony_ci if (SSL_version(ssl) == TLS1_3_VERSION) { 6452c593315Sopenharmony_ci return 2; 6462c593315Sopenharmony_ci } 6472c593315Sopenharmony_ci#endif // TLS1_3_VERSION 6482c593315Sopenharmony_ci 6492c593315Sopenharmony_ci return i == 0 ? 1 : 2; 6502c593315Sopenharmony_ci} 6512c593315Sopenharmony_ci} // namespace 6522c593315Sopenharmony_ci 6532c593315Sopenharmony_cinamespace { 6542c593315Sopenharmony_civoid info_callback(const SSL *ssl, int where, int ret) { 6552c593315Sopenharmony_ci#ifdef TLS1_3_VERSION 6562c593315Sopenharmony_ci // TLSv1.3 has no renegotiation. 6572c593315Sopenharmony_ci if (SSL_version(ssl) == TLS1_3_VERSION) { 6582c593315Sopenharmony_ci return; 6592c593315Sopenharmony_ci } 6602c593315Sopenharmony_ci#endif // TLS1_3_VERSION 6612c593315Sopenharmony_ci 6622c593315Sopenharmony_ci // To mitigate possible DOS attack using lots of renegotiations, we 6632c593315Sopenharmony_ci // disable renegotiation. Since OpenSSL does not provide an easy way 6642c593315Sopenharmony_ci // to disable it, we check that renegotiation is started in this 6652c593315Sopenharmony_ci // callback. 6662c593315Sopenharmony_ci if (where & SSL_CB_HANDSHAKE_START) { 6672c593315Sopenharmony_ci auto conn = static_cast<Connection *>(SSL_get_app_data(ssl)); 6682c593315Sopenharmony_ci if (conn && conn->tls.initial_handshake_done) { 6692c593315Sopenharmony_ci auto handler = static_cast<ClientHandler *>(conn->data); 6702c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 6712c593315Sopenharmony_ci CLOG(INFO, handler) << "TLS renegotiation started"; 6722c593315Sopenharmony_ci } 6732c593315Sopenharmony_ci handler->start_immediate_shutdown(); 6742c593315Sopenharmony_ci } 6752c593315Sopenharmony_ci } 6762c593315Sopenharmony_ci} 6772c593315Sopenharmony_ci} // namespace 6782c593315Sopenharmony_ci 6792c593315Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L 6802c593315Sopenharmony_cinamespace { 6812c593315Sopenharmony_ciint alpn_select_proto_cb(SSL *ssl, const unsigned char **out, 6822c593315Sopenharmony_ci unsigned char *outlen, const unsigned char *in, 6832c593315Sopenharmony_ci unsigned int inlen, void *arg) { 6842c593315Sopenharmony_ci // We assume that get_config()->npn_list contains ALPN protocol 6852c593315Sopenharmony_ci // identifier sorted by preference order. So we just break when we 6862c593315Sopenharmony_ci // found the first overlap. 6872c593315Sopenharmony_ci for (const auto &target_proto_id : get_config()->tls.npn_list) { 6882c593315Sopenharmony_ci for (auto p = in, end = in + inlen; p < end;) { 6892c593315Sopenharmony_ci auto proto_id = p + 1; 6902c593315Sopenharmony_ci auto proto_len = *p; 6912c593315Sopenharmony_ci 6922c593315Sopenharmony_ci if (proto_id + proto_len <= end && 6932c593315Sopenharmony_ci util::streq(target_proto_id, StringRef{proto_id, proto_len})) { 6942c593315Sopenharmony_ci 6952c593315Sopenharmony_ci *out = reinterpret_cast<const unsigned char *>(proto_id); 6962c593315Sopenharmony_ci *outlen = proto_len; 6972c593315Sopenharmony_ci 6982c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 6992c593315Sopenharmony_ci } 7002c593315Sopenharmony_ci 7012c593315Sopenharmony_ci p += 1 + proto_len; 7022c593315Sopenharmony_ci } 7032c593315Sopenharmony_ci } 7042c593315Sopenharmony_ci 7052c593315Sopenharmony_ci return SSL_TLSEXT_ERR_NOACK; 7062c593315Sopenharmony_ci} 7072c593315Sopenharmony_ci} // namespace 7082c593315Sopenharmony_ci#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L 7092c593315Sopenharmony_ci 7102c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 7112c593315Sopenharmony_ci# if OPENSSL_VERSION_NUMBER >= 0x10002000L 7122c593315Sopenharmony_cinamespace { 7132c593315Sopenharmony_ciint quic_alpn_select_proto_cb(SSL *ssl, const unsigned char **out, 7142c593315Sopenharmony_ci unsigned char *outlen, const unsigned char *in, 7152c593315Sopenharmony_ci unsigned int inlen, void *arg) { 7162c593315Sopenharmony_ci constexpr StringRef alpnlist[] = { 7172c593315Sopenharmony_ci StringRef::from_lit("h3"), 7182c593315Sopenharmony_ci StringRef::from_lit("h3-29"), 7192c593315Sopenharmony_ci }; 7202c593315Sopenharmony_ci 7212c593315Sopenharmony_ci for (auto &alpn : alpnlist) { 7222c593315Sopenharmony_ci for (auto p = in, end = in + inlen; p < end;) { 7232c593315Sopenharmony_ci auto proto_id = p + 1; 7242c593315Sopenharmony_ci auto proto_len = *p; 7252c593315Sopenharmony_ci 7262c593315Sopenharmony_ci if (alpn.size() == proto_len && 7272c593315Sopenharmony_ci memcmp(alpn.byte(), proto_id, alpn.size()) == 0) { 7282c593315Sopenharmony_ci *out = proto_id; 7292c593315Sopenharmony_ci *outlen = proto_len; 7302c593315Sopenharmony_ci 7312c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 7322c593315Sopenharmony_ci } 7332c593315Sopenharmony_ci 7342c593315Sopenharmony_ci p += 1 + proto_len; 7352c593315Sopenharmony_ci } 7362c593315Sopenharmony_ci } 7372c593315Sopenharmony_ci 7382c593315Sopenharmony_ci return SSL_TLSEXT_ERR_ALERT_FATAL; 7392c593315Sopenharmony_ci} 7402c593315Sopenharmony_ci} // namespace 7412c593315Sopenharmony_ci# endif // OPENSSL_VERSION_NUMBER >= 0x10002000L 7422c593315Sopenharmony_ci#endif // ENABLE_HTTP3 7432c593315Sopenharmony_ci 7442c593315Sopenharmony_ci#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L && \ 7452c593315Sopenharmony_ci !defined(OPENSSL_IS_BORINGSSL) 7462c593315Sopenharmony_ci 7472c593315Sopenharmony_ci# ifndef TLSEXT_TYPE_signed_certificate_timestamp 7482c593315Sopenharmony_ci# define TLSEXT_TYPE_signed_certificate_timestamp 18 7492c593315Sopenharmony_ci# endif // !TLSEXT_TYPE_signed_certificate_timestamp 7502c593315Sopenharmony_ci 7512c593315Sopenharmony_cinamespace { 7522c593315Sopenharmony_ciint sct_add_cb(SSL *ssl, unsigned int ext_type, unsigned int context, 7532c593315Sopenharmony_ci const unsigned char **out, size_t *outlen, X509 *x, 7542c593315Sopenharmony_ci size_t chainidx, int *al, void *add_arg) { 7552c593315Sopenharmony_ci assert(ext_type == TLSEXT_TYPE_signed_certificate_timestamp); 7562c593315Sopenharmony_ci 7572c593315Sopenharmony_ci auto conn = static_cast<Connection *>(SSL_get_app_data(ssl)); 7582c593315Sopenharmony_ci if (!conn->tls.sct_requested) { 7592c593315Sopenharmony_ci return 0; 7602c593315Sopenharmony_ci } 7612c593315Sopenharmony_ci 7622c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 7632c593315Sopenharmony_ci LOG(INFO) << "sct_add_cb is called, chainidx=" << chainidx << ", x=" << x 7642c593315Sopenharmony_ci << ", context=" << log::hex << context; 7652c593315Sopenharmony_ci } 7662c593315Sopenharmony_ci 7672c593315Sopenharmony_ci // We only have SCTs for leaf certificate. 7682c593315Sopenharmony_ci if (chainidx != 0) { 7692c593315Sopenharmony_ci return 0; 7702c593315Sopenharmony_ci } 7712c593315Sopenharmony_ci 7722c593315Sopenharmony_ci auto ssl_ctx = SSL_get_SSL_CTX(ssl); 7732c593315Sopenharmony_ci auto tls_ctx_data = 7742c593315Sopenharmony_ci static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx)); 7752c593315Sopenharmony_ci 7762c593315Sopenharmony_ci *out = tls_ctx_data->sct_data.data(); 7772c593315Sopenharmony_ci *outlen = tls_ctx_data->sct_data.size(); 7782c593315Sopenharmony_ci 7792c593315Sopenharmony_ci return 1; 7802c593315Sopenharmony_ci} 7812c593315Sopenharmony_ci} // namespace 7822c593315Sopenharmony_ci 7832c593315Sopenharmony_cinamespace { 7842c593315Sopenharmony_civoid sct_free_cb(SSL *ssl, unsigned int ext_type, unsigned int context, 7852c593315Sopenharmony_ci const unsigned char *out, void *add_arg) { 7862c593315Sopenharmony_ci assert(ext_type == TLSEXT_TYPE_signed_certificate_timestamp); 7872c593315Sopenharmony_ci} 7882c593315Sopenharmony_ci} // namespace 7892c593315Sopenharmony_ci 7902c593315Sopenharmony_cinamespace { 7912c593315Sopenharmony_ciint sct_parse_cb(SSL *ssl, unsigned int ext_type, unsigned int context, 7922c593315Sopenharmony_ci const unsigned char *in, size_t inlen, X509 *x, 7932c593315Sopenharmony_ci size_t chainidx, int *al, void *parse_arg) { 7942c593315Sopenharmony_ci assert(ext_type == TLSEXT_TYPE_signed_certificate_timestamp); 7952c593315Sopenharmony_ci // client SHOULD send 0 length extension_data, but it is still 7962c593315Sopenharmony_ci // SHOULD, and not MUST. 7972c593315Sopenharmony_ci 7982c593315Sopenharmony_ci // For TLSv1.3 Certificate message, sct_add_cb is called even if 7992c593315Sopenharmony_ci // client has not sent signed_certificate_timestamp extension in its 8002c593315Sopenharmony_ci // ClientHello. Explicitly remember that client has included it 8012c593315Sopenharmony_ci // here. 8022c593315Sopenharmony_ci auto conn = static_cast<Connection *>(SSL_get_app_data(ssl)); 8032c593315Sopenharmony_ci conn->tls.sct_requested = true; 8042c593315Sopenharmony_ci 8052c593315Sopenharmony_ci return 1; 8062c593315Sopenharmony_ci} 8072c593315Sopenharmony_ci} // namespace 8082c593315Sopenharmony_ci 8092c593315Sopenharmony_ci# if !OPENSSL_1_1_1_API 8102c593315Sopenharmony_ci 8112c593315Sopenharmony_cinamespace { 8122c593315Sopenharmony_ciint legacy_sct_add_cb(SSL *ssl, unsigned int ext_type, 8132c593315Sopenharmony_ci const unsigned char **out, size_t *outlen, int *al, 8142c593315Sopenharmony_ci void *add_arg) { 8152c593315Sopenharmony_ci return sct_add_cb(ssl, ext_type, 0, out, outlen, nullptr, 0, al, add_arg); 8162c593315Sopenharmony_ci} 8172c593315Sopenharmony_ci} // namespace 8182c593315Sopenharmony_ci 8192c593315Sopenharmony_cinamespace { 8202c593315Sopenharmony_civoid legacy_sct_free_cb(SSL *ssl, unsigned int ext_type, 8212c593315Sopenharmony_ci const unsigned char *out, void *add_arg) { 8222c593315Sopenharmony_ci sct_free_cb(ssl, ext_type, 0, out, add_arg); 8232c593315Sopenharmony_ci} 8242c593315Sopenharmony_ci} // namespace 8252c593315Sopenharmony_ci 8262c593315Sopenharmony_cinamespace { 8272c593315Sopenharmony_ciint legacy_sct_parse_cb(SSL *ssl, unsigned int ext_type, 8282c593315Sopenharmony_ci const unsigned char *in, size_t inlen, int *al, 8292c593315Sopenharmony_ci void *parse_arg) { 8302c593315Sopenharmony_ci return sct_parse_cb(ssl, ext_type, 0, in, inlen, nullptr, 0, al, parse_arg); 8312c593315Sopenharmony_ci} 8322c593315Sopenharmony_ci} // namespace 8332c593315Sopenharmony_ci 8342c593315Sopenharmony_ci# endif // !OPENSSL_1_1_1_API 8352c593315Sopenharmony_ci#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L && 8362c593315Sopenharmony_ci // !defined(OPENSSL_IS_BORINGSSL) 8372c593315Sopenharmony_ci 8382c593315Sopenharmony_ci#ifndef OPENSSL_NO_PSK 8392c593315Sopenharmony_cinamespace { 8402c593315Sopenharmony_ciunsigned int psk_server_cb(SSL *ssl, const char *identity, unsigned char *psk, 8412c593315Sopenharmony_ci unsigned int max_psk_len) { 8422c593315Sopenharmony_ci auto config = get_config(); 8432c593315Sopenharmony_ci auto &tlsconf = config->tls; 8442c593315Sopenharmony_ci 8452c593315Sopenharmony_ci auto it = tlsconf.psk_secrets.find(StringRef{identity}); 8462c593315Sopenharmony_ci if (it == std::end(tlsconf.psk_secrets)) { 8472c593315Sopenharmony_ci return 0; 8482c593315Sopenharmony_ci } 8492c593315Sopenharmony_ci 8502c593315Sopenharmony_ci auto &secret = (*it).second; 8512c593315Sopenharmony_ci if (secret.size() > max_psk_len) { 8522c593315Sopenharmony_ci LOG(ERROR) << "The size of PSK secret is " << secret.size() 8532c593315Sopenharmony_ci << ", but the acceptable maximum size is" << max_psk_len; 8542c593315Sopenharmony_ci return 0; 8552c593315Sopenharmony_ci } 8562c593315Sopenharmony_ci 8572c593315Sopenharmony_ci std::copy(std::begin(secret), std::end(secret), psk); 8582c593315Sopenharmony_ci 8592c593315Sopenharmony_ci return static_cast<unsigned int>(secret.size()); 8602c593315Sopenharmony_ci} 8612c593315Sopenharmony_ci} // namespace 8622c593315Sopenharmony_ci#endif // !OPENSSL_NO_PSK 8632c593315Sopenharmony_ci 8642c593315Sopenharmony_ci#ifndef OPENSSL_NO_PSK 8652c593315Sopenharmony_cinamespace { 8662c593315Sopenharmony_ciunsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity_out, 8672c593315Sopenharmony_ci unsigned int max_identity_len, unsigned char *psk, 8682c593315Sopenharmony_ci unsigned int max_psk_len) { 8692c593315Sopenharmony_ci auto config = get_config(); 8702c593315Sopenharmony_ci auto &tlsconf = config->tls; 8712c593315Sopenharmony_ci 8722c593315Sopenharmony_ci auto &identity = tlsconf.client.psk.identity; 8732c593315Sopenharmony_ci auto &secret = tlsconf.client.psk.secret; 8742c593315Sopenharmony_ci 8752c593315Sopenharmony_ci if (identity.empty()) { 8762c593315Sopenharmony_ci return 0; 8772c593315Sopenharmony_ci } 8782c593315Sopenharmony_ci 8792c593315Sopenharmony_ci if (identity.size() + 1 > max_identity_len) { 8802c593315Sopenharmony_ci LOG(ERROR) << "The size of PSK identity is " << identity.size() 8812c593315Sopenharmony_ci << ", but the acceptable maximum size is " << max_identity_len; 8822c593315Sopenharmony_ci return 0; 8832c593315Sopenharmony_ci } 8842c593315Sopenharmony_ci 8852c593315Sopenharmony_ci if (secret.size() > max_psk_len) { 8862c593315Sopenharmony_ci LOG(ERROR) << "The size of PSK secret is " << secret.size() 8872c593315Sopenharmony_ci << ", but the acceptable maximum size is " << max_psk_len; 8882c593315Sopenharmony_ci return 0; 8892c593315Sopenharmony_ci } 8902c593315Sopenharmony_ci 8912c593315Sopenharmony_ci *std::copy(std::begin(identity), std::end(identity), identity_out) = '\0'; 8922c593315Sopenharmony_ci std::copy(std::begin(secret), std::end(secret), psk); 8932c593315Sopenharmony_ci 8942c593315Sopenharmony_ci return static_cast<unsigned int>(secret.size()); 8952c593315Sopenharmony_ci} 8962c593315Sopenharmony_ci} // namespace 8972c593315Sopenharmony_ci#endif // !OPENSSL_NO_PSK 8982c593315Sopenharmony_ci 8992c593315Sopenharmony_cistruct TLSProtocol { 9002c593315Sopenharmony_ci StringRef name; 9012c593315Sopenharmony_ci long int mask; 9022c593315Sopenharmony_ci}; 9032c593315Sopenharmony_ci 9042c593315Sopenharmony_ciconstexpr TLSProtocol TLS_PROTOS[] = { 9052c593315Sopenharmony_ci TLSProtocol{StringRef::from_lit("TLSv1.2"), SSL_OP_NO_TLSv1_2}, 9062c593315Sopenharmony_ci TLSProtocol{StringRef::from_lit("TLSv1.1"), SSL_OP_NO_TLSv1_1}, 9072c593315Sopenharmony_ci TLSProtocol{StringRef::from_lit("TLSv1.0"), SSL_OP_NO_TLSv1}}; 9082c593315Sopenharmony_ci 9092c593315Sopenharmony_cilong int create_tls_proto_mask(const std::vector<StringRef> &tls_proto_list) { 9102c593315Sopenharmony_ci long int res = 0; 9112c593315Sopenharmony_ci 9122c593315Sopenharmony_ci for (auto &supported : TLS_PROTOS) { 9132c593315Sopenharmony_ci auto ok = false; 9142c593315Sopenharmony_ci for (auto &name : tls_proto_list) { 9152c593315Sopenharmony_ci if (util::strieq(supported.name, name)) { 9162c593315Sopenharmony_ci ok = true; 9172c593315Sopenharmony_ci break; 9182c593315Sopenharmony_ci } 9192c593315Sopenharmony_ci } 9202c593315Sopenharmony_ci if (!ok) { 9212c593315Sopenharmony_ci res |= supported.mask; 9222c593315Sopenharmony_ci } 9232c593315Sopenharmony_ci } 9242c593315Sopenharmony_ci return res; 9252c593315Sopenharmony_ci} 9262c593315Sopenharmony_ci 9272c593315Sopenharmony_ciSSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, 9282c593315Sopenharmony_ci const std::vector<uint8_t> &sct_data 9292c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 9302c593315Sopenharmony_ci , 9312c593315Sopenharmony_ci neverbleed_t *nb 9322c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 9332c593315Sopenharmony_ci) { 9342c593315Sopenharmony_ci auto ssl_ctx = SSL_CTX_new(TLS_server_method()); 9352c593315Sopenharmony_ci if (!ssl_ctx) { 9362c593315Sopenharmony_ci LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr); 9372c593315Sopenharmony_ci DIE(); 9382c593315Sopenharmony_ci } 9392c593315Sopenharmony_ci 9402c593315Sopenharmony_ci auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | 9412c593315Sopenharmony_ci SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION | 9422c593315Sopenharmony_ci SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | 9432c593315Sopenharmony_ci SSL_OP_SINGLE_ECDH_USE | SSL_OP_SINGLE_DH_USE | 9442c593315Sopenharmony_ci SSL_OP_CIPHER_SERVER_PREFERENCE 9452c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 9462c593315Sopenharmony_ci // The reason for disabling built-in anti-replay in 9472c593315Sopenharmony_ci // OpenSSL is that it only works if client gets back 9482c593315Sopenharmony_ci // to the same server. The freshness check 9492c593315Sopenharmony_ci // described in 9502c593315Sopenharmony_ci // https://tools.ietf.org/html/rfc8446#section-8.3 9512c593315Sopenharmony_ci // is still performed. 9522c593315Sopenharmony_ci | SSL_OP_NO_ANTI_REPLAY 9532c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 9542c593315Sopenharmony_ci ; 9552c593315Sopenharmony_ci 9562c593315Sopenharmony_ci auto config = mod_config(); 9572c593315Sopenharmony_ci auto &tlsconf = config->tls; 9582c593315Sopenharmony_ci 9592c593315Sopenharmony_ci#ifdef SSL_OP_ENABLE_KTLS 9602c593315Sopenharmony_ci if (tlsconf.ktls) { 9612c593315Sopenharmony_ci ssl_opts |= SSL_OP_ENABLE_KTLS; 9622c593315Sopenharmony_ci } 9632c593315Sopenharmony_ci#endif // SSL_OP_ENABLE_KTLS 9642c593315Sopenharmony_ci 9652c593315Sopenharmony_ci SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask); 9662c593315Sopenharmony_ci 9672c593315Sopenharmony_ci if (nghttp2::tls::ssl_ctx_set_proto_versions( 9682c593315Sopenharmony_ci ssl_ctx, tlsconf.min_proto_version, tlsconf.max_proto_version) != 0) { 9692c593315Sopenharmony_ci LOG(FATAL) << "Could not set TLS protocol version"; 9702c593315Sopenharmony_ci DIE(); 9712c593315Sopenharmony_ci } 9722c593315Sopenharmony_ci 9732c593315Sopenharmony_ci const unsigned char sid_ctx[] = "shrpx"; 9742c593315Sopenharmony_ci SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1); 9752c593315Sopenharmony_ci SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER); 9762c593315Sopenharmony_ci 9772c593315Sopenharmony_ci if (!tlsconf.session_cache.memcached.host.empty()) { 9782c593315Sopenharmony_ci SSL_CTX_sess_set_new_cb(ssl_ctx, tls_session_new_cb); 9792c593315Sopenharmony_ci SSL_CTX_sess_set_get_cb(ssl_ctx, tls_session_get_cb); 9802c593315Sopenharmony_ci } 9812c593315Sopenharmony_ci 9822c593315Sopenharmony_ci SSL_CTX_set_timeout(ssl_ctx, tlsconf.session_timeout.count()); 9832c593315Sopenharmony_ci 9842c593315Sopenharmony_ci if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.ciphers.c_str()) == 0) { 9852c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_cipher_list " << tlsconf.ciphers 9862c593315Sopenharmony_ci << " failed: " << ERR_error_string(ERR_get_error(), nullptr); 9872c593315Sopenharmony_ci DIE(); 9882c593315Sopenharmony_ci } 9892c593315Sopenharmony_ci 9902c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 9912c593315Sopenharmony_ci if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.c_str()) == 0) { 9922c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.tls13_ciphers 9932c593315Sopenharmony_ci << " failed: " << ERR_error_string(ERR_get_error(), nullptr); 9942c593315Sopenharmony_ci DIE(); 9952c593315Sopenharmony_ci } 9962c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 9972c593315Sopenharmony_ci 9982c593315Sopenharmony_ci#ifndef OPENSSL_NO_EC 9992c593315Sopenharmony_ci# if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L 10002c593315Sopenharmony_ci if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.c_str()) != 1) { 10012c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set1_curves_list " << tlsconf.ecdh_curves 10022c593315Sopenharmony_ci << " failed"; 10032c593315Sopenharmony_ci DIE(); 10042c593315Sopenharmony_ci } 10052c593315Sopenharmony_ci# if !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_1_1_API 10062c593315Sopenharmony_ci // It looks like we need this function call for OpenSSL 1.0.2. This 10072c593315Sopenharmony_ci // function was deprecated in OpenSSL 1.1.0 and BoringSSL. 10082c593315Sopenharmony_ci SSL_CTX_set_ecdh_auto(ssl_ctx, 1); 10092c593315Sopenharmony_ci# endif // !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_1_1_API 10102c593315Sopenharmony_ci# else // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L 10112c593315Sopenharmony_ci // Use P-256, which is sufficiently secure at the time of this 10122c593315Sopenharmony_ci // writing. 10132c593315Sopenharmony_ci auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 10142c593315Sopenharmony_ci if (ecdh == nullptr) { 10152c593315Sopenharmony_ci LOG(FATAL) << "EC_KEY_new_by_curv_name failed: " 10162c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 10172c593315Sopenharmony_ci DIE(); 10182c593315Sopenharmony_ci } 10192c593315Sopenharmony_ci SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh); 10202c593315Sopenharmony_ci EC_KEY_free(ecdh); 10212c593315Sopenharmony_ci# endif // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L 10222c593315Sopenharmony_ci#endif // OPENSSL_NO_EC 10232c593315Sopenharmony_ci 10242c593315Sopenharmony_ci if (!tlsconf.dh_param_file.empty()) { 10252c593315Sopenharmony_ci // Read DH parameters from file 10262c593315Sopenharmony_ci auto bio = BIO_new_file(tlsconf.dh_param_file.c_str(), "rb"); 10272c593315Sopenharmony_ci if (bio == nullptr) { 10282c593315Sopenharmony_ci LOG(FATAL) << "BIO_new_file() failed: " 10292c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 10302c593315Sopenharmony_ci DIE(); 10312c593315Sopenharmony_ci } 10322c593315Sopenharmony_ci#if OPENSSL_3_0_0_API 10332c593315Sopenharmony_ci EVP_PKEY *dh = nullptr; 10342c593315Sopenharmony_ci auto dctx = OSSL_DECODER_CTX_new_for_pkey( 10352c593315Sopenharmony_ci &dh, "PEM", nullptr, "DH", OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, 10362c593315Sopenharmony_ci nullptr, nullptr); 10372c593315Sopenharmony_ci 10382c593315Sopenharmony_ci if (!OSSL_DECODER_from_bio(dctx, bio)) { 10392c593315Sopenharmony_ci LOG(FATAL) << "OSSL_DECODER_from_bio() failed: " 10402c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 10412c593315Sopenharmony_ci DIE(); 10422c593315Sopenharmony_ci } 10432c593315Sopenharmony_ci 10442c593315Sopenharmony_ci if (SSL_CTX_set0_tmp_dh_pkey(ssl_ctx, dh) != 1) { 10452c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set0_tmp_dh_pkey failed: " 10462c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 10472c593315Sopenharmony_ci DIE(); 10482c593315Sopenharmony_ci } 10492c593315Sopenharmony_ci#else // !OPENSSL_3_0_0_API 10502c593315Sopenharmony_ci auto dh = PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr); 10512c593315Sopenharmony_ci if (dh == nullptr) { 10522c593315Sopenharmony_ci LOG(FATAL) << "PEM_read_bio_DHparams() failed: " 10532c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 10542c593315Sopenharmony_ci DIE(); 10552c593315Sopenharmony_ci } 10562c593315Sopenharmony_ci SSL_CTX_set_tmp_dh(ssl_ctx, dh); 10572c593315Sopenharmony_ci DH_free(dh); 10582c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API 10592c593315Sopenharmony_ci BIO_free(bio); 10602c593315Sopenharmony_ci } 10612c593315Sopenharmony_ci 10622c593315Sopenharmony_ci SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); 10632c593315Sopenharmony_ci 10642c593315Sopenharmony_ci if (SSL_CTX_set_default_verify_paths(ssl_ctx) != 1) { 10652c593315Sopenharmony_ci LOG(WARN) << "Could not load system trusted ca certificates: " 10662c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 10672c593315Sopenharmony_ci } 10682c593315Sopenharmony_ci 10692c593315Sopenharmony_ci if (!tlsconf.cacert.empty()) { 10702c593315Sopenharmony_ci if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.c_str(), 10712c593315Sopenharmony_ci nullptr) != 1) { 10722c593315Sopenharmony_ci LOG(FATAL) << "Could not load trusted ca certificates from " 10732c593315Sopenharmony_ci << tlsconf.cacert << ": " 10742c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 10752c593315Sopenharmony_ci DIE(); 10762c593315Sopenharmony_ci } 10772c593315Sopenharmony_ci } 10782c593315Sopenharmony_ci 10792c593315Sopenharmony_ci if (!tlsconf.private_key_passwd.empty()) { 10802c593315Sopenharmony_ci SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb); 10812c593315Sopenharmony_ci SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, config); 10822c593315Sopenharmony_ci } 10832c593315Sopenharmony_ci 10842c593315Sopenharmony_ci#ifndef HAVE_NEVERBLEED 10852c593315Sopenharmony_ci if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file, 10862c593315Sopenharmony_ci SSL_FILETYPE_PEM) != 1) { 10872c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_use_PrivateKey_file failed: " 10882c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 10892c593315Sopenharmony_ci DIE(); 10902c593315Sopenharmony_ci } 10912c593315Sopenharmony_ci#else // HAVE_NEVERBLEED 10922c593315Sopenharmony_ci std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf; 10932c593315Sopenharmony_ci if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file, 10942c593315Sopenharmony_ci errbuf.data()) != 1) { 10952c593315Sopenharmony_ci LOG(FATAL) << "neverbleed_load_private_key_file failed: " << errbuf.data(); 10962c593315Sopenharmony_ci DIE(); 10972c593315Sopenharmony_ci } 10982c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 10992c593315Sopenharmony_ci 11002c593315Sopenharmony_ci if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) { 11012c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_use_certificate_file failed: " 11022c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 11032c593315Sopenharmony_ci DIE(); 11042c593315Sopenharmony_ci } 11052c593315Sopenharmony_ci if (SSL_CTX_check_private_key(ssl_ctx) != 1) { 11062c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_check_private_key failed: " 11072c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 11082c593315Sopenharmony_ci DIE(); 11092c593315Sopenharmony_ci } 11102c593315Sopenharmony_ci if (tlsconf.client_verify.enabled) { 11112c593315Sopenharmony_ci if (!tlsconf.client_verify.cacert.empty()) { 11122c593315Sopenharmony_ci if (SSL_CTX_load_verify_locations( 11132c593315Sopenharmony_ci ssl_ctx, tlsconf.client_verify.cacert.c_str(), nullptr) != 1) { 11142c593315Sopenharmony_ci 11152c593315Sopenharmony_ci LOG(FATAL) << "Could not load trusted ca certificates from " 11162c593315Sopenharmony_ci << tlsconf.client_verify.cacert << ": " 11172c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 11182c593315Sopenharmony_ci DIE(); 11192c593315Sopenharmony_ci } 11202c593315Sopenharmony_ci // It is heard that SSL_CTX_load_verify_locations() may leave 11212c593315Sopenharmony_ci // error even though it returns success. See 11222c593315Sopenharmony_ci // http://forum.nginx.org/read.php?29,242540 11232c593315Sopenharmony_ci ERR_clear_error(); 11242c593315Sopenharmony_ci auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.c_str()); 11252c593315Sopenharmony_ci if (!list) { 11262c593315Sopenharmony_ci LOG(FATAL) << "Could not load ca certificates from " 11272c593315Sopenharmony_ci << tlsconf.client_verify.cacert << ": " 11282c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 11292c593315Sopenharmony_ci DIE(); 11302c593315Sopenharmony_ci } 11312c593315Sopenharmony_ci SSL_CTX_set_client_CA_list(ssl_ctx, list); 11322c593315Sopenharmony_ci } 11332c593315Sopenharmony_ci SSL_CTX_set_verify(ssl_ctx, 11342c593315Sopenharmony_ci SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | 11352c593315Sopenharmony_ci SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 11362c593315Sopenharmony_ci verify_callback); 11372c593315Sopenharmony_ci } 11382c593315Sopenharmony_ci SSL_CTX_set_tlsext_servername_callback(ssl_ctx, servername_callback); 11392c593315Sopenharmony_ci#if OPENSSL_3_0_0_API 11402c593315Sopenharmony_ci SSL_CTX_set_tlsext_ticket_key_evp_cb(ssl_ctx, ticket_key_cb); 11412c593315Sopenharmony_ci#else // !OPENSSL_3_0_0_API 11422c593315Sopenharmony_ci SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx, ticket_key_cb); 11432c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API 11442c593315Sopenharmony_ci#ifndef OPENSSL_IS_BORINGSSL 11452c593315Sopenharmony_ci SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb); 11462c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL 11472c593315Sopenharmony_ci SSL_CTX_set_info_callback(ssl_ctx, info_callback); 11482c593315Sopenharmony_ci 11492c593315Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL 11502c593315Sopenharmony_ci SSL_CTX_set_early_data_enabled(ssl_ctx, 1); 11512c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL 11522c593315Sopenharmony_ci 11532c593315Sopenharmony_ci // NPN advertisement 11542c593315Sopenharmony_ci#ifndef OPENSSL_NO_NEXTPROTONEG 11552c593315Sopenharmony_ci SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, nullptr); 11562c593315Sopenharmony_ci#endif // !OPENSSL_NO_NEXTPROTONEG 11572c593315Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L 11582c593315Sopenharmony_ci // ALPN selection callback 11592c593315Sopenharmony_ci SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, nullptr); 11602c593315Sopenharmony_ci#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L 11612c593315Sopenharmony_ci 11622c593315Sopenharmony_ci auto tls_ctx_data = new TLSContextData(); 11632c593315Sopenharmony_ci tls_ctx_data->cert_file = cert_file; 11642c593315Sopenharmony_ci tls_ctx_data->sct_data = sct_data; 11652c593315Sopenharmony_ci 11662c593315Sopenharmony_ci SSL_CTX_set_app_data(ssl_ctx, tls_ctx_data); 11672c593315Sopenharmony_ci 11682c593315Sopenharmony_ci#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L && \ 11692c593315Sopenharmony_ci !defined(OPENSSL_IS_BORINGSSL) 11702c593315Sopenharmony_ci // SSL_extension_supported(TLSEXT_TYPE_signed_certificate_timestamp) 11712c593315Sopenharmony_ci // returns 1, which means OpenSSL internally handles it. But 11722c593315Sopenharmony_ci // OpenSSL handles signed_certificate_timestamp extension specially, 11732c593315Sopenharmony_ci // and it lets custom handler to process the extension. 11742c593315Sopenharmony_ci if (!sct_data.empty()) { 11752c593315Sopenharmony_ci# if OPENSSL_1_1_1_API 11762c593315Sopenharmony_ci // It is not entirely clear to me that SSL_EXT_CLIENT_HELLO is 11772c593315Sopenharmony_ci // required here. sct_parse_cb is called without 11782c593315Sopenharmony_ci // SSL_EXT_CLIENT_HELLO being set. But the passed context value 11792c593315Sopenharmony_ci // is SSL_EXT_CLIENT_HELLO. 11802c593315Sopenharmony_ci if (SSL_CTX_add_custom_ext( 11812c593315Sopenharmony_ci ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp, 11822c593315Sopenharmony_ci SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO | 11832c593315Sopenharmony_ci SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_IGNORE_ON_RESUMPTION, 11842c593315Sopenharmony_ci sct_add_cb, sct_free_cb, nullptr, sct_parse_cb, nullptr) != 1) { 11852c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_add_custom_ext failed: " 11862c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 11872c593315Sopenharmony_ci DIE(); 11882c593315Sopenharmony_ci } 11892c593315Sopenharmony_ci# else // !OPENSSL_1_1_1_API 11902c593315Sopenharmony_ci if (SSL_CTX_add_server_custom_ext( 11912c593315Sopenharmony_ci ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp, 11922c593315Sopenharmony_ci legacy_sct_add_cb, legacy_sct_free_cb, nullptr, legacy_sct_parse_cb, 11932c593315Sopenharmony_ci nullptr) != 1) { 11942c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_add_server_custom_ext failed: " 11952c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 11962c593315Sopenharmony_ci DIE(); 11972c593315Sopenharmony_ci } 11982c593315Sopenharmony_ci# endif // !OPENSSL_1_1_1_API 11992c593315Sopenharmony_ci } 12002c593315Sopenharmony_ci#elif defined(OPENSSL_IS_BORINGSSL) 12012c593315Sopenharmony_ci if (!tls_ctx_data->sct_data.empty() && 12022c593315Sopenharmony_ci SSL_CTX_set_signed_cert_timestamp_list( 12032c593315Sopenharmony_ci ssl_ctx, tls_ctx_data->sct_data.data(), 12042c593315Sopenharmony_ci tls_ctx_data->sct_data.size()) != 1) { 12052c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_signed_cert_timestamp_list failed: " 12062c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 12072c593315Sopenharmony_ci DIE(); 12082c593315Sopenharmony_ci } 12092c593315Sopenharmony_ci#endif // defined(OPENSSL_IS_BORINGSSL) 12102c593315Sopenharmony_ci 12112c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 12122c593315Sopenharmony_ci if (SSL_CTX_set_max_early_data(ssl_ctx, tlsconf.max_early_data) != 1) { 12132c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_max_early_data failed: " 12142c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 12152c593315Sopenharmony_ci DIE(); 12162c593315Sopenharmony_ci } 12172c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 12182c593315Sopenharmony_ci 12192c593315Sopenharmony_ci#ifndef OPENSSL_NO_PSK 12202c593315Sopenharmony_ci SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb); 12212c593315Sopenharmony_ci#endif // !LIBRESSL_NO_PSK 12222c593315Sopenharmony_ci 12232c593315Sopenharmony_ci return ssl_ctx; 12242c593315Sopenharmony_ci} 12252c593315Sopenharmony_ci 12262c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 12272c593315Sopenharmony_ciSSL_CTX *create_quic_ssl_context(const char *private_key_file, 12282c593315Sopenharmony_ci const char *cert_file, 12292c593315Sopenharmony_ci const std::vector<uint8_t> &sct_data 12302c593315Sopenharmony_ci# ifdef HAVE_NEVERBLEED 12312c593315Sopenharmony_ci , 12322c593315Sopenharmony_ci neverbleed_t *nb 12332c593315Sopenharmony_ci# endif // HAVE_NEVERBLEED 12342c593315Sopenharmony_ci) { 12352c593315Sopenharmony_ci auto ssl_ctx = SSL_CTX_new(TLS_server_method()); 12362c593315Sopenharmony_ci if (!ssl_ctx) { 12372c593315Sopenharmony_ci LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr); 12382c593315Sopenharmony_ci DIE(); 12392c593315Sopenharmony_ci } 12402c593315Sopenharmony_ci 12412c593315Sopenharmony_ci constexpr auto ssl_opts = 12422c593315Sopenharmony_ci (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | 12432c593315Sopenharmony_ci SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE | 12442c593315Sopenharmony_ci SSL_OP_SINGLE_DH_USE | 12452c593315Sopenharmony_ci SSL_OP_CIPHER_SERVER_PREFERENCE 12462c593315Sopenharmony_ci# if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 12472c593315Sopenharmony_ci // The reason for disabling built-in anti-replay in OpenSSL is 12482c593315Sopenharmony_ci // that it only works if client gets back to the same server. 12492c593315Sopenharmony_ci // The freshness check described in 12502c593315Sopenharmony_ci // https://tools.ietf.org/html/rfc8446#section-8.3 is still 12512c593315Sopenharmony_ci // performed. 12522c593315Sopenharmony_ci | SSL_OP_NO_ANTI_REPLAY 12532c593315Sopenharmony_ci# endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 12542c593315Sopenharmony_ci ; 12552c593315Sopenharmony_ci 12562c593315Sopenharmony_ci auto config = mod_config(); 12572c593315Sopenharmony_ci auto &tlsconf = config->tls; 12582c593315Sopenharmony_ci 12592c593315Sopenharmony_ci SSL_CTX_set_options(ssl_ctx, ssl_opts); 12602c593315Sopenharmony_ci 12612c593315Sopenharmony_ci# ifdef HAVE_LIBNGTCP2_CRYPTO_QUICTLS 12622c593315Sopenharmony_ci if (ngtcp2_crypto_quictls_configure_server_context(ssl_ctx) != 0) { 12632c593315Sopenharmony_ci LOG(FATAL) << "ngtcp2_crypto_quictls_configure_server_context failed"; 12642c593315Sopenharmony_ci DIE(); 12652c593315Sopenharmony_ci } 12662c593315Sopenharmony_ci# endif // HAVE_LIBNGTCP2_CRYPTO_QUICTLS 12672c593315Sopenharmony_ci# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL 12682c593315Sopenharmony_ci if (ngtcp2_crypto_boringssl_configure_server_context(ssl_ctx) != 0) { 12692c593315Sopenharmony_ci LOG(FATAL) << "ngtcp2_crypto_boringssl_configure_server_context failed"; 12702c593315Sopenharmony_ci DIE(); 12712c593315Sopenharmony_ci } 12722c593315Sopenharmony_ci# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL 12732c593315Sopenharmony_ci 12742c593315Sopenharmony_ci const unsigned char sid_ctx[] = "shrpx"; 12752c593315Sopenharmony_ci SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1); 12762c593315Sopenharmony_ci SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_OFF); 12772c593315Sopenharmony_ci 12782c593315Sopenharmony_ci SSL_CTX_set_timeout(ssl_ctx, tlsconf.session_timeout.count()); 12792c593315Sopenharmony_ci 12802c593315Sopenharmony_ci if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.ciphers.c_str()) == 0) { 12812c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_cipher_list " << tlsconf.ciphers 12822c593315Sopenharmony_ci << " failed: " << ERR_error_string(ERR_get_error(), nullptr); 12832c593315Sopenharmony_ci DIE(); 12842c593315Sopenharmony_ci } 12852c593315Sopenharmony_ci 12862c593315Sopenharmony_ci# if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 12872c593315Sopenharmony_ci if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.c_str()) == 0) { 12882c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.tls13_ciphers 12892c593315Sopenharmony_ci << " failed: " << ERR_error_string(ERR_get_error(), nullptr); 12902c593315Sopenharmony_ci DIE(); 12912c593315Sopenharmony_ci } 12922c593315Sopenharmony_ci# endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 12932c593315Sopenharmony_ci 12942c593315Sopenharmony_ci# ifndef OPENSSL_NO_EC 12952c593315Sopenharmony_ci# if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L 12962c593315Sopenharmony_ci if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.c_str()) != 1) { 12972c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set1_curves_list " << tlsconf.ecdh_curves 12982c593315Sopenharmony_ci << " failed"; 12992c593315Sopenharmony_ci DIE(); 13002c593315Sopenharmony_ci } 13012c593315Sopenharmony_ci# if !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_1_1_API 13022c593315Sopenharmony_ci // It looks like we need this function call for OpenSSL 1.0.2. This 13032c593315Sopenharmony_ci // function was deprecated in OpenSSL 1.1.0 and BoringSSL. 13042c593315Sopenharmony_ci SSL_CTX_set_ecdh_auto(ssl_ctx, 1); 13052c593315Sopenharmony_ci# endif // !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_1_1_API 13062c593315Sopenharmony_ci# else // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L 13072c593315Sopenharmony_ci // Use P-256, which is sufficiently secure at the time of this 13082c593315Sopenharmony_ci // writing. 13092c593315Sopenharmony_ci auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 13102c593315Sopenharmony_ci if (ecdh == nullptr) { 13112c593315Sopenharmony_ci LOG(FATAL) << "EC_KEY_new_by_curv_name failed: " 13122c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 13132c593315Sopenharmony_ci DIE(); 13142c593315Sopenharmony_ci } 13152c593315Sopenharmony_ci SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh); 13162c593315Sopenharmony_ci EC_KEY_free(ecdh); 13172c593315Sopenharmony_ci# endif // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L 13182c593315Sopenharmony_ci# endif // OPENSSL_NO_EC 13192c593315Sopenharmony_ci 13202c593315Sopenharmony_ci if (!tlsconf.dh_param_file.empty()) { 13212c593315Sopenharmony_ci // Read DH parameters from file 13222c593315Sopenharmony_ci auto bio = BIO_new_file(tlsconf.dh_param_file.c_str(), "rb"); 13232c593315Sopenharmony_ci if (bio == nullptr) { 13242c593315Sopenharmony_ci LOG(FATAL) << "BIO_new_file() failed: " 13252c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 13262c593315Sopenharmony_ci DIE(); 13272c593315Sopenharmony_ci } 13282c593315Sopenharmony_ci# if OPENSSL_3_0_0_API 13292c593315Sopenharmony_ci EVP_PKEY *dh = nullptr; 13302c593315Sopenharmony_ci auto dctx = OSSL_DECODER_CTX_new_for_pkey( 13312c593315Sopenharmony_ci &dh, "PEM", nullptr, "DH", OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, 13322c593315Sopenharmony_ci nullptr, nullptr); 13332c593315Sopenharmony_ci 13342c593315Sopenharmony_ci if (!OSSL_DECODER_from_bio(dctx, bio)) { 13352c593315Sopenharmony_ci LOG(FATAL) << "OSSL_DECODER_from_bio() failed: " 13362c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 13372c593315Sopenharmony_ci DIE(); 13382c593315Sopenharmony_ci } 13392c593315Sopenharmony_ci 13402c593315Sopenharmony_ci if (SSL_CTX_set0_tmp_dh_pkey(ssl_ctx, dh) != 1) { 13412c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set0_tmp_dh_pkey failed: " 13422c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 13432c593315Sopenharmony_ci DIE(); 13442c593315Sopenharmony_ci } 13452c593315Sopenharmony_ci# else // !OPENSSL_3_0_0_API 13462c593315Sopenharmony_ci auto dh = PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr); 13472c593315Sopenharmony_ci if (dh == nullptr) { 13482c593315Sopenharmony_ci LOG(FATAL) << "PEM_read_bio_DHparams() failed: " 13492c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 13502c593315Sopenharmony_ci DIE(); 13512c593315Sopenharmony_ci } 13522c593315Sopenharmony_ci SSL_CTX_set_tmp_dh(ssl_ctx, dh); 13532c593315Sopenharmony_ci DH_free(dh); 13542c593315Sopenharmony_ci# endif // !OPENSSL_3_0_0_API 13552c593315Sopenharmony_ci BIO_free(bio); 13562c593315Sopenharmony_ci } 13572c593315Sopenharmony_ci 13582c593315Sopenharmony_ci SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); 13592c593315Sopenharmony_ci 13602c593315Sopenharmony_ci if (SSL_CTX_set_default_verify_paths(ssl_ctx) != 1) { 13612c593315Sopenharmony_ci LOG(WARN) << "Could not load system trusted ca certificates: " 13622c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 13632c593315Sopenharmony_ci } 13642c593315Sopenharmony_ci 13652c593315Sopenharmony_ci if (!tlsconf.cacert.empty()) { 13662c593315Sopenharmony_ci if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.c_str(), 13672c593315Sopenharmony_ci nullptr) != 1) { 13682c593315Sopenharmony_ci LOG(FATAL) << "Could not load trusted ca certificates from " 13692c593315Sopenharmony_ci << tlsconf.cacert << ": " 13702c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 13712c593315Sopenharmony_ci DIE(); 13722c593315Sopenharmony_ci } 13732c593315Sopenharmony_ci } 13742c593315Sopenharmony_ci 13752c593315Sopenharmony_ci if (!tlsconf.private_key_passwd.empty()) { 13762c593315Sopenharmony_ci SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb); 13772c593315Sopenharmony_ci SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, config); 13782c593315Sopenharmony_ci } 13792c593315Sopenharmony_ci 13802c593315Sopenharmony_ci# ifndef HAVE_NEVERBLEED 13812c593315Sopenharmony_ci if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file, 13822c593315Sopenharmony_ci SSL_FILETYPE_PEM) != 1) { 13832c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_use_PrivateKey_file failed: " 13842c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 13852c593315Sopenharmony_ci DIE(); 13862c593315Sopenharmony_ci } 13872c593315Sopenharmony_ci# else // HAVE_NEVERBLEED 13882c593315Sopenharmony_ci std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf; 13892c593315Sopenharmony_ci if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file, 13902c593315Sopenharmony_ci errbuf.data()) != 1) { 13912c593315Sopenharmony_ci LOG(FATAL) << "neverbleed_load_private_key_file failed: " << errbuf.data(); 13922c593315Sopenharmony_ci DIE(); 13932c593315Sopenharmony_ci } 13942c593315Sopenharmony_ci# endif // HAVE_NEVERBLEED 13952c593315Sopenharmony_ci 13962c593315Sopenharmony_ci if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) { 13972c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_use_certificate_file failed: " 13982c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 13992c593315Sopenharmony_ci DIE(); 14002c593315Sopenharmony_ci } 14012c593315Sopenharmony_ci if (SSL_CTX_check_private_key(ssl_ctx) != 1) { 14022c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_check_private_key failed: " 14032c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 14042c593315Sopenharmony_ci DIE(); 14052c593315Sopenharmony_ci } 14062c593315Sopenharmony_ci if (tlsconf.client_verify.enabled) { 14072c593315Sopenharmony_ci if (!tlsconf.client_verify.cacert.empty()) { 14082c593315Sopenharmony_ci if (SSL_CTX_load_verify_locations( 14092c593315Sopenharmony_ci ssl_ctx, tlsconf.client_verify.cacert.c_str(), nullptr) != 1) { 14102c593315Sopenharmony_ci 14112c593315Sopenharmony_ci LOG(FATAL) << "Could not load trusted ca certificates from " 14122c593315Sopenharmony_ci << tlsconf.client_verify.cacert << ": " 14132c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 14142c593315Sopenharmony_ci DIE(); 14152c593315Sopenharmony_ci } 14162c593315Sopenharmony_ci // It is heard that SSL_CTX_load_verify_locations() may leave 14172c593315Sopenharmony_ci // error even though it returns success. See 14182c593315Sopenharmony_ci // http://forum.nginx.org/read.php?29,242540 14192c593315Sopenharmony_ci ERR_clear_error(); 14202c593315Sopenharmony_ci auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.c_str()); 14212c593315Sopenharmony_ci if (!list) { 14222c593315Sopenharmony_ci LOG(FATAL) << "Could not load ca certificates from " 14232c593315Sopenharmony_ci << tlsconf.client_verify.cacert << ": " 14242c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 14252c593315Sopenharmony_ci DIE(); 14262c593315Sopenharmony_ci } 14272c593315Sopenharmony_ci SSL_CTX_set_client_CA_list(ssl_ctx, list); 14282c593315Sopenharmony_ci } 14292c593315Sopenharmony_ci SSL_CTX_set_verify(ssl_ctx, 14302c593315Sopenharmony_ci SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | 14312c593315Sopenharmony_ci SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 14322c593315Sopenharmony_ci verify_callback); 14332c593315Sopenharmony_ci } 14342c593315Sopenharmony_ci SSL_CTX_set_tlsext_servername_callback(ssl_ctx, servername_callback); 14352c593315Sopenharmony_ci# if OPENSSL_3_0_0_API 14362c593315Sopenharmony_ci SSL_CTX_set_tlsext_ticket_key_evp_cb(ssl_ctx, ticket_key_cb); 14372c593315Sopenharmony_ci# else // !OPENSSL_3_0_0_API 14382c593315Sopenharmony_ci SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx, ticket_key_cb); 14392c593315Sopenharmony_ci# endif // !OPENSSL_3_0_0_API 14402c593315Sopenharmony_ci# ifndef OPENSSL_IS_BORINGSSL 14412c593315Sopenharmony_ci SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb); 14422c593315Sopenharmony_ci# endif // OPENSSL_IS_BORINGSSL 14432c593315Sopenharmony_ci 14442c593315Sopenharmony_ci# if OPENSSL_VERSION_NUMBER >= 0x10002000L 14452c593315Sopenharmony_ci // ALPN selection callback 14462c593315Sopenharmony_ci SSL_CTX_set_alpn_select_cb(ssl_ctx, quic_alpn_select_proto_cb, nullptr); 14472c593315Sopenharmony_ci# endif // OPENSSL_VERSION_NUMBER >= 0x10002000L 14482c593315Sopenharmony_ci 14492c593315Sopenharmony_ci auto tls_ctx_data = new TLSContextData(); 14502c593315Sopenharmony_ci tls_ctx_data->cert_file = cert_file; 14512c593315Sopenharmony_ci tls_ctx_data->sct_data = sct_data; 14522c593315Sopenharmony_ci 14532c593315Sopenharmony_ci SSL_CTX_set_app_data(ssl_ctx, tls_ctx_data); 14542c593315Sopenharmony_ci 14552c593315Sopenharmony_ci# if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L && \ 14562c593315Sopenharmony_ci !defined(OPENSSL_IS_BORINGSSL) 14572c593315Sopenharmony_ci // SSL_extension_supported(TLSEXT_TYPE_signed_certificate_timestamp) 14582c593315Sopenharmony_ci // returns 1, which means OpenSSL internally handles it. But 14592c593315Sopenharmony_ci // OpenSSL handles signed_certificate_timestamp extension specially, 14602c593315Sopenharmony_ci // and it lets custom handler to process the extension. 14612c593315Sopenharmony_ci if (!sct_data.empty()) { 14622c593315Sopenharmony_ci# if OPENSSL_1_1_1_API 14632c593315Sopenharmony_ci // It is not entirely clear to me that SSL_EXT_CLIENT_HELLO is 14642c593315Sopenharmony_ci // required here. sct_parse_cb is called without 14652c593315Sopenharmony_ci // SSL_EXT_CLIENT_HELLO being set. But the passed context value 14662c593315Sopenharmony_ci // is SSL_EXT_CLIENT_HELLO. 14672c593315Sopenharmony_ci if (SSL_CTX_add_custom_ext( 14682c593315Sopenharmony_ci ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp, 14692c593315Sopenharmony_ci SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO | 14702c593315Sopenharmony_ci SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_IGNORE_ON_RESUMPTION, 14712c593315Sopenharmony_ci sct_add_cb, sct_free_cb, nullptr, sct_parse_cb, nullptr) != 1) { 14722c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_add_custom_ext failed: " 14732c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 14742c593315Sopenharmony_ci DIE(); 14752c593315Sopenharmony_ci } 14762c593315Sopenharmony_ci# else // !OPENSSL_1_1_1_API 14772c593315Sopenharmony_ci if (SSL_CTX_add_server_custom_ext( 14782c593315Sopenharmony_ci ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp, 14792c593315Sopenharmony_ci legacy_sct_add_cb, legacy_sct_free_cb, nullptr, legacy_sct_parse_cb, 14802c593315Sopenharmony_ci nullptr) != 1) { 14812c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_add_server_custom_ext failed: " 14822c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 14832c593315Sopenharmony_ci DIE(); 14842c593315Sopenharmony_ci } 14852c593315Sopenharmony_ci# endif // !OPENSSL_1_1_1_API 14862c593315Sopenharmony_ci } 14872c593315Sopenharmony_ci# elif defined(OPENSSL_IS_BORINGSSL) 14882c593315Sopenharmony_ci if (!tls_ctx_data->sct_data.empty() && 14892c593315Sopenharmony_ci SSL_CTX_set_signed_cert_timestamp_list( 14902c593315Sopenharmony_ci ssl_ctx, tls_ctx_data->sct_data.data(), 14912c593315Sopenharmony_ci tls_ctx_data->sct_data.size()) != 1) { 14922c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_signed_cert_timestamp_list failed: " 14932c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 14942c593315Sopenharmony_ci DIE(); 14952c593315Sopenharmony_ci } 14962c593315Sopenharmony_ci# endif // defined(OPENSSL_IS_BORINGSSL) 14972c593315Sopenharmony_ci 14982c593315Sopenharmony_ci# if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 14992c593315Sopenharmony_ci auto &quicconf = config->quic; 15002c593315Sopenharmony_ci 15012c593315Sopenharmony_ci if (quicconf.upstream.early_data && 15022c593315Sopenharmony_ci SSL_CTX_set_max_early_data(ssl_ctx, 15032c593315Sopenharmony_ci std::numeric_limits<uint32_t>::max()) != 1) { 15042c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_max_early_data failed: " 15052c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 15062c593315Sopenharmony_ci DIE(); 15072c593315Sopenharmony_ci } 15082c593315Sopenharmony_ci# endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 15092c593315Sopenharmony_ci 15102c593315Sopenharmony_ci# ifndef OPENSSL_NO_PSK 15112c593315Sopenharmony_ci SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb); 15122c593315Sopenharmony_ci# endif // !LIBRESSL_NO_PSK 15132c593315Sopenharmony_ci 15142c593315Sopenharmony_ci return ssl_ctx; 15152c593315Sopenharmony_ci} 15162c593315Sopenharmony_ci#endif // ENABLE_HTTP3 15172c593315Sopenharmony_ci 15182c593315Sopenharmony_cinamespace { 15192c593315Sopenharmony_ciint select_h2_next_proto_cb(SSL *ssl, unsigned char **out, 15202c593315Sopenharmony_ci unsigned char *outlen, const unsigned char *in, 15212c593315Sopenharmony_ci unsigned int inlen, void *arg) { 15222c593315Sopenharmony_ci if (!util::select_h2(const_cast<const unsigned char **>(out), outlen, in, 15232c593315Sopenharmony_ci inlen)) { 15242c593315Sopenharmony_ci return SSL_TLSEXT_ERR_NOACK; 15252c593315Sopenharmony_ci } 15262c593315Sopenharmony_ci 15272c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 15282c593315Sopenharmony_ci} 15292c593315Sopenharmony_ci} // namespace 15302c593315Sopenharmony_ci 15312c593315Sopenharmony_cinamespace { 15322c593315Sopenharmony_ciint select_h1_next_proto_cb(SSL *ssl, unsigned char **out, 15332c593315Sopenharmony_ci unsigned char *outlen, const unsigned char *in, 15342c593315Sopenharmony_ci unsigned int inlen, void *arg) { 15352c593315Sopenharmony_ci auto end = in + inlen; 15362c593315Sopenharmony_ci for (; in < end;) { 15372c593315Sopenharmony_ci if (util::streq(NGHTTP2_H1_1_ALPN, StringRef{in, in + (in[0] + 1)})) { 15382c593315Sopenharmony_ci *out = const_cast<unsigned char *>(in) + 1; 15392c593315Sopenharmony_ci *outlen = in[0]; 15402c593315Sopenharmony_ci return SSL_TLSEXT_ERR_OK; 15412c593315Sopenharmony_ci } 15422c593315Sopenharmony_ci in += in[0] + 1; 15432c593315Sopenharmony_ci } 15442c593315Sopenharmony_ci 15452c593315Sopenharmony_ci return SSL_TLSEXT_ERR_NOACK; 15462c593315Sopenharmony_ci} 15472c593315Sopenharmony_ci} // namespace 15482c593315Sopenharmony_ci 15492c593315Sopenharmony_cinamespace { 15502c593315Sopenharmony_ciint select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen, 15512c593315Sopenharmony_ci const unsigned char *in, unsigned int inlen, 15522c593315Sopenharmony_ci void *arg) { 15532c593315Sopenharmony_ci auto conn = static_cast<Connection *>(SSL_get_app_data(ssl)); 15542c593315Sopenharmony_ci switch (conn->proto) { 15552c593315Sopenharmony_ci case Proto::HTTP1: 15562c593315Sopenharmony_ci return select_h1_next_proto_cb(ssl, out, outlen, in, inlen, arg); 15572c593315Sopenharmony_ci case Proto::HTTP2: 15582c593315Sopenharmony_ci return select_h2_next_proto_cb(ssl, out, outlen, in, inlen, arg); 15592c593315Sopenharmony_ci default: 15602c593315Sopenharmony_ci return SSL_TLSEXT_ERR_NOACK; 15612c593315Sopenharmony_ci } 15622c593315Sopenharmony_ci} 15632c593315Sopenharmony_ci} // namespace 15642c593315Sopenharmony_ci 15652c593315Sopenharmony_ciSSL_CTX *create_ssl_client_context( 15662c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 15672c593315Sopenharmony_ci neverbleed_t *nb, 15682c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 15692c593315Sopenharmony_ci const StringRef &cacert, const StringRef &cert_file, 15702c593315Sopenharmony_ci const StringRef &private_key_file, 15712c593315Sopenharmony_ci int (*next_proto_select_cb)(SSL *s, unsigned char **out, 15722c593315Sopenharmony_ci unsigned char *outlen, const unsigned char *in, 15732c593315Sopenharmony_ci unsigned int inlen, void *arg)) { 15742c593315Sopenharmony_ci auto ssl_ctx = SSL_CTX_new(TLS_client_method()); 15752c593315Sopenharmony_ci if (!ssl_ctx) { 15762c593315Sopenharmony_ci LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr); 15772c593315Sopenharmony_ci DIE(); 15782c593315Sopenharmony_ci } 15792c593315Sopenharmony_ci 15802c593315Sopenharmony_ci auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | 15812c593315Sopenharmony_ci SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION | 15822c593315Sopenharmony_ci SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; 15832c593315Sopenharmony_ci 15842c593315Sopenharmony_ci auto &tlsconf = get_config()->tls; 15852c593315Sopenharmony_ci 15862c593315Sopenharmony_ci#ifdef SSL_OP_ENABLE_KTLS 15872c593315Sopenharmony_ci if (tlsconf.ktls) { 15882c593315Sopenharmony_ci ssl_opts |= SSL_OP_ENABLE_KTLS; 15892c593315Sopenharmony_ci } 15902c593315Sopenharmony_ci#endif // SSL_OP_ENABLE_KTLS 15912c593315Sopenharmony_ci 15922c593315Sopenharmony_ci SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask); 15932c593315Sopenharmony_ci 15942c593315Sopenharmony_ci SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_CLIENT | 15952c593315Sopenharmony_ci SSL_SESS_CACHE_NO_INTERNAL_STORE); 15962c593315Sopenharmony_ci SSL_CTX_sess_set_new_cb(ssl_ctx, tls_session_client_new_cb); 15972c593315Sopenharmony_ci 15982c593315Sopenharmony_ci if (nghttp2::tls::ssl_ctx_set_proto_versions( 15992c593315Sopenharmony_ci ssl_ctx, tlsconf.min_proto_version, tlsconf.max_proto_version) != 0) { 16002c593315Sopenharmony_ci LOG(FATAL) << "Could not set TLS protocol version"; 16012c593315Sopenharmony_ci DIE(); 16022c593315Sopenharmony_ci } 16032c593315Sopenharmony_ci 16042c593315Sopenharmony_ci if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.client.ciphers.c_str()) == 0) { 16052c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_cipher_list " << tlsconf.client.ciphers 16062c593315Sopenharmony_ci << " failed: " << ERR_error_string(ERR_get_error(), nullptr); 16072c593315Sopenharmony_ci DIE(); 16082c593315Sopenharmony_ci } 16092c593315Sopenharmony_ci 16102c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 16112c593315Sopenharmony_ci if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.client.tls13_ciphers.c_str()) == 16122c593315Sopenharmony_ci 0) { 16132c593315Sopenharmony_ci LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.client.tls13_ciphers 16142c593315Sopenharmony_ci << " failed: " << ERR_error_string(ERR_get_error(), nullptr); 16152c593315Sopenharmony_ci DIE(); 16162c593315Sopenharmony_ci } 16172c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 16182c593315Sopenharmony_ci 16192c593315Sopenharmony_ci SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); 16202c593315Sopenharmony_ci 16212c593315Sopenharmony_ci if (SSL_CTX_set_default_verify_paths(ssl_ctx) != 1) { 16222c593315Sopenharmony_ci LOG(WARN) << "Could not load system trusted ca certificates: " 16232c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 16242c593315Sopenharmony_ci } 16252c593315Sopenharmony_ci 16262c593315Sopenharmony_ci if (!cacert.empty()) { 16272c593315Sopenharmony_ci if (SSL_CTX_load_verify_locations(ssl_ctx, cacert.c_str(), nullptr) != 1) { 16282c593315Sopenharmony_ci 16292c593315Sopenharmony_ci LOG(FATAL) << "Could not load trusted ca certificates from " << cacert 16302c593315Sopenharmony_ci << ": " << ERR_error_string(ERR_get_error(), nullptr); 16312c593315Sopenharmony_ci DIE(); 16322c593315Sopenharmony_ci } 16332c593315Sopenharmony_ci } 16342c593315Sopenharmony_ci 16352c593315Sopenharmony_ci if (!tlsconf.insecure) { 16362c593315Sopenharmony_ci SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, nullptr); 16372c593315Sopenharmony_ci } 16382c593315Sopenharmony_ci 16392c593315Sopenharmony_ci if (!cert_file.empty()) { 16402c593315Sopenharmony_ci if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file.c_str()) != 1) { 16412c593315Sopenharmony_ci 16422c593315Sopenharmony_ci LOG(FATAL) << "Could not load client certificate from " << cert_file 16432c593315Sopenharmony_ci << ": " << ERR_error_string(ERR_get_error(), nullptr); 16442c593315Sopenharmony_ci DIE(); 16452c593315Sopenharmony_ci } 16462c593315Sopenharmony_ci } 16472c593315Sopenharmony_ci 16482c593315Sopenharmony_ci if (!private_key_file.empty()) { 16492c593315Sopenharmony_ci#ifndef HAVE_NEVERBLEED 16502c593315Sopenharmony_ci if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file.c_str(), 16512c593315Sopenharmony_ci SSL_FILETYPE_PEM) != 1) { 16522c593315Sopenharmony_ci LOG(FATAL) << "Could not load client private key from " 16532c593315Sopenharmony_ci << private_key_file << ": " 16542c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 16552c593315Sopenharmony_ci DIE(); 16562c593315Sopenharmony_ci } 16572c593315Sopenharmony_ci#else // HAVE_NEVERBLEED 16582c593315Sopenharmony_ci std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf; 16592c593315Sopenharmony_ci if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file.c_str(), 16602c593315Sopenharmony_ci errbuf.data()) != 1) { 16612c593315Sopenharmony_ci LOG(FATAL) << "neverbleed_load_private_key_file: could not load client " 16622c593315Sopenharmony_ci "private key from " 16632c593315Sopenharmony_ci << private_key_file << ": " << errbuf.data(); 16642c593315Sopenharmony_ci DIE(); 16652c593315Sopenharmony_ci } 16662c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 16672c593315Sopenharmony_ci } 16682c593315Sopenharmony_ci 16692c593315Sopenharmony_ci#ifndef OPENSSL_NO_PSK 16702c593315Sopenharmony_ci SSL_CTX_set_psk_client_callback(ssl_ctx, psk_client_cb); 16712c593315Sopenharmony_ci#endif // !OPENSSL_NO_PSK 16722c593315Sopenharmony_ci 16732c593315Sopenharmony_ci // NPN selection callback. This is required to set SSL_CTX because 16742c593315Sopenharmony_ci // OpenSSL does not offer SSL_set_next_proto_select_cb. 16752c593315Sopenharmony_ci#ifndef OPENSSL_NO_NEXTPROTONEG 16762c593315Sopenharmony_ci SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_cb, nullptr); 16772c593315Sopenharmony_ci#endif // !OPENSSL_NO_NEXTPROTONEG 16782c593315Sopenharmony_ci 16792c593315Sopenharmony_ci return ssl_ctx; 16802c593315Sopenharmony_ci} 16812c593315Sopenharmony_ci 16822c593315Sopenharmony_ciSSL *create_ssl(SSL_CTX *ssl_ctx) { 16832c593315Sopenharmony_ci auto ssl = SSL_new(ssl_ctx); 16842c593315Sopenharmony_ci if (!ssl) { 16852c593315Sopenharmony_ci LOG(ERROR) << "SSL_new() failed: " 16862c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 16872c593315Sopenharmony_ci return nullptr; 16882c593315Sopenharmony_ci } 16892c593315Sopenharmony_ci 16902c593315Sopenharmony_ci return ssl; 16912c593315Sopenharmony_ci} 16922c593315Sopenharmony_ci 16932c593315Sopenharmony_ciClientHandler *accept_connection(Worker *worker, int fd, sockaddr *addr, 16942c593315Sopenharmony_ci int addrlen, const UpstreamAddr *faddr) { 16952c593315Sopenharmony_ci std::array<char, NI_MAXHOST> host; 16962c593315Sopenharmony_ci std::array<char, NI_MAXSERV> service; 16972c593315Sopenharmony_ci int rv; 16982c593315Sopenharmony_ci 16992c593315Sopenharmony_ci if (addr->sa_family == AF_UNIX) { 17002c593315Sopenharmony_ci std::copy_n("localhost", sizeof("localhost"), std::begin(host)); 17012c593315Sopenharmony_ci service[0] = '\0'; 17022c593315Sopenharmony_ci } else { 17032c593315Sopenharmony_ci rv = getnameinfo(addr, addrlen, host.data(), host.size(), service.data(), 17042c593315Sopenharmony_ci service.size(), NI_NUMERICHOST | NI_NUMERICSERV); 17052c593315Sopenharmony_ci if (rv != 0) { 17062c593315Sopenharmony_ci LOG(ERROR) << "getnameinfo() failed: " << gai_strerror(rv); 17072c593315Sopenharmony_ci 17082c593315Sopenharmony_ci return nullptr; 17092c593315Sopenharmony_ci } 17102c593315Sopenharmony_ci 17112c593315Sopenharmony_ci rv = util::make_socket_nodelay(fd); 17122c593315Sopenharmony_ci if (rv == -1) { 17132c593315Sopenharmony_ci LOG(WARN) << "Setting option TCP_NODELAY failed: errno=" << errno; 17142c593315Sopenharmony_ci } 17152c593315Sopenharmony_ci } 17162c593315Sopenharmony_ci SSL *ssl = nullptr; 17172c593315Sopenharmony_ci if (faddr->tls) { 17182c593315Sopenharmony_ci auto ssl_ctx = worker->get_sv_ssl_ctx(); 17192c593315Sopenharmony_ci 17202c593315Sopenharmony_ci assert(ssl_ctx); 17212c593315Sopenharmony_ci 17222c593315Sopenharmony_ci ssl = create_ssl(ssl_ctx); 17232c593315Sopenharmony_ci if (!ssl) { 17242c593315Sopenharmony_ci return nullptr; 17252c593315Sopenharmony_ci } 17262c593315Sopenharmony_ci // Disable TLS session ticket if we don't have working ticket 17272c593315Sopenharmony_ci // keys. 17282c593315Sopenharmony_ci if (!worker->get_ticket_keys()) { 17292c593315Sopenharmony_ci SSL_set_options(ssl, SSL_OP_NO_TICKET); 17302c593315Sopenharmony_ci } 17312c593315Sopenharmony_ci } 17322c593315Sopenharmony_ci 17332c593315Sopenharmony_ci return new ClientHandler(worker, fd, ssl, StringRef{host.data()}, 17342c593315Sopenharmony_ci StringRef{service.data()}, addr->sa_family, faddr); 17352c593315Sopenharmony_ci} 17362c593315Sopenharmony_ci 17372c593315Sopenharmony_cibool tls_hostname_match(const StringRef &pattern, const StringRef &hostname) { 17382c593315Sopenharmony_ci auto ptWildcard = std::find(std::begin(pattern), std::end(pattern), '*'); 17392c593315Sopenharmony_ci if (ptWildcard == std::end(pattern)) { 17402c593315Sopenharmony_ci return util::strieq(pattern, hostname); 17412c593315Sopenharmony_ci } 17422c593315Sopenharmony_ci 17432c593315Sopenharmony_ci auto ptLeftLabelEnd = std::find(std::begin(pattern), std::end(pattern), '.'); 17442c593315Sopenharmony_ci auto wildcardEnabled = true; 17452c593315Sopenharmony_ci // Do case-insensitive match. At least 2 dots are required to enable 17462c593315Sopenharmony_ci // wildcard match. Also wildcard must be in the left-most label. 17472c593315Sopenharmony_ci // Don't attempt to match a presented identifier where the wildcard 17482c593315Sopenharmony_ci // character is embedded within an A-label. 17492c593315Sopenharmony_ci if (ptLeftLabelEnd == std::end(pattern) || 17502c593315Sopenharmony_ci std::find(ptLeftLabelEnd + 1, std::end(pattern), '.') == 17512c593315Sopenharmony_ci std::end(pattern) || 17522c593315Sopenharmony_ci ptLeftLabelEnd < ptWildcard || util::istarts_with_l(pattern, "xn--")) { 17532c593315Sopenharmony_ci wildcardEnabled = false; 17542c593315Sopenharmony_ci } 17552c593315Sopenharmony_ci 17562c593315Sopenharmony_ci if (!wildcardEnabled) { 17572c593315Sopenharmony_ci return util::strieq(pattern, hostname); 17582c593315Sopenharmony_ci } 17592c593315Sopenharmony_ci 17602c593315Sopenharmony_ci auto hnLeftLabelEnd = 17612c593315Sopenharmony_ci std::find(std::begin(hostname), std::end(hostname), '.'); 17622c593315Sopenharmony_ci if (hnLeftLabelEnd == std::end(hostname) || 17632c593315Sopenharmony_ci !util::strieq(StringRef{ptLeftLabelEnd, std::end(pattern)}, 17642c593315Sopenharmony_ci StringRef{hnLeftLabelEnd, std::end(hostname)})) { 17652c593315Sopenharmony_ci return false; 17662c593315Sopenharmony_ci } 17672c593315Sopenharmony_ci // Perform wildcard match. Here '*' must match at least one 17682c593315Sopenharmony_ci // character. 17692c593315Sopenharmony_ci if (hnLeftLabelEnd - std::begin(hostname) < 17702c593315Sopenharmony_ci ptLeftLabelEnd - std::begin(pattern)) { 17712c593315Sopenharmony_ci return false; 17722c593315Sopenharmony_ci } 17732c593315Sopenharmony_ci return util::istarts_with(StringRef{std::begin(hostname), hnLeftLabelEnd}, 17742c593315Sopenharmony_ci StringRef{std::begin(pattern), ptWildcard}) && 17752c593315Sopenharmony_ci util::iends_with(StringRef{std::begin(hostname), hnLeftLabelEnd}, 17762c593315Sopenharmony_ci StringRef{ptWildcard + 1, ptLeftLabelEnd}); 17772c593315Sopenharmony_ci} 17782c593315Sopenharmony_ci 17792c593315Sopenharmony_cinamespace { 17802c593315Sopenharmony_ci// if return value is not empty, StringRef.c_str() must be freed using 17812c593315Sopenharmony_ci// OPENSSL_free(). 17822c593315Sopenharmony_ciStringRef get_common_name(X509 *cert) { 17832c593315Sopenharmony_ci auto subjectname = X509_get_subject_name(cert); 17842c593315Sopenharmony_ci if (!subjectname) { 17852c593315Sopenharmony_ci LOG(WARN) << "Could not get X509 name object from the certificate."; 17862c593315Sopenharmony_ci return StringRef{}; 17872c593315Sopenharmony_ci } 17882c593315Sopenharmony_ci int lastpos = -1; 17892c593315Sopenharmony_ci for (;;) { 17902c593315Sopenharmony_ci lastpos = X509_NAME_get_index_by_NID(subjectname, NID_commonName, lastpos); 17912c593315Sopenharmony_ci if (lastpos == -1) { 17922c593315Sopenharmony_ci break; 17932c593315Sopenharmony_ci } 17942c593315Sopenharmony_ci auto entry = X509_NAME_get_entry(subjectname, lastpos); 17952c593315Sopenharmony_ci 17962c593315Sopenharmony_ci unsigned char *p; 17972c593315Sopenharmony_ci auto plen = ASN1_STRING_to_UTF8(&p, X509_NAME_ENTRY_get_data(entry)); 17982c593315Sopenharmony_ci if (plen < 0) { 17992c593315Sopenharmony_ci continue; 18002c593315Sopenharmony_ci } 18012c593315Sopenharmony_ci if (std::find(p, p + plen, '\0') != p + plen) { 18022c593315Sopenharmony_ci // Embedded NULL is not permitted. 18032c593315Sopenharmony_ci continue; 18042c593315Sopenharmony_ci } 18052c593315Sopenharmony_ci if (plen == 0) { 18062c593315Sopenharmony_ci LOG(WARN) << "X509 name is empty"; 18072c593315Sopenharmony_ci OPENSSL_free(p); 18082c593315Sopenharmony_ci continue; 18092c593315Sopenharmony_ci } 18102c593315Sopenharmony_ci 18112c593315Sopenharmony_ci return StringRef{p, static_cast<size_t>(plen)}; 18122c593315Sopenharmony_ci } 18132c593315Sopenharmony_ci return StringRef{}; 18142c593315Sopenharmony_ci} 18152c593315Sopenharmony_ci} // namespace 18162c593315Sopenharmony_ci 18172c593315Sopenharmony_ciint verify_numeric_hostname(X509 *cert, const StringRef &hostname, 18182c593315Sopenharmony_ci const Address *addr) { 18192c593315Sopenharmony_ci const void *saddr; 18202c593315Sopenharmony_ci size_t saddrlen; 18212c593315Sopenharmony_ci switch (addr->su.storage.ss_family) { 18222c593315Sopenharmony_ci case AF_INET: 18232c593315Sopenharmony_ci saddr = &addr->su.in.sin_addr; 18242c593315Sopenharmony_ci saddrlen = sizeof(addr->su.in.sin_addr); 18252c593315Sopenharmony_ci break; 18262c593315Sopenharmony_ci case AF_INET6: 18272c593315Sopenharmony_ci saddr = &addr->su.in6.sin6_addr; 18282c593315Sopenharmony_ci saddrlen = sizeof(addr->su.in6.sin6_addr); 18292c593315Sopenharmony_ci break; 18302c593315Sopenharmony_ci default: 18312c593315Sopenharmony_ci return -1; 18322c593315Sopenharmony_ci } 18332c593315Sopenharmony_ci 18342c593315Sopenharmony_ci auto altnames = static_cast<GENERAL_NAMES *>( 18352c593315Sopenharmony_ci X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); 18362c593315Sopenharmony_ci if (altnames) { 18372c593315Sopenharmony_ci auto altnames_deleter = defer(GENERAL_NAMES_free, altnames); 18382c593315Sopenharmony_ci size_t n = sk_GENERAL_NAME_num(altnames); 18392c593315Sopenharmony_ci auto ip_found = false; 18402c593315Sopenharmony_ci for (size_t i = 0; i < n; ++i) { 18412c593315Sopenharmony_ci auto altname = sk_GENERAL_NAME_value(altnames, i); 18422c593315Sopenharmony_ci if (altname->type != GEN_IPADD) { 18432c593315Sopenharmony_ci continue; 18442c593315Sopenharmony_ci } 18452c593315Sopenharmony_ci 18462c593315Sopenharmony_ci auto ip_addr = altname->d.iPAddress->data; 18472c593315Sopenharmony_ci if (!ip_addr) { 18482c593315Sopenharmony_ci continue; 18492c593315Sopenharmony_ci } 18502c593315Sopenharmony_ci size_t ip_addrlen = altname->d.iPAddress->length; 18512c593315Sopenharmony_ci 18522c593315Sopenharmony_ci ip_found = true; 18532c593315Sopenharmony_ci if (saddrlen == ip_addrlen && memcmp(saddr, ip_addr, ip_addrlen) == 0) { 18542c593315Sopenharmony_ci return 0; 18552c593315Sopenharmony_ci } 18562c593315Sopenharmony_ci } 18572c593315Sopenharmony_ci 18582c593315Sopenharmony_ci if (ip_found) { 18592c593315Sopenharmony_ci return -1; 18602c593315Sopenharmony_ci } 18612c593315Sopenharmony_ci } 18622c593315Sopenharmony_ci 18632c593315Sopenharmony_ci auto cn = get_common_name(cert); 18642c593315Sopenharmony_ci if (cn.empty()) { 18652c593315Sopenharmony_ci return -1; 18662c593315Sopenharmony_ci } 18672c593315Sopenharmony_ci 18682c593315Sopenharmony_ci // cn is not NULL terminated 18692c593315Sopenharmony_ci auto rv = util::streq(hostname, cn); 18702c593315Sopenharmony_ci OPENSSL_free(const_cast<char *>(cn.c_str())); 18712c593315Sopenharmony_ci 18722c593315Sopenharmony_ci if (rv) { 18732c593315Sopenharmony_ci return 0; 18742c593315Sopenharmony_ci } 18752c593315Sopenharmony_ci 18762c593315Sopenharmony_ci return -1; 18772c593315Sopenharmony_ci} 18782c593315Sopenharmony_ci 18792c593315Sopenharmony_ciint verify_dns_hostname(X509 *cert, const StringRef &hostname) { 18802c593315Sopenharmony_ci auto altnames = static_cast<GENERAL_NAMES *>( 18812c593315Sopenharmony_ci X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); 18822c593315Sopenharmony_ci if (altnames) { 18832c593315Sopenharmony_ci auto dns_found = false; 18842c593315Sopenharmony_ci auto altnames_deleter = defer(GENERAL_NAMES_free, altnames); 18852c593315Sopenharmony_ci size_t n = sk_GENERAL_NAME_num(altnames); 18862c593315Sopenharmony_ci for (size_t i = 0; i < n; ++i) { 18872c593315Sopenharmony_ci auto altname = sk_GENERAL_NAME_value(altnames, i); 18882c593315Sopenharmony_ci if (altname->type != GEN_DNS) { 18892c593315Sopenharmony_ci continue; 18902c593315Sopenharmony_ci } 18912c593315Sopenharmony_ci 18922c593315Sopenharmony_ci auto name = ASN1_STRING_get0_data(altname->d.ia5); 18932c593315Sopenharmony_ci if (!name) { 18942c593315Sopenharmony_ci continue; 18952c593315Sopenharmony_ci } 18962c593315Sopenharmony_ci 18972c593315Sopenharmony_ci auto len = ASN1_STRING_length(altname->d.ia5); 18982c593315Sopenharmony_ci if (len == 0) { 18992c593315Sopenharmony_ci continue; 19002c593315Sopenharmony_ci } 19012c593315Sopenharmony_ci if (std::find(name, name + len, '\0') != name + len) { 19022c593315Sopenharmony_ci // Embedded NULL is not permitted. 19032c593315Sopenharmony_ci continue; 19042c593315Sopenharmony_ci } 19052c593315Sopenharmony_ci 19062c593315Sopenharmony_ci if (name[len - 1] == '.') { 19072c593315Sopenharmony_ci --len; 19082c593315Sopenharmony_ci if (len == 0) { 19092c593315Sopenharmony_ci continue; 19102c593315Sopenharmony_ci } 19112c593315Sopenharmony_ci } 19122c593315Sopenharmony_ci 19132c593315Sopenharmony_ci dns_found = true; 19142c593315Sopenharmony_ci 19152c593315Sopenharmony_ci if (tls_hostname_match(StringRef{name, static_cast<size_t>(len)}, 19162c593315Sopenharmony_ci hostname)) { 19172c593315Sopenharmony_ci return 0; 19182c593315Sopenharmony_ci } 19192c593315Sopenharmony_ci } 19202c593315Sopenharmony_ci 19212c593315Sopenharmony_ci // RFC 6125, section 6.4.4. says that client MUST not seek a match 19222c593315Sopenharmony_ci // for CN if a dns dNSName is found. 19232c593315Sopenharmony_ci if (dns_found) { 19242c593315Sopenharmony_ci return -1; 19252c593315Sopenharmony_ci } 19262c593315Sopenharmony_ci } 19272c593315Sopenharmony_ci 19282c593315Sopenharmony_ci auto cn = get_common_name(cert); 19292c593315Sopenharmony_ci if (cn.empty()) { 19302c593315Sopenharmony_ci return -1; 19312c593315Sopenharmony_ci } 19322c593315Sopenharmony_ci 19332c593315Sopenharmony_ci if (cn[cn.size() - 1] == '.') { 19342c593315Sopenharmony_ci if (cn.size() == 1) { 19352c593315Sopenharmony_ci OPENSSL_free(const_cast<char *>(cn.c_str())); 19362c593315Sopenharmony_ci 19372c593315Sopenharmony_ci return -1; 19382c593315Sopenharmony_ci } 19392c593315Sopenharmony_ci cn = StringRef{cn.c_str(), cn.size() - 1}; 19402c593315Sopenharmony_ci } 19412c593315Sopenharmony_ci 19422c593315Sopenharmony_ci auto rv = tls_hostname_match(cn, hostname); 19432c593315Sopenharmony_ci OPENSSL_free(const_cast<char *>(cn.c_str())); 19442c593315Sopenharmony_ci 19452c593315Sopenharmony_ci return rv ? 0 : -1; 19462c593315Sopenharmony_ci} 19472c593315Sopenharmony_ci 19482c593315Sopenharmony_cinamespace { 19492c593315Sopenharmony_ciint verify_hostname(X509 *cert, const StringRef &hostname, 19502c593315Sopenharmony_ci const Address *addr) { 19512c593315Sopenharmony_ci if (util::numeric_host(hostname.c_str())) { 19522c593315Sopenharmony_ci return verify_numeric_hostname(cert, hostname, addr); 19532c593315Sopenharmony_ci } 19542c593315Sopenharmony_ci 19552c593315Sopenharmony_ci return verify_dns_hostname(cert, hostname); 19562c593315Sopenharmony_ci} 19572c593315Sopenharmony_ci} // namespace 19582c593315Sopenharmony_ci 19592c593315Sopenharmony_ciint check_cert(SSL *ssl, const Address *addr, const StringRef &host) { 19602c593315Sopenharmony_ci#if OPENSSL_3_0_0_API 19612c593315Sopenharmony_ci auto cert = SSL_get0_peer_certificate(ssl); 19622c593315Sopenharmony_ci#else // !OPENSSL_3_0_0_API 19632c593315Sopenharmony_ci auto cert = SSL_get_peer_certificate(ssl); 19642c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API 19652c593315Sopenharmony_ci if (!cert) { 19662c593315Sopenharmony_ci // By the protocol definition, TLS server always sends certificate 19672c593315Sopenharmony_ci // if it has. If certificate cannot be retrieved, authentication 19682c593315Sopenharmony_ci // without certificate is used, such as PSK. 19692c593315Sopenharmony_ci return 0; 19702c593315Sopenharmony_ci } 19712c593315Sopenharmony_ci#if !OPENSSL_3_0_0_API 19722c593315Sopenharmony_ci auto cert_deleter = defer(X509_free, cert); 19732c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API 19742c593315Sopenharmony_ci 19752c593315Sopenharmony_ci if (verify_hostname(cert, host, addr) != 0) { 19762c593315Sopenharmony_ci LOG(ERROR) << "Certificate verification failed: hostname does not match"; 19772c593315Sopenharmony_ci return -1; 19782c593315Sopenharmony_ci } 19792c593315Sopenharmony_ci return 0; 19802c593315Sopenharmony_ci} 19812c593315Sopenharmony_ci 19822c593315Sopenharmony_ciint check_cert(SSL *ssl, const DownstreamAddr *addr, const Address *raddr) { 19832c593315Sopenharmony_ci auto hostname = 19842c593315Sopenharmony_ci addr->sni.empty() ? StringRef{addr->host} : StringRef{addr->sni}; 19852c593315Sopenharmony_ci return check_cert(ssl, raddr, hostname); 19862c593315Sopenharmony_ci} 19872c593315Sopenharmony_ci 19882c593315Sopenharmony_ciCertLookupTree::CertLookupTree() {} 19892c593315Sopenharmony_ci 19902c593315Sopenharmony_cissize_t CertLookupTree::add_cert(const StringRef &hostname, size_t idx) { 19912c593315Sopenharmony_ci std::array<uint8_t, NI_MAXHOST> buf; 19922c593315Sopenharmony_ci 19932c593315Sopenharmony_ci // NI_MAXHOST includes terminal NULL byte 19942c593315Sopenharmony_ci if (hostname.empty() || hostname.size() + 1 > buf.size()) { 19952c593315Sopenharmony_ci return -1; 19962c593315Sopenharmony_ci } 19972c593315Sopenharmony_ci 19982c593315Sopenharmony_ci auto wildcard_it = std::find(std::begin(hostname), std::end(hostname), '*'); 19992c593315Sopenharmony_ci if (wildcard_it != std::end(hostname) && 20002c593315Sopenharmony_ci wildcard_it + 1 != std::end(hostname)) { 20012c593315Sopenharmony_ci auto wildcard_prefix = StringRef{std::begin(hostname), wildcard_it}; 20022c593315Sopenharmony_ci auto wildcard_suffix = StringRef{wildcard_it + 1, std::end(hostname)}; 20032c593315Sopenharmony_ci 20042c593315Sopenharmony_ci auto rev_suffix = StringRef{std::begin(buf), 20052c593315Sopenharmony_ci std::reverse_copy(std::begin(wildcard_suffix), 20062c593315Sopenharmony_ci std::end(wildcard_suffix), 20072c593315Sopenharmony_ci std::begin(buf))}; 20082c593315Sopenharmony_ci 20092c593315Sopenharmony_ci WildcardPattern *wpat; 20102c593315Sopenharmony_ci 20112c593315Sopenharmony_ci if (wildcard_patterns_.size() != 20122c593315Sopenharmony_ci rev_wildcard_router_.add_route(rev_suffix, wildcard_patterns_.size())) { 20132c593315Sopenharmony_ci auto wcidx = rev_wildcard_router_.match(rev_suffix); 20142c593315Sopenharmony_ci 20152c593315Sopenharmony_ci assert(wcidx != -1); 20162c593315Sopenharmony_ci 20172c593315Sopenharmony_ci wpat = &wildcard_patterns_[wcidx]; 20182c593315Sopenharmony_ci } else { 20192c593315Sopenharmony_ci wildcard_patterns_.emplace_back(); 20202c593315Sopenharmony_ci wpat = &wildcard_patterns_.back(); 20212c593315Sopenharmony_ci } 20222c593315Sopenharmony_ci 20232c593315Sopenharmony_ci auto rev_prefix = StringRef{std::begin(buf), 20242c593315Sopenharmony_ci std::reverse_copy(std::begin(wildcard_prefix), 20252c593315Sopenharmony_ci std::end(wildcard_prefix), 20262c593315Sopenharmony_ci std::begin(buf))}; 20272c593315Sopenharmony_ci 20282c593315Sopenharmony_ci for (auto &p : wpat->rev_prefix) { 20292c593315Sopenharmony_ci if (p.prefix == rev_prefix) { 20302c593315Sopenharmony_ci return p.idx; 20312c593315Sopenharmony_ci } 20322c593315Sopenharmony_ci } 20332c593315Sopenharmony_ci 20342c593315Sopenharmony_ci wpat->rev_prefix.emplace_back(rev_prefix, idx); 20352c593315Sopenharmony_ci 20362c593315Sopenharmony_ci return idx; 20372c593315Sopenharmony_ci } 20382c593315Sopenharmony_ci 20392c593315Sopenharmony_ci return router_.add_route(hostname, idx); 20402c593315Sopenharmony_ci} 20412c593315Sopenharmony_ci 20422c593315Sopenharmony_cissize_t CertLookupTree::lookup(const StringRef &hostname) { 20432c593315Sopenharmony_ci std::array<uint8_t, NI_MAXHOST> buf; 20442c593315Sopenharmony_ci 20452c593315Sopenharmony_ci // NI_MAXHOST includes terminal NULL byte 20462c593315Sopenharmony_ci if (hostname.empty() || hostname.size() + 1 > buf.size()) { 20472c593315Sopenharmony_ci return -1; 20482c593315Sopenharmony_ci } 20492c593315Sopenharmony_ci 20502c593315Sopenharmony_ci // Always prefer exact match 20512c593315Sopenharmony_ci auto idx = router_.match(hostname); 20522c593315Sopenharmony_ci if (idx != -1) { 20532c593315Sopenharmony_ci return idx; 20542c593315Sopenharmony_ci } 20552c593315Sopenharmony_ci 20562c593315Sopenharmony_ci if (wildcard_patterns_.empty()) { 20572c593315Sopenharmony_ci return -1; 20582c593315Sopenharmony_ci } 20592c593315Sopenharmony_ci 20602c593315Sopenharmony_ci ssize_t best_idx = -1; 20612c593315Sopenharmony_ci size_t best_prefixlen = 0; 20622c593315Sopenharmony_ci const RNode *last_node = nullptr; 20632c593315Sopenharmony_ci 20642c593315Sopenharmony_ci auto rev_host = StringRef{ 20652c593315Sopenharmony_ci std::begin(buf), std::reverse_copy(std::begin(hostname), 20662c593315Sopenharmony_ci std::end(hostname), std::begin(buf))}; 20672c593315Sopenharmony_ci 20682c593315Sopenharmony_ci for (;;) { 20692c593315Sopenharmony_ci size_t nread = 0; 20702c593315Sopenharmony_ci 20712c593315Sopenharmony_ci auto wcidx = 20722c593315Sopenharmony_ci rev_wildcard_router_.match_prefix(&nread, &last_node, rev_host); 20732c593315Sopenharmony_ci if (wcidx == -1) { 20742c593315Sopenharmony_ci return best_idx; 20752c593315Sopenharmony_ci } 20762c593315Sopenharmony_ci 20772c593315Sopenharmony_ci // '*' must match at least one byte 20782c593315Sopenharmony_ci if (nread == rev_host.size()) { 20792c593315Sopenharmony_ci return best_idx; 20802c593315Sopenharmony_ci } 20812c593315Sopenharmony_ci 20822c593315Sopenharmony_ci rev_host = StringRef{std::begin(rev_host) + nread, std::end(rev_host)}; 20832c593315Sopenharmony_ci 20842c593315Sopenharmony_ci auto rev_prefix = StringRef{std::begin(rev_host) + 1, std::end(rev_host)}; 20852c593315Sopenharmony_ci 20862c593315Sopenharmony_ci auto &wpat = wildcard_patterns_[wcidx]; 20872c593315Sopenharmony_ci for (auto &wprefix : wpat.rev_prefix) { 20882c593315Sopenharmony_ci if (!util::ends_with(rev_prefix, wprefix.prefix)) { 20892c593315Sopenharmony_ci continue; 20902c593315Sopenharmony_ci } 20912c593315Sopenharmony_ci 20922c593315Sopenharmony_ci auto prefixlen = 20932c593315Sopenharmony_ci wprefix.prefix.size() + 20942c593315Sopenharmony_ci (reinterpret_cast<const uint8_t *>(&rev_host[0]) - &buf[0]); 20952c593315Sopenharmony_ci 20962c593315Sopenharmony_ci // Breaking a tie with longer suffix 20972c593315Sopenharmony_ci if (prefixlen < best_prefixlen) { 20982c593315Sopenharmony_ci continue; 20992c593315Sopenharmony_ci } 21002c593315Sopenharmony_ci 21012c593315Sopenharmony_ci best_idx = wprefix.idx; 21022c593315Sopenharmony_ci best_prefixlen = prefixlen; 21032c593315Sopenharmony_ci } 21042c593315Sopenharmony_ci } 21052c593315Sopenharmony_ci} 21062c593315Sopenharmony_ci 21072c593315Sopenharmony_civoid CertLookupTree::dump() const { 21082c593315Sopenharmony_ci std::cerr << "exact:" << std::endl; 21092c593315Sopenharmony_ci router_.dump(); 21102c593315Sopenharmony_ci std::cerr << "wildcard suffix (reversed):" << std::endl; 21112c593315Sopenharmony_ci rev_wildcard_router_.dump(); 21122c593315Sopenharmony_ci} 21132c593315Sopenharmony_ci 21142c593315Sopenharmony_ciint cert_lookup_tree_add_ssl_ctx( 21152c593315Sopenharmony_ci CertLookupTree *lt, std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx, 21162c593315Sopenharmony_ci SSL_CTX *ssl_ctx) { 21172c593315Sopenharmony_ci std::array<uint8_t, NI_MAXHOST> buf; 21182c593315Sopenharmony_ci 21192c593315Sopenharmony_ci#if LIBRESSL_2_7_API || \ 21202c593315Sopenharmony_ci (!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L) 21212c593315Sopenharmony_ci auto cert = SSL_CTX_get0_certificate(ssl_ctx); 21222c593315Sopenharmony_ci#else // !LIBRESSL_2_7_API && OPENSSL_VERSION_NUMBER < 0x10002000L 21232c593315Sopenharmony_ci auto tls_ctx_data = 21242c593315Sopenharmony_ci static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx)); 21252c593315Sopenharmony_ci auto cert = load_certificate(tls_ctx_data->cert_file); 21262c593315Sopenharmony_ci auto cert_deleter = defer(X509_free, cert); 21272c593315Sopenharmony_ci#endif // !LIBRESSL_2_7_API && OPENSSL_VERSION_NUMBER < 0x10002000L 21282c593315Sopenharmony_ci 21292c593315Sopenharmony_ci auto altnames = static_cast<GENERAL_NAMES *>( 21302c593315Sopenharmony_ci X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); 21312c593315Sopenharmony_ci if (altnames) { 21322c593315Sopenharmony_ci auto altnames_deleter = defer(GENERAL_NAMES_free, altnames); 21332c593315Sopenharmony_ci size_t n = sk_GENERAL_NAME_num(altnames); 21342c593315Sopenharmony_ci auto dns_found = false; 21352c593315Sopenharmony_ci for (size_t i = 0; i < n; ++i) { 21362c593315Sopenharmony_ci auto altname = sk_GENERAL_NAME_value(altnames, i); 21372c593315Sopenharmony_ci if (altname->type != GEN_DNS) { 21382c593315Sopenharmony_ci continue; 21392c593315Sopenharmony_ci } 21402c593315Sopenharmony_ci 21412c593315Sopenharmony_ci auto name = ASN1_STRING_get0_data(altname->d.ia5); 21422c593315Sopenharmony_ci if (!name) { 21432c593315Sopenharmony_ci continue; 21442c593315Sopenharmony_ci } 21452c593315Sopenharmony_ci 21462c593315Sopenharmony_ci auto len = ASN1_STRING_length(altname->d.ia5); 21472c593315Sopenharmony_ci if (len == 0) { 21482c593315Sopenharmony_ci continue; 21492c593315Sopenharmony_ci } 21502c593315Sopenharmony_ci if (std::find(name, name + len, '\0') != name + len) { 21512c593315Sopenharmony_ci // Embedded NULL is not permitted. 21522c593315Sopenharmony_ci continue; 21532c593315Sopenharmony_ci } 21542c593315Sopenharmony_ci 21552c593315Sopenharmony_ci if (name[len - 1] == '.') { 21562c593315Sopenharmony_ci --len; 21572c593315Sopenharmony_ci if (len == 0) { 21582c593315Sopenharmony_ci continue; 21592c593315Sopenharmony_ci } 21602c593315Sopenharmony_ci } 21612c593315Sopenharmony_ci 21622c593315Sopenharmony_ci dns_found = true; 21632c593315Sopenharmony_ci 21642c593315Sopenharmony_ci if (static_cast<size_t>(len) + 1 > buf.size()) { 21652c593315Sopenharmony_ci continue; 21662c593315Sopenharmony_ci } 21672c593315Sopenharmony_ci 21682c593315Sopenharmony_ci auto end_buf = std::copy_n(name, len, std::begin(buf)); 21692c593315Sopenharmony_ci util::inp_strlower(std::begin(buf), end_buf); 21702c593315Sopenharmony_ci 21712c593315Sopenharmony_ci auto idx = lt->add_cert(StringRef{std::begin(buf), end_buf}, 21722c593315Sopenharmony_ci indexed_ssl_ctx.size()); 21732c593315Sopenharmony_ci if (idx == -1) { 21742c593315Sopenharmony_ci continue; 21752c593315Sopenharmony_ci } 21762c593315Sopenharmony_ci 21772c593315Sopenharmony_ci if (static_cast<size_t>(idx) < indexed_ssl_ctx.size()) { 21782c593315Sopenharmony_ci indexed_ssl_ctx[idx].push_back(ssl_ctx); 21792c593315Sopenharmony_ci } else { 21802c593315Sopenharmony_ci assert(static_cast<size_t>(idx) == indexed_ssl_ctx.size()); 21812c593315Sopenharmony_ci indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx}); 21822c593315Sopenharmony_ci } 21832c593315Sopenharmony_ci } 21842c593315Sopenharmony_ci 21852c593315Sopenharmony_ci // Don't bother CN if we have dNSName. 21862c593315Sopenharmony_ci if (dns_found) { 21872c593315Sopenharmony_ci return 0; 21882c593315Sopenharmony_ci } 21892c593315Sopenharmony_ci } 21902c593315Sopenharmony_ci 21912c593315Sopenharmony_ci auto cn = get_common_name(cert); 21922c593315Sopenharmony_ci if (cn.empty()) { 21932c593315Sopenharmony_ci return 0; 21942c593315Sopenharmony_ci } 21952c593315Sopenharmony_ci 21962c593315Sopenharmony_ci if (cn[cn.size() - 1] == '.') { 21972c593315Sopenharmony_ci if (cn.size() == 1) { 21982c593315Sopenharmony_ci OPENSSL_free(const_cast<char *>(cn.c_str())); 21992c593315Sopenharmony_ci 22002c593315Sopenharmony_ci return 0; 22012c593315Sopenharmony_ci } 22022c593315Sopenharmony_ci 22032c593315Sopenharmony_ci cn = StringRef{cn.c_str(), cn.size() - 1}; 22042c593315Sopenharmony_ci } 22052c593315Sopenharmony_ci 22062c593315Sopenharmony_ci auto end_buf = std::copy(std::begin(cn), std::end(cn), std::begin(buf)); 22072c593315Sopenharmony_ci 22082c593315Sopenharmony_ci OPENSSL_free(const_cast<char *>(cn.c_str())); 22092c593315Sopenharmony_ci 22102c593315Sopenharmony_ci util::inp_strlower(std::begin(buf), end_buf); 22112c593315Sopenharmony_ci 22122c593315Sopenharmony_ci auto idx = 22132c593315Sopenharmony_ci lt->add_cert(StringRef{std::begin(buf), end_buf}, indexed_ssl_ctx.size()); 22142c593315Sopenharmony_ci if (idx == -1) { 22152c593315Sopenharmony_ci return 0; 22162c593315Sopenharmony_ci } 22172c593315Sopenharmony_ci 22182c593315Sopenharmony_ci if (static_cast<size_t>(idx) < indexed_ssl_ctx.size()) { 22192c593315Sopenharmony_ci indexed_ssl_ctx[idx].push_back(ssl_ctx); 22202c593315Sopenharmony_ci } else { 22212c593315Sopenharmony_ci assert(static_cast<size_t>(idx) == indexed_ssl_ctx.size()); 22222c593315Sopenharmony_ci indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx}); 22232c593315Sopenharmony_ci } 22242c593315Sopenharmony_ci 22252c593315Sopenharmony_ci return 0; 22262c593315Sopenharmony_ci} 22272c593315Sopenharmony_ci 22282c593315Sopenharmony_cibool in_proto_list(const std::vector<StringRef> &protos, 22292c593315Sopenharmony_ci const StringRef &needle) { 22302c593315Sopenharmony_ci for (auto &proto : protos) { 22312c593315Sopenharmony_ci if (util::streq(proto, needle)) { 22322c593315Sopenharmony_ci return true; 22332c593315Sopenharmony_ci } 22342c593315Sopenharmony_ci } 22352c593315Sopenharmony_ci return false; 22362c593315Sopenharmony_ci} 22372c593315Sopenharmony_ci 22382c593315Sopenharmony_cibool upstream_tls_enabled(const ConnectionConfig &connconf) { 22392c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 22402c593315Sopenharmony_ci if (connconf.quic_listener.addrs.size()) { 22412c593315Sopenharmony_ci return true; 22422c593315Sopenharmony_ci } 22432c593315Sopenharmony_ci#endif // ENABLE_HTTP3 22442c593315Sopenharmony_ci 22452c593315Sopenharmony_ci const auto &faddrs = connconf.listener.addrs; 22462c593315Sopenharmony_ci return std::any_of(std::begin(faddrs), std::end(faddrs), 22472c593315Sopenharmony_ci [](const UpstreamAddr &faddr) { return faddr.tls; }); 22482c593315Sopenharmony_ci} 22492c593315Sopenharmony_ci 22502c593315Sopenharmony_ciX509 *load_certificate(const char *filename) { 22512c593315Sopenharmony_ci auto bio = BIO_new(BIO_s_file()); 22522c593315Sopenharmony_ci if (!bio) { 22532c593315Sopenharmony_ci fprintf(stderr, "BIO_new() failed\n"); 22542c593315Sopenharmony_ci return nullptr; 22552c593315Sopenharmony_ci } 22562c593315Sopenharmony_ci auto bio_deleter = defer(BIO_vfree, bio); 22572c593315Sopenharmony_ci if (!BIO_read_filename(bio, filename)) { 22582c593315Sopenharmony_ci fprintf(stderr, "Could not read certificate file '%s'\n", filename); 22592c593315Sopenharmony_ci return nullptr; 22602c593315Sopenharmony_ci } 22612c593315Sopenharmony_ci auto cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr); 22622c593315Sopenharmony_ci if (!cert) { 22632c593315Sopenharmony_ci fprintf(stderr, "Could not read X509 structure from file '%s'\n", filename); 22642c593315Sopenharmony_ci return nullptr; 22652c593315Sopenharmony_ci } 22662c593315Sopenharmony_ci 22672c593315Sopenharmony_ci return cert; 22682c593315Sopenharmony_ci} 22692c593315Sopenharmony_ci 22702c593315Sopenharmony_ciSSL_CTX * 22712c593315Sopenharmony_cisetup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx, 22722c593315Sopenharmony_ci std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx, 22732c593315Sopenharmony_ci CertLookupTree *cert_tree 22742c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 22752c593315Sopenharmony_ci , 22762c593315Sopenharmony_ci neverbleed_t *nb 22772c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 22782c593315Sopenharmony_ci) { 22792c593315Sopenharmony_ci auto config = get_config(); 22802c593315Sopenharmony_ci 22812c593315Sopenharmony_ci if (!upstream_tls_enabled(config->conn)) { 22822c593315Sopenharmony_ci return nullptr; 22832c593315Sopenharmony_ci } 22842c593315Sopenharmony_ci 22852c593315Sopenharmony_ci auto &tlsconf = config->tls; 22862c593315Sopenharmony_ci 22872c593315Sopenharmony_ci auto ssl_ctx = create_ssl_context(tlsconf.private_key_file.c_str(), 22882c593315Sopenharmony_ci tlsconf.cert_file.c_str(), tlsconf.sct_data 22892c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 22902c593315Sopenharmony_ci , 22912c593315Sopenharmony_ci nb 22922c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 22932c593315Sopenharmony_ci ); 22942c593315Sopenharmony_ci 22952c593315Sopenharmony_ci all_ssl_ctx.push_back(ssl_ctx); 22962c593315Sopenharmony_ci 22972c593315Sopenharmony_ci assert(cert_tree); 22982c593315Sopenharmony_ci 22992c593315Sopenharmony_ci if (cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx, ssl_ctx) == -1) { 23002c593315Sopenharmony_ci LOG(FATAL) << "Failed to add default certificate."; 23012c593315Sopenharmony_ci DIE(); 23022c593315Sopenharmony_ci } 23032c593315Sopenharmony_ci 23042c593315Sopenharmony_ci for (auto &c : tlsconf.subcerts) { 23052c593315Sopenharmony_ci auto ssl_ctx = create_ssl_context(c.private_key_file.c_str(), 23062c593315Sopenharmony_ci c.cert_file.c_str(), c.sct_data 23072c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 23082c593315Sopenharmony_ci , 23092c593315Sopenharmony_ci nb 23102c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 23112c593315Sopenharmony_ci ); 23122c593315Sopenharmony_ci all_ssl_ctx.push_back(ssl_ctx); 23132c593315Sopenharmony_ci 23142c593315Sopenharmony_ci if (cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx, ssl_ctx) == 23152c593315Sopenharmony_ci -1) { 23162c593315Sopenharmony_ci LOG(FATAL) << "Failed to add sub certificate."; 23172c593315Sopenharmony_ci DIE(); 23182c593315Sopenharmony_ci } 23192c593315Sopenharmony_ci } 23202c593315Sopenharmony_ci 23212c593315Sopenharmony_ci return ssl_ctx; 23222c593315Sopenharmony_ci} 23232c593315Sopenharmony_ci 23242c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 23252c593315Sopenharmony_ciSSL_CTX *setup_quic_server_ssl_context( 23262c593315Sopenharmony_ci std::vector<SSL_CTX *> &all_ssl_ctx, 23272c593315Sopenharmony_ci std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx, 23282c593315Sopenharmony_ci CertLookupTree *cert_tree 23292c593315Sopenharmony_ci# ifdef HAVE_NEVERBLEED 23302c593315Sopenharmony_ci , 23312c593315Sopenharmony_ci neverbleed_t *nb 23322c593315Sopenharmony_ci# endif // HAVE_NEVERBLEED 23332c593315Sopenharmony_ci) { 23342c593315Sopenharmony_ci auto config = get_config(); 23352c593315Sopenharmony_ci 23362c593315Sopenharmony_ci if (!upstream_tls_enabled(config->conn)) { 23372c593315Sopenharmony_ci return nullptr; 23382c593315Sopenharmony_ci } 23392c593315Sopenharmony_ci 23402c593315Sopenharmony_ci auto &tlsconf = config->tls; 23412c593315Sopenharmony_ci 23422c593315Sopenharmony_ci auto ssl_ctx = 23432c593315Sopenharmony_ci create_quic_ssl_context(tlsconf.private_key_file.c_str(), 23442c593315Sopenharmony_ci tlsconf.cert_file.c_str(), tlsconf.sct_data 23452c593315Sopenharmony_ci# ifdef HAVE_NEVERBLEED 23462c593315Sopenharmony_ci , 23472c593315Sopenharmony_ci nb 23482c593315Sopenharmony_ci# endif // HAVE_NEVERBLEED 23492c593315Sopenharmony_ci ); 23502c593315Sopenharmony_ci 23512c593315Sopenharmony_ci all_ssl_ctx.push_back(ssl_ctx); 23522c593315Sopenharmony_ci 23532c593315Sopenharmony_ci assert(cert_tree); 23542c593315Sopenharmony_ci 23552c593315Sopenharmony_ci if (cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx, ssl_ctx) == -1) { 23562c593315Sopenharmony_ci LOG(FATAL) << "Failed to add default certificate."; 23572c593315Sopenharmony_ci DIE(); 23582c593315Sopenharmony_ci } 23592c593315Sopenharmony_ci 23602c593315Sopenharmony_ci for (auto &c : tlsconf.subcerts) { 23612c593315Sopenharmony_ci auto ssl_ctx = create_quic_ssl_context(c.private_key_file.c_str(), 23622c593315Sopenharmony_ci c.cert_file.c_str(), c.sct_data 23632c593315Sopenharmony_ci# ifdef HAVE_NEVERBLEED 23642c593315Sopenharmony_ci , 23652c593315Sopenharmony_ci nb 23662c593315Sopenharmony_ci# endif // HAVE_NEVERBLEED 23672c593315Sopenharmony_ci ); 23682c593315Sopenharmony_ci all_ssl_ctx.push_back(ssl_ctx); 23692c593315Sopenharmony_ci 23702c593315Sopenharmony_ci if (cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx, ssl_ctx) == 23712c593315Sopenharmony_ci -1) { 23722c593315Sopenharmony_ci LOG(FATAL) << "Failed to add sub certificate."; 23732c593315Sopenharmony_ci DIE(); 23742c593315Sopenharmony_ci } 23752c593315Sopenharmony_ci } 23762c593315Sopenharmony_ci 23772c593315Sopenharmony_ci return ssl_ctx; 23782c593315Sopenharmony_ci} 23792c593315Sopenharmony_ci#endif // ENABLE_HTTP3 23802c593315Sopenharmony_ci 23812c593315Sopenharmony_ciSSL_CTX *setup_downstream_client_ssl_context( 23822c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 23832c593315Sopenharmony_ci neverbleed_t *nb 23842c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 23852c593315Sopenharmony_ci) { 23862c593315Sopenharmony_ci auto &tlsconf = get_config()->tls; 23872c593315Sopenharmony_ci 23882c593315Sopenharmony_ci return create_ssl_client_context( 23892c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 23902c593315Sopenharmony_ci nb, 23912c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 23922c593315Sopenharmony_ci tlsconf.cacert, tlsconf.client.cert_file, tlsconf.client.private_key_file, 23932c593315Sopenharmony_ci select_next_proto_cb); 23942c593315Sopenharmony_ci} 23952c593315Sopenharmony_ci 23962c593315Sopenharmony_civoid setup_downstream_http2_alpn(SSL *ssl) { 23972c593315Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L 23982c593315Sopenharmony_ci // ALPN advertisement 23992c593315Sopenharmony_ci auto alpn = util::get_default_alpn(); 24002c593315Sopenharmony_ci SSL_set_alpn_protos(ssl, alpn.data(), alpn.size()); 24012c593315Sopenharmony_ci#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L 24022c593315Sopenharmony_ci} 24032c593315Sopenharmony_ci 24042c593315Sopenharmony_civoid setup_downstream_http1_alpn(SSL *ssl) { 24052c593315Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L 24062c593315Sopenharmony_ci // ALPN advertisement 24072c593315Sopenharmony_ci SSL_set_alpn_protos(ssl, NGHTTP2_H1_1_ALPN.byte(), NGHTTP2_H1_1_ALPN.size()); 24082c593315Sopenharmony_ci#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L 24092c593315Sopenharmony_ci} 24102c593315Sopenharmony_ci 24112c593315Sopenharmony_cistd::unique_ptr<CertLookupTree> create_cert_lookup_tree() { 24122c593315Sopenharmony_ci auto config = get_config(); 24132c593315Sopenharmony_ci if (!upstream_tls_enabled(config->conn)) { 24142c593315Sopenharmony_ci return nullptr; 24152c593315Sopenharmony_ci } 24162c593315Sopenharmony_ci return std::make_unique<CertLookupTree>(); 24172c593315Sopenharmony_ci} 24182c593315Sopenharmony_ci 24192c593315Sopenharmony_cinamespace { 24202c593315Sopenharmony_cistd::vector<uint8_t> serialize_ssl_session(SSL_SESSION *session) { 24212c593315Sopenharmony_ci auto len = i2d_SSL_SESSION(session, nullptr); 24222c593315Sopenharmony_ci auto buf = std::vector<uint8_t>(len); 24232c593315Sopenharmony_ci auto p = buf.data(); 24242c593315Sopenharmony_ci i2d_SSL_SESSION(session, &p); 24252c593315Sopenharmony_ci 24262c593315Sopenharmony_ci return buf; 24272c593315Sopenharmony_ci} 24282c593315Sopenharmony_ci} // namespace 24292c593315Sopenharmony_ci 24302c593315Sopenharmony_civoid try_cache_tls_session(TLSSessionCache *cache, SSL_SESSION *session, 24312c593315Sopenharmony_ci const std::chrono::steady_clock::time_point &t) { 24322c593315Sopenharmony_ci if (cache->last_updated + 1min > t) { 24332c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 24342c593315Sopenharmony_ci LOG(INFO) << "Client session cache entry is still fresh."; 24352c593315Sopenharmony_ci } 24362c593315Sopenharmony_ci return; 24372c593315Sopenharmony_ci } 24382c593315Sopenharmony_ci 24392c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 24402c593315Sopenharmony_ci LOG(INFO) << "Update client cache entry " 24412c593315Sopenharmony_ci << "timestamp = " << t.time_since_epoch().count(); 24422c593315Sopenharmony_ci } 24432c593315Sopenharmony_ci 24442c593315Sopenharmony_ci cache->session_data = serialize_ssl_session(session); 24452c593315Sopenharmony_ci cache->last_updated = t; 24462c593315Sopenharmony_ci} 24472c593315Sopenharmony_ci 24482c593315Sopenharmony_ciSSL_SESSION *reuse_tls_session(const TLSSessionCache &cache) { 24492c593315Sopenharmony_ci if (cache.session_data.empty()) { 24502c593315Sopenharmony_ci return nullptr; 24512c593315Sopenharmony_ci } 24522c593315Sopenharmony_ci 24532c593315Sopenharmony_ci auto p = cache.session_data.data(); 24542c593315Sopenharmony_ci return d2i_SSL_SESSION(nullptr, &p, cache.session_data.size()); 24552c593315Sopenharmony_ci} 24562c593315Sopenharmony_ci 24572c593315Sopenharmony_ciint proto_version_from_string(const StringRef &v) { 24582c593315Sopenharmony_ci#ifdef TLS1_3_VERSION 24592c593315Sopenharmony_ci if (util::strieq_l("TLSv1.3", v)) { 24602c593315Sopenharmony_ci return TLS1_3_VERSION; 24612c593315Sopenharmony_ci } 24622c593315Sopenharmony_ci#endif // TLS1_3_VERSION 24632c593315Sopenharmony_ci if (util::strieq_l("TLSv1.2", v)) { 24642c593315Sopenharmony_ci return TLS1_2_VERSION; 24652c593315Sopenharmony_ci } 24662c593315Sopenharmony_ci if (util::strieq_l("TLSv1.1", v)) { 24672c593315Sopenharmony_ci return TLS1_1_VERSION; 24682c593315Sopenharmony_ci } 24692c593315Sopenharmony_ci if (util::strieq_l("TLSv1.0", v)) { 24702c593315Sopenharmony_ci return TLS1_VERSION; 24712c593315Sopenharmony_ci } 24722c593315Sopenharmony_ci return -1; 24732c593315Sopenharmony_ci} 24742c593315Sopenharmony_ci 24752c593315Sopenharmony_ciint verify_ocsp_response(SSL_CTX *ssl_ctx, const uint8_t *ocsp_resp, 24762c593315Sopenharmony_ci size_t ocsp_resplen) { 24772c593315Sopenharmony_ci 24782c593315Sopenharmony_ci#if !defined(OPENSSL_NO_OCSP) && !LIBRESSL_IN_USE && \ 24792c593315Sopenharmony_ci OPENSSL_VERSION_NUMBER >= 0x10002000L 24802c593315Sopenharmony_ci int rv; 24812c593315Sopenharmony_ci 24822c593315Sopenharmony_ci STACK_OF(X509) * chain_certs; 24832c593315Sopenharmony_ci SSL_CTX_get0_chain_certs(ssl_ctx, &chain_certs); 24842c593315Sopenharmony_ci 24852c593315Sopenharmony_ci auto resp = d2i_OCSP_RESPONSE(nullptr, &ocsp_resp, ocsp_resplen); 24862c593315Sopenharmony_ci if (resp == nullptr) { 24872c593315Sopenharmony_ci LOG(ERROR) << "d2i_OCSP_RESPONSE failed"; 24882c593315Sopenharmony_ci return -1; 24892c593315Sopenharmony_ci } 24902c593315Sopenharmony_ci auto resp_deleter = defer(OCSP_RESPONSE_free, resp); 24912c593315Sopenharmony_ci 24922c593315Sopenharmony_ci if (OCSP_response_status(resp) != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 24932c593315Sopenharmony_ci LOG(ERROR) << "OCSP response status is not successful"; 24942c593315Sopenharmony_ci return -1; 24952c593315Sopenharmony_ci } 24962c593315Sopenharmony_ci 24972c593315Sopenharmony_ci ERR_clear_error(); 24982c593315Sopenharmony_ci 24992c593315Sopenharmony_ci auto bs = OCSP_response_get1_basic(resp); 25002c593315Sopenharmony_ci if (bs == nullptr) { 25012c593315Sopenharmony_ci LOG(ERROR) << "OCSP_response_get1_basic failed: " 25022c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 25032c593315Sopenharmony_ci return -1; 25042c593315Sopenharmony_ci } 25052c593315Sopenharmony_ci auto bs_deleter = defer(OCSP_BASICRESP_free, bs); 25062c593315Sopenharmony_ci 25072c593315Sopenharmony_ci auto store = SSL_CTX_get_cert_store(ssl_ctx); 25082c593315Sopenharmony_ci 25092c593315Sopenharmony_ci ERR_clear_error(); 25102c593315Sopenharmony_ci 25112c593315Sopenharmony_ci rv = OCSP_basic_verify(bs, chain_certs, store, 0); 25122c593315Sopenharmony_ci 25132c593315Sopenharmony_ci if (rv != 1) { 25142c593315Sopenharmony_ci LOG(ERROR) << "OCSP_basic_verify failed: " 25152c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 25162c593315Sopenharmony_ci return -1; 25172c593315Sopenharmony_ci } 25182c593315Sopenharmony_ci 25192c593315Sopenharmony_ci auto sresp = OCSP_resp_get0(bs, 0); 25202c593315Sopenharmony_ci if (sresp == nullptr) { 25212c593315Sopenharmony_ci LOG(ERROR) << "OCSP response verification failed: no single response"; 25222c593315Sopenharmony_ci return -1; 25232c593315Sopenharmony_ci } 25242c593315Sopenharmony_ci 25252c593315Sopenharmony_ci# if OPENSSL_1_1_API 25262c593315Sopenharmony_ci auto certid = OCSP_SINGLERESP_get0_id(sresp); 25272c593315Sopenharmony_ci# else // !OPENSSL_1_1_API 25282c593315Sopenharmony_ci auto certid = sresp->certId; 25292c593315Sopenharmony_ci# endif // !OPENSSL_1_1_API 25302c593315Sopenharmony_ci assert(certid != nullptr); 25312c593315Sopenharmony_ci 25322c593315Sopenharmony_ci ASN1_INTEGER *serial; 25332c593315Sopenharmony_ci rv = OCSP_id_get0_info(nullptr, nullptr, nullptr, &serial, 25342c593315Sopenharmony_ci const_cast<OCSP_CERTID *>(certid)); 25352c593315Sopenharmony_ci if (rv != 1) { 25362c593315Sopenharmony_ci LOG(ERROR) << "OCSP_id_get0_info failed"; 25372c593315Sopenharmony_ci return -1; 25382c593315Sopenharmony_ci } 25392c593315Sopenharmony_ci 25402c593315Sopenharmony_ci if (serial == nullptr) { 25412c593315Sopenharmony_ci LOG(ERROR) << "OCSP response does not contain serial number"; 25422c593315Sopenharmony_ci return -1; 25432c593315Sopenharmony_ci } 25442c593315Sopenharmony_ci 25452c593315Sopenharmony_ci auto cert = SSL_CTX_get0_certificate(ssl_ctx); 25462c593315Sopenharmony_ci auto cert_serial = X509_get_serialNumber(cert); 25472c593315Sopenharmony_ci 25482c593315Sopenharmony_ci if (ASN1_INTEGER_cmp(cert_serial, serial)) { 25492c593315Sopenharmony_ci LOG(ERROR) << "OCSP verification serial numbers do not match"; 25502c593315Sopenharmony_ci return -1; 25512c593315Sopenharmony_ci } 25522c593315Sopenharmony_ci 25532c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 25542c593315Sopenharmony_ci LOG(INFO) << "OCSP verification succeeded"; 25552c593315Sopenharmony_ci } 25562c593315Sopenharmony_ci#endif // !defined(OPENSSL_NO_OCSP) && !LIBRESSL_IN_USE 25572c593315Sopenharmony_ci // && OPENSSL_VERSION_NUMBER >= 0x10002000L 25582c593315Sopenharmony_ci 25592c593315Sopenharmony_ci return 0; 25602c593315Sopenharmony_ci} 25612c593315Sopenharmony_ci 25622c593315Sopenharmony_cissize_t get_x509_fingerprint(uint8_t *dst, size_t dstlen, const X509 *x, 25632c593315Sopenharmony_ci const EVP_MD *md) { 25642c593315Sopenharmony_ci unsigned int len = dstlen; 25652c593315Sopenharmony_ci if (X509_digest(x, md, dst, &len) != 1) { 25662c593315Sopenharmony_ci return -1; 25672c593315Sopenharmony_ci } 25682c593315Sopenharmony_ci return len; 25692c593315Sopenharmony_ci} 25702c593315Sopenharmony_ci 25712c593315Sopenharmony_cinamespace { 25722c593315Sopenharmony_ciStringRef get_x509_name(BlockAllocator &balloc, X509_NAME *nm) { 25732c593315Sopenharmony_ci auto b = BIO_new(BIO_s_mem()); 25742c593315Sopenharmony_ci if (!b) { 25752c593315Sopenharmony_ci return StringRef{}; 25762c593315Sopenharmony_ci } 25772c593315Sopenharmony_ci 25782c593315Sopenharmony_ci auto b_deleter = defer(BIO_free, b); 25792c593315Sopenharmony_ci 25802c593315Sopenharmony_ci // Not documented, but it seems that X509_NAME_print_ex returns the 25812c593315Sopenharmony_ci // number of bytes written into b. 25822c593315Sopenharmony_ci auto slen = X509_NAME_print_ex(b, nm, 0, XN_FLAG_RFC2253); 25832c593315Sopenharmony_ci if (slen <= 0) { 25842c593315Sopenharmony_ci return StringRef{}; 25852c593315Sopenharmony_ci } 25862c593315Sopenharmony_ci 25872c593315Sopenharmony_ci auto iov = make_byte_ref(balloc, slen + 1); 25882c593315Sopenharmony_ci BIO_read(b, iov.base, slen); 25892c593315Sopenharmony_ci iov.base[slen] = '\0'; 25902c593315Sopenharmony_ci return StringRef{iov.base, static_cast<size_t>(slen)}; 25912c593315Sopenharmony_ci} 25922c593315Sopenharmony_ci} // namespace 25932c593315Sopenharmony_ci 25942c593315Sopenharmony_ciStringRef get_x509_subject_name(BlockAllocator &balloc, X509 *x) { 25952c593315Sopenharmony_ci return get_x509_name(balloc, X509_get_subject_name(x)); 25962c593315Sopenharmony_ci} 25972c593315Sopenharmony_ci 25982c593315Sopenharmony_ciStringRef get_x509_issuer_name(BlockAllocator &balloc, X509 *x) { 25992c593315Sopenharmony_ci return get_x509_name(balloc, X509_get_issuer_name(x)); 26002c593315Sopenharmony_ci} 26012c593315Sopenharmony_ci 26022c593315Sopenharmony_ciStringRef get_x509_serial(BlockAllocator &balloc, X509 *x) { 26032c593315Sopenharmony_ci auto sn = X509_get_serialNumber(x); 26042c593315Sopenharmony_ci auto bn = BN_new(); 26052c593315Sopenharmony_ci auto bn_d = defer(BN_free, bn); 26062c593315Sopenharmony_ci if (!ASN1_INTEGER_to_BN(sn, bn) || BN_num_bytes(bn) > 20) { 26072c593315Sopenharmony_ci return StringRef{}; 26082c593315Sopenharmony_ci } 26092c593315Sopenharmony_ci 26102c593315Sopenharmony_ci std::array<uint8_t, 20> b; 26112c593315Sopenharmony_ci auto n = BN_bn2bin(bn, b.data()); 26122c593315Sopenharmony_ci assert(n <= 20); 26132c593315Sopenharmony_ci 26142c593315Sopenharmony_ci return util::format_hex(balloc, StringRef{b.data(), static_cast<size_t>(n)}); 26152c593315Sopenharmony_ci} 26162c593315Sopenharmony_ci 26172c593315Sopenharmony_cinamespace { 26182c593315Sopenharmony_ci// Performs conversion from |at| to time_t. The result is stored in 26192c593315Sopenharmony_ci// |t|. This function returns 0 if it succeeds, or -1. 26202c593315Sopenharmony_ciint time_t_from_asn1_time(time_t &t, const ASN1_TIME *at) { 26212c593315Sopenharmony_ci int rv; 26222c593315Sopenharmony_ci 26232c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 26242c593315Sopenharmony_ci struct tm tm; 26252c593315Sopenharmony_ci rv = ASN1_TIME_to_tm(at, &tm); 26262c593315Sopenharmony_ci if (rv != 1) { 26272c593315Sopenharmony_ci return -1; 26282c593315Sopenharmony_ci } 26292c593315Sopenharmony_ci 26302c593315Sopenharmony_ci t = nghttp2_timegm(&tm); 26312c593315Sopenharmony_ci#else // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)) 26322c593315Sopenharmony_ci auto b = BIO_new(BIO_s_mem()); 26332c593315Sopenharmony_ci if (!b) { 26342c593315Sopenharmony_ci return -1; 26352c593315Sopenharmony_ci } 26362c593315Sopenharmony_ci 26372c593315Sopenharmony_ci auto bio_deleter = defer(BIO_free, b); 26382c593315Sopenharmony_ci 26392c593315Sopenharmony_ci rv = ASN1_TIME_print(b, at); 26402c593315Sopenharmony_ci if (rv != 1) { 26412c593315Sopenharmony_ci return -1; 26422c593315Sopenharmony_ci } 26432c593315Sopenharmony_ci 26442c593315Sopenharmony_ci# ifdef OPENSSL_IS_BORINGSSL 26452c593315Sopenharmony_ci char *s; 26462c593315Sopenharmony_ci# else 26472c593315Sopenharmony_ci unsigned char *s; 26482c593315Sopenharmony_ci# endif 26492c593315Sopenharmony_ci auto slen = BIO_get_mem_data(b, &s); 26502c593315Sopenharmony_ci auto tt = util::parse_openssl_asn1_time_print( 26512c593315Sopenharmony_ci StringRef{s, static_cast<size_t>(slen)}); 26522c593315Sopenharmony_ci if (tt == 0) { 26532c593315Sopenharmony_ci return -1; 26542c593315Sopenharmony_ci } 26552c593315Sopenharmony_ci 26562c593315Sopenharmony_ci t = tt; 26572c593315Sopenharmony_ci#endif // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)) 26582c593315Sopenharmony_ci 26592c593315Sopenharmony_ci return 0; 26602c593315Sopenharmony_ci} 26612c593315Sopenharmony_ci} // namespace 26622c593315Sopenharmony_ci 26632c593315Sopenharmony_ciint get_x509_not_before(time_t &t, X509 *x) { 26642c593315Sopenharmony_ci#if OPENSSL_1_1_API 26652c593315Sopenharmony_ci auto at = X509_get0_notBefore(x); 26662c593315Sopenharmony_ci#else // !OPENSSL_1_1_API 26672c593315Sopenharmony_ci auto at = X509_get_notBefore(x); 26682c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API 26692c593315Sopenharmony_ci if (!at) { 26702c593315Sopenharmony_ci return -1; 26712c593315Sopenharmony_ci } 26722c593315Sopenharmony_ci 26732c593315Sopenharmony_ci return time_t_from_asn1_time(t, at); 26742c593315Sopenharmony_ci} 26752c593315Sopenharmony_ci 26762c593315Sopenharmony_ciint get_x509_not_after(time_t &t, X509 *x) { 26772c593315Sopenharmony_ci#if OPENSSL_1_1_API 26782c593315Sopenharmony_ci auto at = X509_get0_notAfter(x); 26792c593315Sopenharmony_ci#else // !OPENSSL_1_1_API 26802c593315Sopenharmony_ci auto at = X509_get_notAfter(x); 26812c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API 26822c593315Sopenharmony_ci if (!at) { 26832c593315Sopenharmony_ci return -1; 26842c593315Sopenharmony_ci } 26852c593315Sopenharmony_ci 26862c593315Sopenharmony_ci return time_t_from_asn1_time(t, at); 26872c593315Sopenharmony_ci} 26882c593315Sopenharmony_ci 26892c593315Sopenharmony_ci} // namespace tls 26902c593315Sopenharmony_ci 26912c593315Sopenharmony_ci} // namespace shrpx 2692