4435 secure sock thread (#4512)

* fix(SecureSocket): Refactor detection of timeout when reading, writing or handshaking. (#3725)

* enh(SecureSocket): some trivial C++17 modernisation changes.

* chore: indentation and compiler warning

* fix(SecureSocketImpl): not thread-safe (1st attempt) #4435

* fix(SecureSocketImpl): silence CodeQL cpp/certificate-not-checked

---------

Co-authored-by: Matej Kenda <matejken@gmail.com>
This commit is contained in:
Aleksandar Fabijanic
2024-04-02 11:53:42 -05:00
committed by GitHub
parent 8d3de8a5ed
commit ece360393f
2 changed files with 43 additions and 7 deletions

View File

@@ -284,16 +284,21 @@ protected:
/// Callback to handle new session data sent by server. /// Callback to handle new session data sent by server.
private: private:
using MutexT = Poco::FastMutex;
using LockT = MutexT::ScopedLock;
using UnLockT = Poco::ScopedLockWithUnlock<MutexT>;
SecureSocketImpl(const SecureSocketImpl&); SecureSocketImpl(const SecureSocketImpl&);
SecureSocketImpl& operator = (const SecureSocketImpl&); SecureSocketImpl& operator = (const SecureSocketImpl&);
SSL* _pSSL; std::atomic<SSL*> _pSSL;
Poco::AutoPtr<SocketImpl> _pSocket; Poco::AutoPtr<SocketImpl> _pSocket;
Context::Ptr _pContext; Context::Ptr _pContext;
bool _needHandshake; bool _needHandshake;
std::string _peerHostName; std::string _peerHostName;
Session::Ptr _pSession; Session::Ptr _pSession;
bool _bidirectShutdown = true; bool _bidirectShutdown = true;
mutable MutexT _mutex;
friend class SecureStreamSocketImpl; friend class SecureStreamSocketImpl;
friend class Context; friend class Context;

View File

@@ -80,6 +80,8 @@ void SecureSocketImpl::acceptSSL()
{ {
poco_assert (!_pSSL); poco_assert (!_pSSL);
LockT l(_mutex);
BIO* pBIO = ::BIO_new(BIO_s_socket()); BIO* pBIO = ::BIO_new(BIO_s_socket());
if (!pBIO) throw SSLException("Cannot create BIO object"); if (!pBIO) throw SSLException("Cannot create BIO object");
BIO_set_fd(pBIO, static_cast<int>(_pSocket->sockfd()), BIO_NOCLOSE); BIO_set_fd(pBIO, static_cast<int>(_pSocket->sockfd()), BIO_NOCLOSE);
@@ -156,6 +158,8 @@ void SecureSocketImpl::connectSSL(bool performHandshake)
poco_assert (!_pSSL); poco_assert (!_pSSL);
poco_assert (_pSocket->initialized()); poco_assert (_pSocket->initialized());
LockT l(_mutex);
::BIO* pBIO = ::BIO_new(BIO_s_socket()); ::BIO* pBIO = ::BIO_new(BIO_s_socket());
if (!pBIO) throw SSLException("Cannot create SSL BIO object"); if (!pBIO) throw SSLException("Cannot create SSL BIO object");
BIO_set_fd(pBIO, static_cast<int>(_pSocket->sockfd()), BIO_NOCLOSE); BIO_set_fd(pBIO, static_cast<int>(_pSocket->sockfd()), BIO_NOCLOSE);
@@ -253,6 +257,8 @@ void SecureSocketImpl::shutdown()
{ {
if (_pSSL) if (_pSSL)
{ {
UnLockT l(_mutex);
// Don't shut down the socket more than once. // Don't shut down the socket more than once.
int shutdownState = ::SSL_get_shutdown(_pSSL); int shutdownState = ::SSL_get_shutdown(_pSSL);
bool shutdownSent = (shutdownState & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN; bool shutdownSent = (shutdownState & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN;
@@ -301,6 +307,9 @@ void SecureSocketImpl::shutdown()
int rc = ::SSL_shutdown(_pSSL); int rc = ::SSL_shutdown(_pSSL);
#endif #endif
if (rc < 0) handleError(rc); if (rc < 0) handleError(rc);
l.unlock();
if (_pSocket->getBlocking()) if (_pSocket->getBlocking())
{ {
_pSocket->shutdown(); _pSocket->shutdown();
@@ -345,6 +354,9 @@ int SecureSocketImpl::sendBytes(const void* buffer, int length, int flags)
poco_check_ptr (_pSSL); poco_check_ptr (_pSSL);
int rc; int rc;
LockT l(_mutex);
if (_needHandshake) if (_needHandshake)
{ {
rc = completeHandshake(); rc = completeHandshake();
@@ -381,6 +393,9 @@ int SecureSocketImpl::receiveBytes(void* buffer, int length, int flags)
poco_check_ptr (_pSSL); poco_check_ptr (_pSSL);
int rc; int rc;
LockT l(_mutex);
if (_needHandshake) if (_needHandshake)
{ {
rc = completeHandshake(); rc = completeHandshake();
@@ -414,6 +429,8 @@ int SecureSocketImpl::available() const
{ {
poco_check_ptr (_pSSL); poco_check_ptr (_pSSL);
LockT l(_mutex);
return ::SSL_pending(_pSSL); return ::SSL_pending(_pSSL);
} }
@@ -468,7 +485,7 @@ long SecureSocketImpl::verifyPeerCertificateImpl(const std::string& hostName)
{ {
Context::VerificationMode mode = _pContext->verificationMode(); Context::VerificationMode mode = _pContext->verificationMode();
if (mode == Context::VERIFY_NONE || !_pContext->extendedCertificateVerificationEnabled() || if (mode == Context::VERIFY_NONE || !_pContext->extendedCertificateVerificationEnabled() ||
(mode != Context::VERIFY_STRICT && isLocalHost(hostName))) (mode != Context::VERIFY_STRICT && isLocalHost(hostName)))
{ {
return X509_V_OK; return X509_V_OK;
} }
@@ -499,10 +516,19 @@ bool SecureSocketImpl::isLocalHost(const std::string& hostName)
X509* SecureSocketImpl::peerCertificate() const X509* SecureSocketImpl::peerCertificate() const
{ {
LockT l(_mutex);
X509* pCert = nullptr;
if (_pSSL) if (_pSSL)
return ::SSL_get_peer_certificate(_pSSL); {
else pCert = ::SSL_get_peer_certificate(_pSSL);
return nullptr; if (X509_V_OK != SSL_get_verify_result(_pSSL))
throw CertificateValidationException("SecureSocketImpl::peerCertificate(): "
"Certificate verification error " + Utility::getLastError());
}
return pCert;
} }
@@ -637,6 +663,8 @@ void SecureSocketImpl::reset()
{ {
if (_pSSL) if (_pSSL)
{ {
LockT l(_mutex);
::SSL_set_ex_data(_pSSL, SSLManager::instance().socketIndex(), nullptr); ::SSL_set_ex_data(_pSSL, SSLManager::instance().socketIndex(), nullptr);
::SSL_free(_pSSL); ::SSL_free(_pSSL);
_pSSL = nullptr; _pSSL = nullptr;
@@ -665,9 +693,12 @@ void SecureSocketImpl::useSession(Session::Ptr pSession)
bool SecureSocketImpl::sessionWasReused() bool SecureSocketImpl::sessionWasReused()
{ {
if (_pSSL) if (_pSSL)
{
LockT l(_mutex);
return ::SSL_session_reused(_pSSL) != 0; return ::SSL_session_reused(_pSSL) != 0;
else }
return false;
return false;
} }