]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
GnuTLS: support for TLS session resume
authorAmos Jeffries <squid3@treenet.co.nz>
Thu, 30 Jun 2016 22:10:55 +0000 (10:10 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Thu, 30 Jun 2016 22:10:55 +0000 (10:10 +1200)
src/CachePeer.cc
src/CachePeer.h
src/adaptation/icap/ServiceRep.cc
src/adaptation/icap/ServiceRep.h
src/adaptation/icap/Xaction.cc
src/client_side.cc
src/security/Session.cc
src/security/Session.h
src/ssl/BlindPeerConnector.cc

index fac6a3e5ba1da99042476ce452b7db4b798e58ba..964948ad5b15e3df0d6e2db69f84b6ce0b299f74 100644 (file)
@@ -42,7 +42,6 @@ CachePeer::CachePeer() :
     domain(NULL),
 #if USE_OPENSSL
     sslContext(NULL),
-    sslSession(NULL),
 #endif
     front_end_https(0),
     connection_auth(2 /* auto */)
@@ -102,9 +101,6 @@ CachePeer::~CachePeer()
 #if USE_OPENSSL
     if (sslContext)
         SSL_CTX_free(sslContext);
-
-    if (sslSession)
-        SSL_SESSION_free(sslSession);
 #endif
 }
 
index 848150df31fa8e97c9547029f49b635af64d8361..67a6302ae399c53d83c0da696c3a2404ebda120b 100644 (file)
@@ -184,9 +184,7 @@ public:
     /// security settings for peer connection
     Security::PeerOptions secure;
     Security::ContextPtr sslContext;
-#if USE_OPENSSL
-    SSL_SESSION *sslSession;
-#endif
+    Security::SessionStatePointer sslSession;
 
     int front_end_https;
     int connection_auth;
index 7aec5ca4f2f623f7a076f7bb8518d80aab71a8f1..14996a7fa8226e92bd305353b4c7c8cfc97df78d 100644 (file)
@@ -34,9 +34,6 @@ CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, ServiceRep);
 Adaptation::Icap::ServiceRep::ServiceRep(const ServiceConfigPointer &svcCfg):
     AsyncJob("Adaptation::Icap::ServiceRep"), Adaptation::Service(svcCfg),
     sslContext(NULL),
-#if USE_OPENSSL
-    sslSession(NULL),
-#endif
     theOptions(NULL), theOptionsFetcher(0), theLastUpdate(0),
     theBusyConns(0),
     theAllWaiters(0),
index 39e9bf57b02d0a84477b55c31b271019c302c212..579bfbd574f84126b97d6f65493cf09c717a5bfc 100644 (file)
@@ -111,9 +111,7 @@ public: // treat these as private, they are for callbacks only
     virtual void noteAdaptationAnswer(const Answer &answer);
 
     Security::ContextPtr sslContext;
-#if USE_OPENSSL
-    SSL_SESSION *sslSession;
-#endif
+    Security::SessionStatePointer sslSession;
 
 private:
     // stores Prepare() callback info
index 89a942c15a57f861ab3ac3038f47ea9ffaf906d0..bb96bf2808c4acdd7e99564440291774c35d7eef 100644 (file)
@@ -725,8 +725,7 @@ Ssl::IcapPeerConnector::initializeSsl()
     if (check)
         check->dst_peer_name = *host;
 
-    if (icapService->sslSession)
-        SSL_set_session(ssl, icapService->sslSession);
+    Security::GetSessionResumeData(Security::SessionPointer(ssl), icapService->sslSession);
 
     return ssl;
 }
@@ -738,13 +737,7 @@ Ssl::IcapPeerConnector::noteNegotiationDone(ErrorState *error)
         return;
 
     const int fd = serverConnection()->fd;
-    auto ssl = fd_table[fd].ssl.get();
-    assert(ssl);
-    if (!SSL_session_reused(ssl)) {
-        if (icapService->sslSession)
-            SSL_SESSION_free(icapService->sslSession);
-        icapService->sslSession = SSL_get1_session(ssl);
-    }
+    Security::GetSessionResumeData(fd_table[fd].ssl, icapService->sslSession);
 }
 
 void
index ed11862591820608eb4f73a7678d0fca2c220b9d..92d0c8bb3747efec1ab03332c2d21b5719a9193b 100644 (file)
@@ -2650,7 +2650,7 @@ clientNegotiateSSL(int fd, void *data)
         return;
     }
 
