mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-17 15:14:48 +02:00
#3880: NetSSL_OpenSSL: Support session resumption with TLSv1.3
This commit is contained in:
parent
a9ad113742
commit
8f764e3505
@ -287,6 +287,10 @@ protected:
|
|||||||
/// Returns the index for SSL_CTX_set_ex_data() and SSL_CTX_get_ex_data() to
|
/// Returns the index for SSL_CTX_set_ex_data() and SSL_CTX_get_ex_data() to
|
||||||
/// store the Context* in the underlying SSL_CTX.
|
/// store the Context* in the underlying SSL_CTX.
|
||||||
|
|
||||||
|
int socketIndex() const;
|
||||||
|
/// Returns the index for SSL_set_ex_data() and SSL_get_ex_data() to
|
||||||
|
/// store the SecureSocketImpl* in the underlying SSL.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SSLManager();
|
SSLManager();
|
||||||
/// Creates the SSLManager.
|
/// Creates the SSLManager.
|
||||||
@ -320,6 +324,7 @@ private:
|
|||||||
PrivateKeyPassphraseHandlerPtr _ptrClientPassphraseHandler;
|
PrivateKeyPassphraseHandlerPtr _ptrClientPassphraseHandler;
|
||||||
InvalidCertificateHandlerPtr _ptrClientCertificateHandler;
|
InvalidCertificateHandlerPtr _ptrClientCertificateHandler;
|
||||||
int _contextIndex;
|
int _contextIndex;
|
||||||
|
int _socketIndex;
|
||||||
Poco::FastMutex _mutex;
|
Poco::FastMutex _mutex;
|
||||||
|
|
||||||
static const std::string CFG_PRIV_KEY_FILE;
|
static const std::string CFG_PRIV_KEY_FILE;
|
||||||
@ -359,6 +364,7 @@ private:
|
|||||||
|
|
||||||
friend class Poco::SingletonHolder<SSLManager>;
|
friend class Poco::SingletonHolder<SSLManager>;
|
||||||
friend class Context;
|
friend class Context;
|
||||||
|
friend class SecureSocketImpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -405,6 +411,12 @@ inline int SSLManager::contextIndex() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline int SSLManager::socketIndex() const
|
||||||
|
{
|
||||||
|
return _socketIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Net
|
} } // namespace Poco::Net
|
||||||
|
|
||||||
|
|
||||||
|
@ -280,6 +280,9 @@ protected:
|
|||||||
/// Note that simply closing a socket is not sufficient
|
/// Note that simply closing a socket is not sufficient
|
||||||
/// to be able to re-use it again.
|
/// to be able to re-use it again.
|
||||||
|
|
||||||
|
static int onSessionCreated(SSL* pSSL, SSL_SESSION* pSession);
|
||||||
|
/// Callback to handle new session data sent by server.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SecureSocketImpl(const SecureSocketImpl&);
|
SecureSocketImpl(const SecureSocketImpl&);
|
||||||
SecureSocketImpl& operator = (const SecureSocketImpl&);
|
SecureSocketImpl& operator = (const SecureSocketImpl&);
|
||||||
@ -293,6 +296,7 @@ private:
|
|||||||
bool _bidirectShutdown = true;
|
bool _bidirectShutdown = true;
|
||||||
|
|
||||||
friend class SecureStreamSocketImpl;
|
friend class SecureStreamSocketImpl;
|
||||||
|
friend class Context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,6 +42,9 @@ public:
|
|||||||
SSL_SESSION* sslSession() const;
|
SSL_SESSION* sslSession() const;
|
||||||
/// Returns the stored OpenSSL SSL_SESSION object.
|
/// Returns the stored OpenSSL SSL_SESSION object.
|
||||||
|
|
||||||
|
bool isResumable() const;
|
||||||
|
/// Returns true if the session is resumable.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Session(SSL_SESSION* pSession);
|
Session(SSL_SESSION* pSession);
|
||||||
/// Creates a new Session object, using the given
|
/// Creates a new Session object, using the given
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "Poco/Net/Context.h"
|
#include "Poco/Net/Context.h"
|
||||||
#include "Poco/Net/SSLManager.h"
|
#include "Poco/Net/SSLManager.h"
|
||||||
#include "Poco/Net/SSLException.h"
|
#include "Poco/Net/SSLException.h"
|
||||||
|
#include "Poco/Net/SecureSocketImpl.h"
|
||||||
#include "Poco/Net/Utility.h"
|
#include "Poco/Net/Utility.h"
|
||||||
#include "Poco/Crypto/OpenSSLInitializer.h"
|
#include "Poco/Crypto/OpenSSLInitializer.h"
|
||||||
#include "Poco/File.h"
|
#include "Poco/File.h"
|
||||||
@ -195,6 +196,11 @@ void Context::init(const Params& params)
|
|||||||
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
|
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
|
||||||
SSL_CTX_set_ex_data(_pSSLContext, SSLManager::instance().contextIndex(), this);
|
SSL_CTX_set_ex_data(_pSSLContext, SSLManager::instance().contextIndex(), this);
|
||||||
|
|
||||||
|
if (!isForServerUse())
|
||||||
|
{
|
||||||
|
SSL_CTX_sess_set_new_cb(_pSSLContext, &SecureSocketImpl::onSessionCreated);
|
||||||
|
}
|
||||||
|
|
||||||
if (!isForServerUse() && params.ocspStaplingVerification)
|
if (!isForServerUse() && params.ocspStaplingVerification)
|
||||||
{
|
{
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "Poco/Net/SecureSocketImpl.h"
|
#include "Poco/Net/SecureSocketImpl.h"
|
||||||
#include "Poco/Net/SSLException.h"
|
#include "Poco/Net/SSLException.h"
|
||||||
|
#include "Poco/Net/SSLManager.h"
|
||||||
#include "Poco/Net/Context.h"
|
#include "Poco/Net/Context.h"
|
||||||
#include "Poco/Net/X509Certificate.h"
|
#include "Poco/Net/X509Certificate.h"
|
||||||
#include "Poco/Net/Utility.h"
|
#include "Poco/Net/Utility.h"
|
||||||
@ -97,6 +98,7 @@ void SecureSocketImpl::acceptSSL()
|
|||||||
}
|
}
|
||||||
SSL_set_bio(_pSSL, pBIO, pBIO);
|
SSL_set_bio(_pSSL, pBIO, pBIO);
|
||||||
SSL_set_accept_state(_pSSL);
|
SSL_set_accept_state(_pSSL);
|
||||||
|
SSL_set_ex_data(_pSSL, SSLManager::instance().socketIndex(), this);
|
||||||
_needHandshake = true;
|
_needHandshake = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +158,7 @@ void SecureSocketImpl::connectSSL(bool performHandshake)
|
|||||||
throw SSLException("Cannot create SSL object");
|
throw SSLException("Cannot create SSL object");
|
||||||
}
|
}
|
||||||
SSL_set_bio(_pSSL, pBIO, pBIO);
|
SSL_set_bio(_pSSL, pBIO, pBIO);
|
||||||
|
SSL_set_ex_data(_pSSL, SSLManager::instance().socketIndex(), this);
|
||||||
|
|
||||||
if (!_peerHostName.empty())
|
if (!_peerHostName.empty())
|
||||||
{
|
{
|
||||||
@ -169,7 +172,7 @@ void SecureSocketImpl::connectSSL(bool performHandshake)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_pSession)
|
if (_pSession && _pSession->isResumable())
|
||||||
{
|
{
|
||||||
SSL_set_session(_pSSL, _pSession->sslSession());
|
SSL_set_session(_pSSL, _pSession->sslSession());
|
||||||
}
|
}
|
||||||
@ -609,6 +612,7 @@ void SecureSocketImpl::reset()
|
|||||||
close();
|
close();
|
||||||
if (_pSSL)
|
if (_pSSL)
|
||||||
{
|
{
|
||||||
|
SSL_set_ex_data(_pSSL, SSLManager::instance().socketIndex(), nullptr);
|
||||||
SSL_free(_pSSL);
|
SSL_free(_pSSL);
|
||||||
_pSSL = 0;
|
_pSSL = 0;
|
||||||
}
|
}
|
||||||
@ -623,20 +627,7 @@ void SecureSocketImpl::abort()
|
|||||||
|
|
||||||
Session::Ptr SecureSocketImpl::currentSession()
|
Session::Ptr SecureSocketImpl::currentSession()
|
||||||
{
|
{
|
||||||
if (_pSSL)
|
return _pSession;
|
||||||
{
|
|
||||||
SSL_SESSION* pSession = SSL_get1_session(_pSSL);
|
|
||||||
if (pSession)
|
|
||||||
{
|
|
||||||
if (_pSession && pSession == _pSession->sslSession())
|
|
||||||
{
|
|
||||||
SSL_SESSION_free(pSession);
|
|
||||||
return _pSession;
|
|
||||||
}
|
|
||||||
else return new Session(pSession);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -655,4 +646,17 @@ bool SecureSocketImpl::sessionWasReused()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SecureSocketImpl::onSessionCreated(SSL* pSSL, SSL_SESSION* pSession)
|
||||||
|
{
|
||||||
|
void* pEx = SSL_get_ex_data(pSSL, SSLManager::instance().socketIndex());
|
||||||
|
if (pEx)
|
||||||
|
{
|
||||||
|
SecureSocketImpl* pThis = reinterpret_cast<SecureSocketImpl*>(pEx);
|
||||||
|
pThis->_pSession = new Session(pSession);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Net
|
} } // namespace Poco::Net
|
||||||
|
@ -12,13 +12,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
// Some OpenSSL functions are deprecated in OS X 10.7
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include "Poco/Net/Session.h"
|
#include "Poco/Net/Session.h"
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@ -37,4 +32,14 @@ Session::~Session()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Session::isResumable() const
|
||||||
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
|
||||||
|
return SSL_SESSION_is_resumable(_pSession) == 1;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Net
|
} } // namespace Poco::Net
|
||||||
|
@ -370,15 +370,15 @@ void TCPServerTest::testReuseSession()
|
|||||||
|
|
||||||
ss1.useSession(pSession);
|
ss1.useSession(pSession);
|
||||||
ss1.connect(sa);
|
ss1.connect(sa);
|
||||||
assertTrue (ss1.sessionWasReused());
|
|
||||||
assertTrue (ss1.currentSession() == pSession);
|
|
||||||
ss1.sendBytes(data.data(), (int) data.size());
|
ss1.sendBytes(data.data(), (int) data.size());
|
||||||
n = ss1.receiveBytes(buffer, sizeof(buffer));
|
n = ss1.receiveBytes(buffer, sizeof(buffer));
|
||||||
|
assertTrue (ss1.sessionWasReused());
|
||||||
assertTrue (n > 0);
|
assertTrue (n > 0);
|
||||||
assertTrue (std::string(buffer, n) == data);
|
assertTrue (std::string(buffer, n) == data);
|
||||||
assertTrue (srv.currentConnections() == 1);
|
assertTrue (srv.currentConnections() == 1);
|
||||||
assertTrue (srv.queuedConnections() == 0);
|
assertTrue (srv.queuedConnections() == 0);
|
||||||
assertTrue (srv.totalConnections() == 2);
|
assertTrue (srv.totalConnections() == 2);
|
||||||
|
pSession = ss1.currentSession();
|
||||||
ss1.close();
|
ss1.close();
|
||||||
Thread::sleep(300);
|
Thread::sleep(300);
|
||||||
assertTrue (srv.currentConnections() == 0);
|
assertTrue (srv.currentConnections() == 0);
|
||||||
@ -388,10 +388,9 @@ void TCPServerTest::testReuseSession()
|
|||||||
|
|
||||||
ss1.useSession(pSession);
|
ss1.useSession(pSession);
|
||||||
ss1.connect(sa);
|
ss1.connect(sa);
|
||||||
assertTrue (!ss1.sessionWasReused());
|
|
||||||
assertTrue (ss1.currentSession() != pSession);
|
|
||||||
ss1.sendBytes(data.data(), (int) data.size());
|
ss1.sendBytes(data.data(), (int) data.size());
|
||||||
n = ss1.receiveBytes(buffer, sizeof(buffer));
|
n = ss1.receiveBytes(buffer, sizeof(buffer));
|
||||||
|
assertTrue (!ss1.sessionWasReused());
|
||||||
assertTrue (n > 0);
|
assertTrue (n > 0);
|
||||||
assertTrue (std::string(buffer, n) == data);
|
assertTrue (std::string(buffer, n) == data);
|
||||||
assertTrue (srv.currentConnections() == 1);
|
assertTrue (srv.currentConnections() == 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user