]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Accept more than one TLS ticket from the same connection
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 25 Aug 2021 12:06:49 +0000 (14:06 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 13 Sep 2021 13:28:27 +0000 (15:28 +0200)
pdns/dnsdistdist/dnsdist-session-cache.cc
pdns/dnsdistdist/dnsdist-session-cache.hh
pdns/dnsdistdist/dnsdist-tcp-downstream.cc
pdns/dnsdistdist/dnsdist-tcp-downstream.hh
pdns/dnsdistdist/test-dnsdisttcp_cc.cc
pdns/tcpiohandler.cc
pdns/tcpiohandler.hh

index 67de19536048c05a3bb5525dfcd7a096dfc058a1..18d03d8d84fec8bcc260280bc9ad55130afc5d40 100644 (file)
@@ -43,18 +43,20 @@ void TLSSessionCache::cleanup(time_t now, const std::lock_guard<std::mutex>& loc
   d_nextCleanup = now + s_cleanupDelay;
 }
 
-void TLSSessionCache::putSession(const boost::uuids::uuid& backendID, time_t now, std::unique_ptr<TLSSession>&& session)
+void TLSSessionCache::putSessions(const boost::uuids::uuid& backendID, time_t now, std::vector<std::unique_ptr<TLSSession>>&& sessions)
 {
   std::lock_guard<decltype(d_lock)> lock(d_lock);
   if (d_nextCleanup == 0 || now > d_nextCleanup) {
     cleanup(now, lock);
   }
 
-  auto& entry = d_sessions[backendID];
-  if (entry.d_sessions.size() >= s_maxSessionsPerBackend) {
-    entry.d_sessions.pop_back();
+  for (auto& session : sessions) {
+    auto& entry = d_sessions[backendID];
+    if (entry.d_sessions.size() >= s_maxSessionsPerBackend) {
+      entry.d_sessions.pop_back();
+    }
+    entry.d_sessions.push_front(std::move(session));
   }
-  entry.d_sessions.push_front(std::move(session));
 }
 
 std::unique_ptr<TLSSession> TLSSessionCache::getSession(const boost::uuids::uuid& backendID, time_t now)
index 6cae14034bbba47b1bb254a4fc65ad03c8001c51..0c523b1b6a95809bbe9a4d3e45e8298bdd428970 100644 (file)
@@ -35,7 +35,7 @@ public:
   }
   void cleanup(time_t now, const std::lock_guard<std::mutex>& lock);
 
-  void putSession(const boost::uuids::uuid& backendID, time_t now, std::unique_ptr<TLSSession>&& session);
+  void putSessions(const boost::uuids::uuid& backendID, time_t now, std::vector<std::unique_ptr<TLSSession>>&& sessions);
   std::unique_ptr<TLSSession> getSession(const boost::uuids::uuid& backendID, time_t now);
 
   static void setCleanupDelay(time_t delay)
index c097fe826331d6e46c68d79a3bcefb4c644ebf5c..da37224087d990437189121e83288a76b8e9e2c4 100644 (file)
@@ -21,9 +21,9 @@ TCPConnectionToBackend::~TCPConnectionToBackend()
         ++d_ds->tlsResumptions;
       }
       try {
-        auto session = d_handler->getTLSSession();
-        if (session) {
-          g_sessionCache.putSession(d_ds->getID(), now.tv_sec, std::move(session));
+        auto sessions = d_handler->getTLSSessions();
+        if (!sessions.empty()) {
+          g_sessionCache.putSessions(d_ds->getID(), now.tv_sec, std::move(sessions));
         }
       }
       catch (const std::exception& e) {
@@ -343,7 +343,14 @@ bool TCPConnectionToBackend::reconnect()
         ++d_ds->tlsResumptions;
       }
       try {
-        tlsSession = d_handler->getTLSSession();
+        auto sessions = d_handler->getTLSSessions();
+        if (!sessions.empty()) {
+          tlsSession = std::move(sessions.back());
+          sessions.pop_back();
+          if (!sessions.empty()) {
+            g_sessionCache.putSessions(d_ds->getID(), time(nullptr), std::move(sessions));
+          }
+        }
       }
       catch (const std::exception& e) {
         vinfolog("Unable to get a TLS session to resume: %s", e.what());
index aafbd3dd90df80d20d4f9bea61d0d2d30b3d6963..a34258cb9005873b62a11139c4d0bc04ed73aba0 100644 (file)
@@ -192,7 +192,6 @@ protected:
   }
 
   PacketBuffer d_responseBuffer;
-#warning we do not need this and could append to the outgoing buffer right away but is it better?
   std::deque<TCPQuery> d_pendingQueries;
   std::unordered_map<uint16_t, TCPQuery> d_pendingResponses;
   std::unique_ptr<FDMultiplexer>& d_mplexer;
index 7ea89e2b87ff5768997b9cc0e3ae3bbcfec35e0a..884780b28c383db76d3db75187846b9c8c586129 100644 (file)
@@ -242,9 +242,9 @@ public:
     return false;
   }
 
