blob: 7555061353c3ad61d4436be13123a08109c64d83 [file] [log] [blame]
/**
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#ifndef OPENSSL_IS_BORINGSSL
#include <openssl/opensslconf.h>
#endif
#include <openssl/ssl.h>
#include <memory>
#include <mutex>
#include <shared_mutex>
/** A class for handling TLS secrets logging. */
class TLSKeyLogger
{
public:
TLSKeyLogger(const TLSKeyLogger &) = delete;
TLSKeyLogger &operator=(const TLSKeyLogger &) = delete;
~TLSKeyLogger()
{
std::unique_lock lock{_mutex};
close_keylog_file();
}
/** A callback for TLS secret key logging.
*
* This is the callback registered with OpenSSL's SSL_CTX_set_keylog_callback
* to log TLS secrets if the user enabled that feature. For more information
* about this callback, see OpenSSL's documentation of
* SSL_CTX_set_keylog_callback.
*
* @param[in] ssl The SSL object associated with the connection.
* @param[in] line The line to place in the keylog file.
*/
static void
ssl_keylog_cb(const SSL *ssl, const char *line)
{
instance().log(line);
}
/** Return whether TLS key logging is enabled.
*
* @return True if TLS session key logging is enabled, false otherwise.
*/
static bool
is_enabled()
{
return instance()._fd >= 0;
}
/** Enable keylogging.
*
* @param[in] keylog_file The path to the file to log TLS secrets to.
*/
static void
enable_keylogging(const char *keylog_file)
{
instance().enable_keylogging_internal(keylog_file);
}
/** Disable TLS secrets logging. */
static void
disable_keylogging()
{
instance().disable_keylogging_internal();
}
private:
TLSKeyLogger() = default;
/** Return the TLSKeyLogger singleton.
*
* We use a getter rather than a class static singleton member so that the
* construction of the singleton delayed until after TLS configuration is
* processed.
*/
static TLSKeyLogger &
instance()
{
static TLSKeyLogger instance;
return instance;
}
/** Close the file descriptor for the key log file.
*
* @note This assumes that a unique lock has been acquired for _mutex.
*/
void close_keylog_file();
/** A TLS secret line to log to the keylog file.
*
* @param[in] line A line to log to the keylog file.
*/
void log(const char *line);
/** Enable TLS keylogging in the instance singleton. */
void enable_keylogging_internal(const char *keylog_file);
/** Disable TLS keylogging in the instance singleton. */
void disable_keylogging_internal();
private:
/** A file descriptor for the log file receiving the TLS secrets. */
int _fd = -1;
/** A mutex to coordinate dynamically changing TLS logging config changes and
* logging to the TLS log file. */
std::shared_mutex _mutex;
};