]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Allow edns-cookie-secret to be set to "random". 15948/head
authorMiod Vallat <miod.vallat@powerdns.com>
Wed, 30 Jul 2025 12:40:11 +0000 (14:40 +0200)
committerMiod Vallat <miod.vallat@powerdns.com>
Wed, 30 Jul 2025 13:44:44 +0000 (15:44 +0200)
Signed-off-by: Miod Vallat <miod.vallat@powerdns.com>
docs/settings.rst
pdns/auth-main.cc
regression-tests.auth-py/test_Cookies.py

index 4545d623e8cfdf8eeef31408a29a15a466649137..482ec473e21c3a84a2677b9dbaa69d2be887f75c 100644 (file)
@@ -744,6 +744,9 @@ PowerDNS will also respond with BADCOOKIE to clients that have sent only a clien
 
 This setting MUST be 32 hexadecimal characters, as the siphash algorithm's key used to create the cookie requires a 128-bit key.
 
+Alternatively, starting with version 5.0.0, this parameter can be set to
+`random`, in which case a random cookie value will be generated upon startup.
+
 .. _setting-edns-subnet-processing:
 
 ``edns-subnet-processing``
index 017285ec8f969d665655f5ec26f3374215007944..0a28e3faf31e34ac5cd93015519ba334772367b6 100644 (file)
@@ -744,15 +744,23 @@ static void mainthread()
     // User wants cookie processing
 #ifdef HAVE_CRYPTO_SHORTHASH // we can do siphash-based cookies
     DNSPacket::s_doEDNSCookieProcessing = true;
-    try {
-      if (::arg()["edns-cookie-secret"].size() != EDNSCookiesOpt::EDNSCookieSecretSize) {
-        throw std::range_error("wrong size (" + std::to_string(::arg()["edns-cookie-secret"].size()) + "), must be " + std::to_string(EDNSCookiesOpt::EDNSCookieSecretSize));
-      }
-      DNSPacket::s_EDNSCookieKey = makeBytesFromHex(::arg()["edns-cookie-secret"]);
+    const std::string& secret = ::arg()["edns-cookie-secret"];
+    if (secret == "random") {
+      std::array<char, EDNSCookiesOpt::EDNSCookieSecretSize / 2> key{};
+      dns_random(key.data(), key.size());
+      DNSPacket::s_EDNSCookieKey = std::string(key.data(), key.size());
     }
-    catch (const std::range_error& e) {
-      g_log << Logger::Error << "edns-cookie-secret invalid: " << e.what() << endl;
-      exit(1);
+    else {
+      try {
+        if (secret.size() != EDNSCookiesOpt::EDNSCookieSecretSize) {
+          throw std::range_error("wrong size (" + std::to_string(secret.size()) + "), must be " + std::to_string(EDNSCookiesOpt::EDNSCookieSecretSize));
+        }
+        DNSPacket::s_EDNSCookieKey = makeBytesFromHex(secret);
+      }
+      catch (const std::range_error& e) {
+        g_log << Logger::Error << "edns-cookie-secret invalid: " << e.what() << endl;
+        exit(1); // NOLINT(concurrency-mt-unsafe) we're single threaded at this point
+      }
     }
 #else
     g_log << Logger::Error << "Support for EDNS Cookies is not available because of missing cryptographic functions (libsodium support should be enabled, with the crypto_shorthash() function available)" << endl;
index ac85c3312b0eac2fa943ef57ed1c9497e2e0f83e..e063b48c6d1f242d9da6f456e12e90c97e41a3db 100644 (file)
@@ -3,7 +3,6 @@ import dns
 
 from authtests import AuthTest
 
-
 class TestEdnsCookies(AuthTest):
     _config_template = """
 launch={backend}
@@ -108,3 +107,9 @@ www.example.org.             3600 IN A    192.0.2.5
                 self.assertNotEqual(opt.data, opts[0].data)
                 return
         self.fail()
+
+class TestEdnsRandomCookies(TestEdnsCookies):
+    _config_template = """
+launch={backend}
+edns-cookie-secret=random
+"""