return d_tlsContext.rotateTicketsKey(now);
}
-void DOHFrontend::setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& hook)
-{
- return d_tlsContext.setTicketsKeyAddedHook(hook);
-}
-
void DOHFrontend::loadTicketsKeys(const std::string& keyFile)
{
return d_tlsContext.loadTicketsKeys(keyFile);
{
}
- virtual void setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& /* hook */)
- {
- }
-
virtual void loadTicketsKeys(const std::string& /* keyFile */)
{
}
virtual void setup();
virtual void reloadCertificates();
- virtual void setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& hook);
virtual void rotateTicketsKey(time_t now);
virtual void loadTicketsKeys(const std::string& keyFile);
virtual void handleTicketsKeyRotation();
#include "dnsdist-lua-hooks.hh"
#include "dnsdist-lua.hh"
#include "lock.hh"
+#include "tcpiohandler.hh"
namespace dnsdist::lua::hooks
{
s_maintenanceHooks.lock()->clear();
}
+void setTicketsKeyAddedHook(const LuaContext& context, const TicketsKeyAddedHook& hook)
+{
+ TLSCtx::setTicketsKeyAddedHook([hook](const std::string& key) {
+ try {
+ hook(key.c_str(), key.size());
+ }
+ catch (const std::exception& exp) {
+ warnlog("Error calling the Lua hook after new tickets key has been added", exp.what());
+ }
+ });
+}
+
void setupLuaHooks(LuaContext& luaCtx)
{
luaCtx.writeFunction("addMaintenanceCallback", [&luaCtx](const MaintenanceCallback& callback) {
setLuaSideEffect();
addMaintenanceCallback(luaCtx, callback);
});
+ luaCtx.writeFunction("setTicketsKeyAddedHook", [&luaCtx](const TicketsKeyAddedHook& hook) {
+ setLuaSideEffect();
+ setTicketsKeyAddedHook(luaCtx, hook);
+ });
}
}
namespace dnsdist::lua::hooks
{
using MaintenanceCallback = std::function<void()>;
+using TicketsKeyAddedHook = std::function<void(const char*, size_t)>;
+
void runMaintenanceHooks(const LuaContext& context);
void addMaintenanceCallback(const LuaContext& context, MaintenanceCallback callback);
+void setTicketsKeyAddedHook(const LuaContext& context, const TicketsKeyAddedHook& hook);
void clearMaintenanceHooks();
void setupLuaHooks(LuaContext& luaCtx);
}
}
});
-
- luaCtx.registerFunction<void (std::shared_ptr<DOHFrontend>::*)(const dnsdist_tickets_key_added_hook&)>("setTicketsKeyAddedHook", [](const std::shared_ptr<DOHFrontend>& frontend, const dnsdist_tickets_key_added_hook& hook) {
- if (frontend != nullptr) {
- frontend->setTicketsKeyAddedHook(hook);
- }
- });
-
luaCtx.registerFunction<void (std::shared_ptr<DOHFrontend>::*)(const LuaArray<std::shared_ptr<DOHResponseMapEntry>>&)>("setResponsesMap", [](const std::shared_ptr<DOHFrontend>& frontend, const LuaArray<std::shared_ptr<DOHResponseMapEntry>>& map) {
if (frontend != nullptr) {
auto newMap = std::make_shared<std::vector<std::shared_ptr<DOHResponseMapEntry>>>();
}
});
- luaCtx.registerFunction<void (std::shared_ptr<TLSCtx>::*)(const dnsdist_tickets_key_added_hook&)>("setTicketsKeyAddedHook", [](const std::shared_ptr<TLSCtx>& frontend, const dnsdist_tickets_key_added_hook& hook) {
- if (frontend != nullptr) {
- frontend->setTicketsKeyAddedHook(hook);
- }
- });
-
luaCtx.registerFunction<void (std::shared_ptr<TLSCtx>::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr<TLSCtx>& ctx, const std::string& file) {
if (ctx != nullptr) {
ctx->loadTicketsKeys(file);
return frontend->d_addr.toStringWithPort();
});
- luaCtx.registerFunction<void (std::shared_ptr<TLSFrontend>::*)(const dnsdist_tickets_key_added_hook&)>("setTicketsKeyAddedHook", [](const std::shared_ptr<TLSFrontend>& frontend, const dnsdist_tickets_key_added_hook& hook) {
- if (frontend == nullptr) {
- return;
- }
- auto ctx = frontend->getContext();
- if (ctx) {
- ctx->setTicketsKeyAddedHook(hook);
- }
- });
-
luaCtx.registerFunction<void (std::shared_ptr<TLSFrontend>::*)()>("rotateTicketsKey", [](std::shared_ptr<TLSFrontend>& frontend) {
if (frontend == nullptr) {
return;
Code is supplied as a string, not as a function object.
Note that this function does nothing in 'client' or 'config-check' modes.
+.. function:: setTicketsKeyAddedHook(callback)
+
+ .. versionadded:: 1.9.0
+
+ Set a Lua function that will be called everytime a new tickets key is added. The function receives:
+
+ * the key content as a string
+ * the keylen as an integer
+
+ See :doc:`../advanced/tls-sessions-management` for more information.
+
.. function:: submitToMainThread(cmd, dict)
.. versionadded:: 1.8.0
Replace the current TLS tickets key by a new random one.
- .. method:: DOHFrontend:setTicketsKeyAddedHook(callback)
-
- .. versionadded:: 1.9.0
-
- Set a Lua function that will be called everytime a new tickets key is added. The function receives:
-
- * the key content as a string
- * the keylen as an integer
-
- See :doc:`../advanced/tls-sessions-management` for more information.
-
.. method:: DOHFrontend:setResponsesMap(rules)
Set a list of HTTP response rules allowing to intercept HTTP queries very early, before the DNS payload has been processed, and send custom responses including error pages, redirects and static content.
Replace the current TLS tickets key by a new random one.
- .. method:: TLSContext:setTicketsKeyAddedHook(callback)
-
- .. versionadded:: 1.9.0
-
- Set a Lua function that will be called everytime a new tickets key is added. The function receives:
-
- * the key content as a string
- * the keylen as an integer
-
- See :doc:`../advanced/tls-sessions-management` for more information.
-
TLSFrontend
~~~~~~~~~~~
Replace the current TLS tickets key by a new random one.
- .. method:: TLSFrontend:setTicketsKeyAddedHook(callback)
-
- .. versionadded:: 1.9.0
-
- Set a Lua function that will be called everytime a new tickets key is added. The function receives:
-
- * the key content as a string
- * the keylen as an integer
-
- See :doc:`../advanced/tls-sessions-management` for more information.
-
EDNS on Self-generated answers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#undef CERT
#include "misc.hh"
+#include "tcpiohandler.hh"
#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL)
/* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */
void OpenSSLTLSTicketKeysRing::addKey(std::shared_ptr<OpenSSLTLSTicketKey>&& newKey)
{
d_ticketKeys.write_lock()->push_front(std::move(newKey));
- if (d_ticketsKeyAddedHook) {
+ if (TLSCtx::hasTicketsKeyAddedHook()) {
auto key = d_ticketKeys.read_lock()->front();
auto keyContent = key->content();
- d_ticketsKeyAddedHook(keyContent.c_str(), keyContent.size());
+ TLSCtx::getTicketsKeyAddedHook()(keyContent);
}
}
-void OpenSSLTLSTicketKeysRing::setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& hook)
-{
- d_ticketsKeyAddedHook = hook;
-}
-
std::shared_ptr<OpenSSLTLSTicketKey> OpenSSLTLSTicketKeysRing::getEncryptionKey()
{
return d_ticketKeys.read_lock()->front();
unsigned char d_hmacKey[TLS_TICKETS_MAC_KEY_SIZE];
};
-using dnsdist_tickets_key_added_hook = std::function<void(const char* key, size_t keyLen)>;
-
class OpenSSLTLSTicketKeysRing
{
public:
size_t getKeysCount();
void loadTicketsKeys(const std::string& keyFile);
void rotateTicketsKey(time_t now);
- void setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& hook);
private:
void addKey(std::shared_ptr<OpenSSLTLSTicketKey>&& newKey);
- dnsdist_tickets_key_added_hook d_ticketsKeyAddedHook;
SharedLockGuarded<boost::circular_buffer<std::shared_ptr<OpenSSLTLSTicketKey> > > d_ticketKeys;
};
#include "libssl.hh"
+dnsdist_tickets_key_added_hook TLSCtx::s_ticketsKeyAddedHook{nullptr};
class OpenSSLFrontendContext
{
}
}
- void setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& hook) override
- {
- d_feContext->d_ticketKeys.setTicketsKeyAddedHook(hook);
- }
-
void loadTicketsKeys(const std::string& keyFile) final
{
d_feContext->d_ticketKeys.loadTicketsKeys(keyFile);
return connection;
}
- void setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& hook) override
- {
- d_ticketsKeyAddedHook = hook;
- }
-
- void rotateTicketsKey(time_t now) override
+ void addTicketsKey(time_t now, std::shared_ptr<GnuTLSTicketsKey>&& newKey)
{
if (!d_enableTickets) {
return;
}
- auto newKey = std::make_shared<GnuTLSTicketsKey>();
-
{
*(d_ticketsKey.write_lock()) = std::move(newKey);
}
d_ticketsKeyNextRotation = now + d_ticketsKeyRotationDelay;
}
- if (d_ticketsKeyAddedHook) {
+ if (TLSCtx::hasTicketsKeyAddedHook()) {
auto ticketsKey = *(d_ticketsKey.read_lock());
auto content = ticketsKey->content();
- d_ticketsKeyAddedHook(content.c_str(), content.size());
+ TLSCtx::getTicketsKeyAddedHook()(content);
}
}
+ void rotateTicketsKey(time_t now) override
+ {
+ if (!d_enableTickets) {
+ return;
+ }
+ auto newKey = std::make_shared<GnuTLSTicketsKey>();
+ addTicketsKey(now, std::move(newKey));
+ }
void loadTicketsKeys(const std::string& file) final
{
if (!d_enableTickets) {
}
auto newKey = std::make_shared<GnuTLSTicketsKey>(file);
- {
- *(d_ticketsKey.write_lock()) = std::move(newKey);
- }
-
- if (d_ticketsKeyRotationDelay > 0) {
- d_ticketsKeyNextRotation = time(nullptr) + d_ticketsKeyRotationDelay;
- }
+ addTicketsKey(time(nullptr), std::move(newKey));
}
size_t getTicketsKeysCount() override
SharedLockGuarded<std::shared_ptr<GnuTLSTicketsKey>> d_ticketsKey{nullptr};
bool d_enableTickets{true};
bool d_validateCerts{true};
- dnsdist_tickets_key_added_hook d_ticketsKeyAddedHook;
};
#endif /* HAVE_GNUTLS */
bool d_resumedFromInactiveTicketKey{false};
};
+using dnsdist_tickets_key_added_hook = std::function<void(const std::string& key)>;
+
class TLSCtx
{
public:
{
throw std::runtime_error("This TLS backend does not have the capability to load a tickets key from a file");
}
- virtual void setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& /* hook */)
- {
- throw std::runtime_error("This TLS backend does not have the capability to setup a hook for added tickets keys");
- }
-
void handleTicketsKeyRotation(time_t now)
{
if (d_ticketsKeyRotationDelay != 0 && now > d_ticketsKeyNextRotation) {
return false;
}
+ static void setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& hook)
+ {
+ TLSCtx::s_ticketsKeyAddedHook = hook;
+ }
+ static const dnsdist_tickets_key_added_hook& getTicketsKeyAddedHook()
+ {
+ return TLSCtx::s_ticketsKeyAddedHook;
+ }
+ static bool hasTicketsKeyAddedHook()
+ {
+ return TLSCtx::s_ticketsKeyAddedHook != nullptr;
+ }
protected:
std::atomic_flag d_rotatingTicketsKey;
std::atomic<time_t> d_ticketsKeyNextRotation{0};
time_t d_ticketsKeyRotationDelay{0};
+
+private:
+ static dnsdist_tickets_key_added_hook s_ticketsKeyAddedHook;
};
class TLSFrontend
}
}
- void setTicketsKeyAddedHook(const dnsdist_tickets_key_added_hook& hook)
- {
- if (d_ctx != nullptr) {
- d_ctx->setTicketsKeyAddedHook(hook);
- }
- }
-
void loadTicketsKeys(const std::string& file)
{
if (d_ctx != nullptr) {
"""
LuaThread: Test the lua newThread interface
"""
- self.sendConsoleCommand('getTLSFrontend(0):setTicketsKeyAddedHook(keyAddedCallback)');
+ self.sendConsoleCommand('setTicketsKeyAddedHook(keyAddedCallback)');
called = self.sendConsoleCommand('callbackCalled')
self.assertEqual(int(called), 0)
self.sendConsoleCommand("getTLSFrontend(0):rotateTicketsKey()")