-    if (SSL_session_reused(ssl)) {
+    if (Security::SessionIsResumed(fd_table[fd].ssl)) {
         debugs(83, 2, "clientNegotiateSSL: Session " << SSL_get_session(ssl) <<
                " reused on FD " << fd << " (" << fd_table[fd].ipaddr << ":" << (int)fd_table[fd].remote_port << ")");
     } else {
index 38480c14385b0f560c5b517e5ba149eeb440ee4f..ae6fc3c919eeb260b9cea0cdcbeebc124cd8acdf 100644 (file)
 #define SSL_SESSION_ID_SIZE 32
 #define SSL_SESSION_MAX_SIZE 10*1024
 
+bool
+Security::SessionIsResumed(const Security::SessionPointer &s)
+{
+    return
+#if USE_OPENSSL
+        SSL_session_reused(s.get()) == 1;
+#elif USE_GNUTLS
+        gnutls_session_is_resumed(s.get()) != 0;
+#else
+        false;
+#endif
+}
+
+void
+Security::GetSessionResumeData(const Security::SessionPointer &s, Security::SessionStatePointer &data)
+{
+    if (!SessionIsResumed(s)) {
+#if USE_OPENSSL
+        data.reset(SSL_get1_session(s.get()));
+#elif USE_GNUTLS
+        gnutls_datum_t *tmp = nullptr;
+        (void)gnutls_session_get_data2(s.get(), tmp);
+        data.reset(tmp);
+#endif
+    }
+}
+
+void
+Security::SetSessionResumeData(const Security::SessionPtr &s, const Security::SessionStatePointer &data)
+{
+    if (s) {
+#if USE_OPENSSL
+        (void)SSL_set_session(s, data.get());
+#elif USE_GNUTLS
+        (void)gnutls_session_set_data(s, data->data, data->size);
+#endif
+    }
+}
+
 static bool
 isTlsServer()
 {
index d3855dc0cf60ddb0212d116c4f8a9ae22f0950cd..b360967b377b083d9ec44f9b3a25506f89c03d85 100644 (file)
@@ -31,6 +31,10 @@ typedef SSL* SessionPtr;
 CtoCpp1(SSL_free, SSL *);
 typedef LockingPointer<SSL, Security::SSL_free_cpp, CRYPTO_LOCK_SSL> SessionPointer;
 
+typedef SSL_SESSION* SessionStatePtr;
+CtoCpp1(SSL_SESSION_free, SSL_SESSION *);
+typedef LockingPointer<SSL_SESSION, Security::SSL_SESSION_free_cpp, CRYPTO_LOCK_SSL_SESSION> SessionStatePointer;
+
 #elif USE_GNUTLS
 typedef gnutls_session_t SessionPtr;
 CtoCpp1(gnutls_deinit, gnutls_session_t);
@@ -40,13 +44,28 @@ CtoCpp1(gnutls_deinit, gnutls_session_t);
 // library functions
 typedef TidyPointer<struct gnutls_session_int, Security::gnutls_deinit_cpp> SessionPointer;
 
+typedef gnutls_datum_t *SessionStatePtr;
+CtoCpp1(gnutls_free, gnutls_datum_t *);
+typedef TidyPointer<gnutls_datum_t, Security::gnutls_free_cpp> SessionStatePointer;
+
 #else
 // use void* so we can check against NULL
 typedef void* SessionPtr;
 typedef TidyPointer<void, nullptr> SessionPointer;
+typedef TidyPointer<void, nullptr> SessionStatePointer;
 
 #endif
 
+/// whether the session is a resumed one
+bool SessionIsResumed(const Security::SessionPointer &);
+
+/// Retrieve the data needed to resume this session on a later connection
+void GetSessionResumeData(const Security::SessionPointer &, Security::SessionStatePointer &);
+
+/// Set the data for resuming a previous session.
+/// Needs to be done before using the SessionPointer for a handshake.
+void SetSessionResumeData(const Security::SessionPtr &, const Security::SessionStatePointer &);
+
 } // namespace Security
 
 #endif /* SQUID_SRC_SECURITY_SESSION_H */
index 02523304c636e40e71fe7da3587009a1898c34aa..97cb67a79bf5f116028fa90ed36ae7adfb00aeb4 100644 (file)
@@ -46,8 +46,7 @@ Ssl::BlindPeerConnector::initializeSsl()
         SBuf *host = new SBuf(peer->secure.sslDomain);
         SSL_set_ex_data(ssl, ssl_ex_index_server, host);
 
-        if (peer->sslSession)
-            SSL_set_session(ssl, peer->sslSession);
+        Security::SetSessionResumeData(ssl, peer->sslSession);
     } else {
         SBuf *hostName = new SBuf(request->url.host());
         SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostName);
@@ -70,13 +69,9 @@ Ssl::BlindPeerConnector::noteNegotiationDone(ErrorState *error)
         return;
     }
 
-    const int fd = serverConnection()->fd;
-    Security::SessionPtr ssl = fd_table[fd].ssl.get();
-    if (serverConnection()->getPeer() && !SSL_session_reused(ssl)) {
-        if (serverConnection()->getPeer()->sslSession)
-            SSL_SESSION_free(serverConnection()->getPeer()->sslSession);
-
-        serverConnection()->getPeer()->sslSession = SSL_get1_session(ssl);
+    if (auto *peer = serverConnection()->getPeer()) {
+        const int fd = serverConnection()->fd;
+        Security::GetSessionResumeData(fd_table[fd].ssl, peer->sslSession);
     }
 }