2021-07-06 23:15:30 +00:00
|
|
|
#include "CertificateReloader.h"
|
2021-07-06 23:34:43 +00:00
|
|
|
#include <common/errnoToString.h>
|
|
|
|
|
2021-07-06 23:15:30 +00:00
|
|
|
|
|
|
|
#if USE_SSL
|
2020-10-08 16:07:58 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
2021-07-06 23:15:30 +00:00
|
|
|
|
2021-07-06 23:34:43 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int CANNOT_STAT;
|
|
|
|
}
|
|
|
|
|
2021-07-06 23:15:30 +00:00
|
|
|
int CertificateReloader::setCertificate(SSL * ssl)
|
2020-10-08 16:07:58 +00:00
|
|
|
{
|
2021-07-06 22:19:26 +00:00
|
|
|
std::shared_lock lock(mutex);
|
2020-10-08 16:07:58 +00:00
|
|
|
SSL_use_certificate(ssl, const_cast<X509 *>(cert->certificate()));
|
|
|
|
SSL_use_RSAPrivateKey(ssl, key->impl()->getRSA());
|
|
|
|
|
|
|
|
int err = SSL_check_private_key(ssl);
|
|
|
|
if (err != 1)
|
|
|
|
{
|
|
|
|
std::string msg = Poco::Net::Utility::getLastError();
|
|
|
|
LOG_ERROR(log, "Unusable keypair {}", msg);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-07-06 23:15:30 +00:00
|
|
|
void CertificateReloader::init(const Poco::Util::AbstractConfiguration & config)
|
2020-10-08 16:07:58 +00:00
|
|
|
{
|
2021-07-06 23:34:43 +00:00
|
|
|
LOG_DEBUG(log, "Initializing certificate reloader.");
|
2020-10-08 16:07:58 +00:00
|
|
|
|
2021-07-06 23:34:43 +00:00
|
|
|
SSL_CTX_set_cert_cb(
|
|
|
|
Poco::Net::SSLManager::instance().defaultClientContext()->sslContext(),
|
|
|
|
[](SSL * ssl, void * arg) { return reinterpret_cast<CertificateReloader *>(arg)->setCertificate(ssl); },
|
|
|
|
static_cast<void *>(this));
|
2020-10-08 16:07:58 +00:00
|
|
|
|
|
|
|
reload(config);
|
|
|
|
}
|
|
|
|
|
2021-07-06 23:15:30 +00:00
|
|
|
void CertificateReloader::reload(const Poco::Util::AbstractConfiguration & config)
|
2020-10-08 16:07:58 +00:00
|
|
|
{
|
2021-07-06 23:34:43 +00:00
|
|
|
LOG_DEBUG(log, "Handling certificate reload.");
|
2020-10-08 16:07:58 +00:00
|
|
|
const auto cert_file_ = config.getString("openSSL.server.certificateFile", "");
|
|
|
|
const auto key_file_ = config.getString("openSSL.server.privateKeyFile", "");
|
|
|
|
|
2020-10-08 20:15:04 +00:00
|
|
|
bool changed = false;
|
|
|
|
changed |= setKeyFile(key_file_);
|
2021-07-06 23:15:30 +00:00
|
|
|
changed |= setCertificateFile(cert_file_);
|
2020-10-08 20:15:04 +00:00
|
|
|
|
|
|
|
if (changed)
|
2020-10-08 16:07:58 +00:00
|
|
|
{
|
2021-07-06 23:34:43 +00:00
|
|
|
LOG_INFO(log, "Reloading certificate ({}) and key ({}).", cert_file, key_file);
|
2020-10-08 16:07:58 +00:00
|
|
|
{
|
2021-07-06 22:19:26 +00:00
|
|
|
std::unique_lock lock(mutex);
|
2021-07-06 23:34:43 +00:00
|
|
|
key = std::make_unique<Poco::Crypto::RSAKey>(/* public key */ "", /* private key */ key_file);
|
2021-07-06 22:20:14 +00:00
|
|
|
cert = std::make_unique<Poco::Crypto::X509Certificate>(cert_file);
|
2020-10-08 16:07:58 +00:00
|
|
|
}
|
2021-07-06 23:34:43 +00:00
|
|
|
LOG_INFO(log, "Reloaded certificate ({}).", cert_file);
|
2020-10-08 16:07:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-06 23:15:30 +00:00
|
|
|
bool CertificateReloader::setKeyFile(const std::string key_file_)
|
2020-10-08 16:07:58 +00:00
|
|
|
{
|
|
|
|
if (key_file_.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
stat_t st;
|
|
|
|
int res = stat(key_file_.c_str(), &st);
|
|
|
|
if (res == -1)
|
2021-07-06 23:34:43 +00:00
|
|
|
{
|
|
|
|
LOG_ERROR(log, "Cannot obtain stat for key file {}, skipping update. {}", key_file_, errnoToString(ErrorCodes::CANNOT_STAT));
|
2020-10-08 16:07:58 +00:00
|
|
|
return false;
|
2021-07-06 23:34:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// NOTE: if file changed twice in a second, the update will be missed.
|
2020-10-08 16:07:58 +00:00
|
|
|
|
|
|
|
if (st.st_mtime != key_file_st.st_mtime || key_file != key_file_)
|
|
|
|
{
|
|
|
|
key_file = key_file_;
|
|
|
|
key_file_st = st;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-07-06 23:15:30 +00:00
|
|
|
bool CertificateReloader::setCertificateFile(const std::string cert_file_)
|
2020-10-08 16:07:58 +00:00
|
|
|
{
|
|
|
|
if (cert_file_.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
stat_t st;
|
|
|
|
int res = stat(cert_file_.c_str(), &st);
|
|
|
|
if (res == -1)
|
2021-07-06 23:34:43 +00:00
|
|
|
{
|
|
|
|
LOG_ERROR(log, "Cannot obtain stat for certificate file {}, skipping update. {}", cert_file_, errnoToString(ErrorCodes::CANNOT_STAT));
|
2020-10-08 16:07:58 +00:00
|
|
|
return false;
|
2021-07-06 23:34:43 +00:00
|
|
|
}
|
2020-10-08 16:07:58 +00:00
|
|
|
|
|
|
|
if (st.st_mtime != cert_file_st.st_mtime || cert_file != cert_file_)
|
|
|
|
{
|
|
|
|
cert_file = cert_file_;
|
|
|
|
cert_file_st = st;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2021-07-06 23:15:30 +00:00
|
|
|
|
|
|
|
#endif
|