-  std::unique_ptr<TLSSession> getSession() override
+  std::vector<std::unique_ptr<TLSSession>> getSessions() override
   {
-    return nullptr;
+    return {};
   }
 
   void setSession(std::unique_ptr<TLSSession>& session) override
index e957d66bbe888338844717ffcf4e0095767eb2e5..0bc0d7376f82308aa9e69c3c3ec17ea9b50ea0ee 100644 (file)
@@ -456,13 +456,9 @@ public:
     return false;
   }
 
-  std::unique_ptr<TLSSession> getSession() override
+  std::vector<std::unique_ptr<TLSSession>> getSessions() override
   {
-    if (d_tlsSession) {
-      return std::move(d_tlsSession);
-    }
-
-    throw std::runtime_error("Unable to get an OpenSSL session");
+    return std::move(d_tlsSessions);
   }
 
   void setSession(std::unique_ptr<TLSSession>& session) override
@@ -480,9 +476,9 @@ public:
     native.release();
   }
 
-  void setNewTicket(SSL_SESSION* session)
+  void addNewTicket(SSL_SESSION* session)
   {
-    d_tlsSession = std::unique_ptr<TLSSession>(new OpenSSLSession(std::unique_ptr<SSL_SESSION, void(*)(SSL_SESSION*)>(session, SSL_SESSION_free)));
+    d_tlsSessions.push_back(std::unique_ptr<TLSSession>(new OpenSSLSession(std::unique_ptr<SSL_SESSION, void(*)(SSL_SESSION*)>(session, SSL_SESSION_free))));
   }
 
   static int s_tlsConnIndex;
@@ -490,9 +486,9 @@ public:
 private:
   static std::atomic_flag s_initTLSConnIndex;
 
+  std::vector<std::unique_ptr<TLSSession>> d_tlsSessions;
   std::shared_ptr<OpenSSLFrontendContext> d_feContext;
   std::unique_ptr<SSL, void(*)(SSL*)> d_conn;
-  std::unique_ptr<TLSSession> d_tlsSession{nullptr};
   std::string d_hostname;
   struct timeval d_timeout;
 };
@@ -652,7 +648,7 @@ public:
       return 0;
     }
 
-    conn->setNewTicket(session);
+    conn->addNewTicket(session);
     return 1;
   }
 
@@ -1007,7 +1003,7 @@ public:
     if (ret != GNUTLS_E_SUCCESS || sess.size <= 4) {
       throw std::runtime_error("Error getting GnuTLSSession: " + std::string(gnutls_strerror(ret)));
     }
-    conn->d_tlsSession = std::unique_ptr<TLSSession>(new GnuTLSSession(sess));
+    conn->d_tlsSessions.push_back(std::unique_ptr<TLSSession>(new GnuTLSSession(sess)));
     return 0;
   }
 
@@ -1360,13 +1356,9 @@ public:
     return false;
   }
 
-  std::unique_ptr<TLSSession> getSession() override
+  std::vector<std::unique_ptr<TLSSession>> getSessions() override
   {
-    if (d_tlsSession) {
-      return std::move(d_tlsSession);
-    }
-
-    throw std::runtime_error("No GnuTLSSession available yet");
+    return std::move(d_tlsSessions);
   }
 
   void setSession(std::unique_ptr<TLSSession>& session) override
@@ -1406,9 +1398,9 @@ public:
   }
 
 private:
+  std::vector<std::unique_ptr<TLSSession>> d_tlsSessions;
   std::shared_ptr<GnuTLSTicketsKey> d_ticketsKey;
   std::unique_ptr<gnutls_session_int, void(*)(gnutls_session_t)> d_conn;
-  std::unique_ptr<TLSSession> d_tlsSession{nullptr};
   std::string d_host;
   bool d_client{false};
   bool d_handshakeDone{false};
index fcde2c62ae13ec1692f4d4cc90c353d6df5448a4..b531466b5f09b56704c1cf11aec07eb0eff7773f 100644 (file)
@@ -36,7 +36,7 @@ public:
   virtual std::vector<uint8_t> getNextProtocol() const = 0;
   virtual LibsslTLSVersion getTLSVersion() const = 0;
   virtual bool hasSessionBeenResumed() const = 0;
-  virtual std::unique_ptr<TLSSession> getSession() = 0;
+  virtual std::vector<std::unique_ptr<TLSSession>> getSessions() = 0;
   virtual void setSession(std::unique_ptr<TLSSession>& session) = 0;
   virtual void close() = 0;
 
@@ -521,13 +521,13 @@ public:
     }
   }
 
-  std::unique_ptr<TLSSession> getTLSSession()
+  std::vector<std::unique_ptr<TLSSession>> getTLSSessions()
   {
     if (!d_conn) {
-      throw std::runtime_error("Trying to get a TLS session from a non-TLS handler");
+      throw std::runtime_error("Trying to get TLS sessions from a non-TLS handler");
     }
 
-    return d_conn->getSession();
+    return d_conn->getSessions();
   }
 
 private: