config.d_ocspFiles.push_back(file.second);
}
}
+
+ if (vars->count("keyLogFile")) {
+ config.d_keyLogFile = boost::get<const string>((*vars)["keyLogFile"]);
+ }
}
#endif // defined(HAVE_DNS_OVER_TLS) || defined(HAVE_DNS_OVER_HTTPS)
* ``sessionTickets``: bool - Whether session resumption via session tickets is enabled. Default is true, meaning tickets are enabled.
* ``numberOfStoredSessions``: int - The maximum number of sessions kept in memory at the same time. Default is 20480. Setting this value to 0 disables stored session entirely.
* ``preferServerCiphers``: bool - Whether to prefer the order of ciphers set by the server instead of the one set by the client. Default is false, meaning that the order of the client is used.
+ * ``keyLogFile``: str - Write the TLS keys in the specified file so that an external program can decrypt TLS exchanges, in the format described in https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.
.. function:: addTLSLocal(address, certFile(s), keyFile(s) [, options])
.. versionchanged:: 1.3.3
``numberOfStoredSessions`` option added.
.. versionchanged:: 1.4.0
- ``ciphersTLS13``, ``minTLSVersion``, ``ocspResponses`` and ``preferServerCiphers`` options added.
+ ``ciphersTLS13``, ``minTLSVersion``, ``ocspResponses``, ``preferServerCiphers``, ``keyLogFile`` options added.
Listen on the specified address and TCP port for incoming DNS over TLS connections, presenting the specified X.509 certificate.
* ``ocspResponses``: list - List of files containing OCSP responses, in the same order than the certificates and keys, that will be used to provide OCSP stapling responses.
* ``minTLSVersion``: str - Minimum version of the TLS protocol to support. Possible values are 'tls1.0', 'tls1.1', 'tls1.2' and 'tls1.3'. Default is to require at least TLS 1.0. Note that this value is ignored when the GnuTLS provider is in use, and the ``ciphers`` option should be set accordingly instead. For example, 'NORMAL:!VERS-TLS1.0:!VERS-TLS1.1' will disable TLS 1.0 and 1.1.
* ``preferServerCiphers``: bool - Whether to prefer the order of ciphers set by the server instead of the one set by the client. Default is false, meaning that the order of the client is used.
+ * ``keyLogFile``: str - Write the TLS keys in the specified file so that an external program can decrypt TLS exchanges, in the format described in https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.
.. function:: setLocal(address[, options])
std::map<int, std::string> d_ocspResponses;
std::unique_ptr<OpenSSLTLSTicketKeysRing> d_ticketKeys{nullptr};
+ std::unique_ptr<FILE, int(*)(FILE*)> d_keyLogFile{nullptr, fclose};
ClientState* d_cs{nullptr};
time_t d_ticketsKeyRotationDelay{0};
libssl_set_error_counters_callback(ctx, &counters);
+ if (!tlsConfig.d_keyLogFile.empty()) {
+ acceptCtx.d_keyLogFile = libssl_set_key_log_file(ctx, tlsConfig.d_keyLogFile);
+ }
+
h2o_ssl_register_alpn_protocols(ctx.get(), h2o_http2_alpn_protocols);
if (tlsConfig.d_ticketKeyFile.empty()) {
static std::atomic<uint64_t> s_users;
static int s_ticketsKeyIndex{-1};
static int s_countersIndex{-1};
+static int s_keyLogIndex{-1};
void registerOpenSSLUser()
{
if (s_users.fetch_add(1) == 0) {
+#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || defined LIBRESSL_VERSION_NUMBER)
+ SSL_load_error_strings();
+ OpenSSL_add_ssl_algorithms();
+ openssl_thread_setup();
+#endif
s_ticketsKeyIndex = SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
if (s_ticketsKeyIndex == -1) {
if (s_countersIndex == -1) {
throw std::runtime_error("Error getting an index for counters");
}
-#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || defined LIBRESSL_VERSION_NUMBER)
- SSL_load_error_strings();
- OpenSSL_add_ssl_algorithms();
- openssl_thread_setup();
-#endif
+
+ s_keyLogIndex = SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
+
+ if (s_keyLogIndex == -1) {
+ throw std::runtime_error("Error getting an index for TLS key logging");
+ }
}
}
return ctx;
}
+#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
+static void libssl_key_log_file_callback(const SSL* ssl, const char* line)
+{
+ SSL_CTX* sslCtx = SSL_get_SSL_CTX(ssl);
+ if (sslCtx == nullptr) {
+ return;
+ }
+
+ auto fp = reinterpret_cast<FILE*>(SSL_CTX_get_ex_data(sslCtx, s_keyLogIndex));
+ if (fp == nullptr) {
+ return;
+ }
+
+ fprintf(fp, "%s\n", line);
+}
+#endif /* HAVE_SSL_CTX_SET_KEYLOG_CALLBACK */
+
+std::unique_ptr<FILE, int(*)(FILE*)> libssl_set_key_log_file(std::unique_ptr<SSL_CTX, void(*)(SSL_CTX*)>& ctx, const std::string& logFile)
+{
+#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
+ auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fopen(logFile.c_str(), "a"), fclose);
+ if (!fp) {
+ throw std::runtime_error("Error opening TLS log file '" + logFile + "'");
+ }
+
+ SSL_CTX_set_ex_data(ctx.get(), s_keyLogIndex, fp.get());
+ SSL_CTX_set_keylog_callback(ctx.get(), &libssl_key_log_file_callback);
+
+ return fp;
+#else
+ return std::unique_ptr<FILE, int(*)(FILE*)>(nullptr, fclose);
+#endif /* HAVE_SSL_CTX_SET_KEYLOG_CALLBACK */
+}
+
#endif /* HAVE_LIBSSL */
save_LIBS=$LIBS
CFLAGS="$LIBSSL_CFLAGS $CFLAGS"
LIBS="$LIBSSL_LIBS -lcrypto $LIBS"
- AC_CHECK_FUNCS([SSL_CTX_set_ciphersuites OCSP_basic_sign SSL_CTX_set_num_tickets])
+ AC_CHECK_FUNCS([SSL_CTX_set_ciphersuites OCSP_basic_sign SSL_CTX_set_num_tickets SSL_CTX_set_keylog_callback])
CFLAGS=$save_CFLAGS
LIBS=$save_LIBS
std::string d_ciphers;
std::string d_ciphers13;
std::string d_ticketKeyFile;
+ std::string d_keyLogFile;
size_t d_maxStoredSessions{20480};
time_t d_ticketsKeyRotationDelay{43200};
std::unique_ptr<SSL_CTX, void(*)(SSL_CTX*)> libssl_init_server_context(const TLSConfig& config,
std::map<int, std::string>& ocspResponses);
+std::unique_ptr<FILE, int(*)(FILE*)> libssl_set_key_log_file(std::unique_ptr<SSL_CTX, void(*)(SSL_CTX*)>& ctx, const std::string& logFile);
#endif /* HAVE_LIBSSL */