From: Amos Jeffries Date: Thu, 30 Jun 2016 22:10:55 +0000 (+1200) Subject: GnuTLS: support for TLS session resume X-Git-Tag: SQUID_4_0_12~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0c07c030fb9c2e74a8e37235ff0809b64e8a1350;p=thirdparty%2Fsquid.git GnuTLS: support for TLS session resume --- diff --git a/src/CachePeer.cc b/src/CachePeer.cc index fac6a3e5ba..964948ad5b 100644 --- a/src/CachePeer.cc +++ b/src/CachePeer.cc @@ -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 } diff --git a/src/CachePeer.h b/src/CachePeer.h index 848150df31..67a6302ae3 100644 --- a/src/CachePeer.h +++ b/src/CachePeer.h @@ -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; diff --git a/src/adaptation/icap/ServiceRep.cc b/src/adaptation/icap/ServiceRep.cc index 7aec5ca4f2..14996a7fa8 100644 --- a/src/adaptation/icap/ServiceRep.cc +++ b/src/adaptation/icap/ServiceRep.cc @@ -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), diff --git a/src/adaptation/icap/ServiceRep.h b/src/adaptation/icap/ServiceRep.h index 39e9bf57b0..579bfbd574 100644 --- a/src/adaptation/icap/ServiceRep.h +++ b/src/adaptation/icap/ServiceRep.h @@ -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 diff --git a/src/adaptation/icap/Xaction.cc b/src/adaptation/icap/Xaction.cc index 89a942c15a..bb96bf2808 100644 --- a/src/adaptation/icap/Xaction.cc +++ b/src/adaptation/icap/Xaction.cc @@ -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 diff --git a/src/client_side.cc b/src/client_side.cc index ed11862591..92d0c8bb37 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -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 { diff --git a/src/security/Session.cc b/src/security/Session.cc index 38480c1438..ae6fc3c919 100644 --- a/src/security/Session.cc +++ b/src/security/Session.cc @@ -16,6 +16,45 @@ #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() { diff --git a/src/security/Session.h b/src/security/Session.h index d3855dc0cf..b360967b37 100644 --- a/src/security/Session.h +++ b/src/security/Session.h @@ -31,6 +31,10 @@ typedef SSL* SessionPtr; CtoCpp1(SSL_free, SSL *); typedef LockingPointer SessionPointer; +typedef SSL_SESSION* SessionStatePtr; +CtoCpp1(SSL_SESSION_free, SSL_SESSION *); +typedef LockingPointer 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 SessionPointer; +typedef gnutls_datum_t *SessionStatePtr; +CtoCpp1(gnutls_free, gnutls_datum_t *); +typedef TidyPointer SessionStatePointer; + #else // use void* so we can check against NULL typedef void* SessionPtr; typedef TidyPointer SessionPointer; +typedef TidyPointer 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 */ diff --git a/src/ssl/BlindPeerConnector.cc b/src/ssl/BlindPeerConnector.cc index 02523304c6..97cb67a79b 100644 --- a/src/ssl/BlindPeerConnector.cc +++ b/src/ssl/BlindPeerConnector.cc @@ -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); } }