From: Remi Gacogne Date: Fri, 5 Apr 2019 15:12:29 +0000 (+0200) Subject: dnsdist: Add 'reloadAllCertificates()' X-Git-Tag: dnsdist-1.4.0-alpha1~6^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bcc62bfb6b8448c0e849ede1866d319954c55a1a;p=thirdparty%2Fpdns.git dnsdist: Add 'reloadAllCertificates()' --- diff --git a/pdns/dnscrypt.cc b/pdns/dnscrypt.cc index f81263c09f..4cf126ce38 100644 --- a/pdns/dnscrypt.cc +++ b/pdns/dnscrypt.cc @@ -283,13 +283,19 @@ std::string DNSCryptContext::certificateDateToStr(uint32_t date) return string(buf); } -void DNSCryptContext::addNewCertificate(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, bool active) +void DNSCryptContext::addNewCertificate(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, bool active, bool reload) { WriteLock w(&d_lock); for (auto pair : certs) { if (pair->cert.getSerial() == newCert.getSerial()) { - throw std::runtime_error("Error adding a new certificate: we already have a certificate with the same serial"); + if (reload) { + /* on reload we just assume that this is the same certificate */ + return; + } + else { + throw std::runtime_error("Error adding a new certificate: we already have a certificate with the same serial"); + } } } @@ -301,7 +307,7 @@ void DNSCryptContext::addNewCertificate(const DNSCryptCert& newCert, const DNSCr certs.push_back(pair); } -void DNSCryptContext::loadNewCertificate(const std::string& certFile, const std::string& keyFile, bool active) +void DNSCryptContext::loadNewCertificate(const std::string& certFile, const std::string& keyFile, bool active, bool reload) { DNSCryptCert newCert; DNSCryptPrivateKey newPrivateKey; @@ -309,7 +315,14 @@ void DNSCryptContext::loadNewCertificate(const std::string& certFile, const std: loadCertFromFile(certFile, newCert); newPrivateKey.loadFromFile(keyFile); - addNewCertificate(newCert, newPrivateKey, active); + addNewCertificate(newCert, newPrivateKey, active, reload); + certificatePath = certFile; + keyPath = keyFile; +} + +void DNSCryptContext::reloadCertificate() +{ + loadNewCertificate(certificatePath, keyPath, true, true); } void DNSCryptContext::markActive(uint32_t serial) diff --git a/pdns/dnscrypt.hh b/pdns/dnscrypt.hh index 307784cb80..86ddcd2015 100644 --- a/pdns/dnscrypt.hh +++ b/pdns/dnscrypt.hh @@ -257,8 +257,9 @@ public: DNSCryptContext(const std::string& pName, const std::string& certFile, const std::string& keyFile); DNSCryptContext(const std::string& pName, const DNSCryptCert& certificate, const DNSCryptPrivateKey& pKey); - void loadNewCertificate(const std::string& certFile, const std::string& keyFile, bool active=true); - void addNewCertificate(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, bool active=true); + void reloadCertificate(); + void loadNewCertificate(const std::string& certFile, const std::string& keyFile, bool active=true, bool reload=false); + void addNewCertificate(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, bool active=true, bool reload=false); void markActive(uint32_t serial); void markInactive(uint32_t serial); void removeInactiveCertificate(uint32_t serial); @@ -276,6 +277,8 @@ private: pthread_rwlock_t d_lock; std::vector> certs; DNSName providerName; + std::string certificatePath; + std::string keyPath; }; bool generateDNSCryptCertificate(const std::string& providerPrivateKeyFile, uint32_t serial, time_t begin, time_t end, DNSCryptExchangeVersion version, DNSCryptCert& certOut, DNSCryptPrivateKey& keyOut); diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index 6ed2244b83..1ff4670caf 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -428,6 +428,7 @@ const std::vector g_consoleKeywords{ { "RCodeRule", true, "rcode", "matches responses with the specified rcode" }, { "RegexRule", true, "regex", "matches the query name against the supplied regex" }, { "registerDynBPFFilter", true, "DynBPFFilter", "register this dynamic BPF filter into the web interface so that its counters are displayed" }, + { "reloadAllCertificates", true, "", "reload all DNSCrypt and TLS certificates, along with their associated keys" }, { "RemoteLogAction", true, "RemoteLogger [, alterFunction [, serverID]]", "send the content of this query to a remote logger via Protocol Buffer. `alterFunction` is a callback, receiving a DNSQuestion and a DNSDistProtoBufMessage, that can be used to modify the Protocol Buffer content, for example for anonymization purposes. `serverID` is the server identifier." }, { "RemoteLogResponseAction", true, "RemoteLogger [,alterFunction [,includeCNAME [, serverID]]]", "send the content of this response to a remote logger via Protocol Buffer. `alterFunction` is the same callback than the one in `RemoteLogAction` and `includeCNAME` indicates whether CNAME records inside the response should be parsed and exported. The default is to only exports A and AAAA records. `serverID` is the server identifier." }, { "rmCacheHitResponseRule", true, "id", "remove cache hit response rule in position 'id', or whose uuid matches if 'id' is an UUID string" }, diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index dea393d3b3..faf002e8b7 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -1766,7 +1766,30 @@ void setupLuaConfig(bool client) #endif }); - g_lua.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse=allow; }); + g_lua.writeFunction("reloadAllCertificates", []() { + for (auto& frontend : g_frontends) { + if (!frontend) { + continue; + } + try { +#ifdef HAVE_DNSCRYPT + if (frontend->dnscryptCtx) { + frontend->dnscryptCtx->reloadCertificate(); + } +#endif /* HAVE_DNSCRYPT */ +#ifdef HAVE_DNS_OVER_TLS + if (frontend->tlsFrontend) { + frontend->tlsFrontend->setupTLS(); + } +#endif /* HAVE_DNS_OVER_TLS */ + } + catch(const std::exception& e) { + errlog("Error reloading certificates for frontend %s: %s", frontend->local.toStringWithPort(), e.what()); + } + } + }); + + g_lua.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse=allow; }); } vector> setupLua(bool client, const std::string& config) diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 62604d792d..6a366f1982 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -42,6 +42,12 @@ Global configuration :param str path: The directory to load configuration files from. Each file must end in ``.conf``. +.. function:: reloadAllCertificates() + + .. versionadded:: 1.4.0 + + Reload all DNSCrypt and TLS certificates, along with their associated keys. + Listen Sockets ~~~~~~~~~~~~~~