mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-24 17:30:44 +02:00
fix(Socket): shutdown fixes from pull #3448
This commit is contained in:
@@ -126,6 +126,16 @@ public:
|
|||||||
PROTO_TLSV1_3 = 0x20
|
PROTO_TLSV1_3 = 0x20
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SecurityLevel
|
||||||
|
{
|
||||||
|
SECURITY_LEVEL_NONE = 0,
|
||||||
|
SECURITY_LEVEL_80_BITS = 1,
|
||||||
|
SECURITY_LEVEL_112_BITS = 2,
|
||||||
|
SECURITY_LEVEL_128_BITS = 3,
|
||||||
|
SECURITY_LEVEL_192_BITS = 4,
|
||||||
|
SECURITY_LEVEL_256_BITS = 5
|
||||||
|
};
|
||||||
|
|
||||||
struct NetSSL_API Params
|
struct NetSSL_API Params
|
||||||
{
|
{
|
||||||
Params();
|
Params();
|
||||||
@@ -193,6 +203,11 @@ public:
|
|||||||
/// and other TLSv1.3 ephemeral key negotiation, based
|
/// and other TLSv1.3 ephemeral key negotiation, based
|
||||||
/// on the group names defined by OpenSSL. Defaults to
|
/// on the group names defined by OpenSSL. Defaults to
|
||||||
/// "X448:X25519:ffdhe4096:ffdhe3072:ffdhe2048:ffdhe6144:ffdhe8192:P-521:P-384:P-256"
|
/// "X448:X25519:ffdhe4096:ffdhe3072:ffdhe2048:ffdhe6144:ffdhe8192:P-521:P-384:P-256"
|
||||||
|
|
||||||
|
SecurityLevel securityLevel;
|
||||||
|
/// Defines minimal number of security bits allowed.
|
||||||
|
/// Requires OpenSSL >= 1.1 to be effective.
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using InvalidCertificateHandlerPtr = Poco::SharedPtr<InvalidCertificateHandler>;
|
using InvalidCertificateHandlerPtr = Poco::SharedPtr<InvalidCertificateHandler>;
|
||||||
@@ -420,6 +435,9 @@ public:
|
|||||||
/// Returns the InvalidCertificateHandler set for this Context,
|
/// Returns the InvalidCertificateHandler set for this Context,
|
||||||
/// or a null pointer if none has been set.
|
/// or a null pointer if none has been set.
|
||||||
|
|
||||||
|
void setSecurityLevel(SecurityLevel level);
|
||||||
|
/// Sets the security level.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init(const Params& params);
|
void init(const Params& params);
|
||||||
/// Initializes the Context with the given parameters.
|
/// Initializes the Context with the given parameters.
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ public:
|
|||||||
bool isSecure() const;
|
bool isSecure() const;
|
||||||
/// Returns true if the session is FTPS.
|
/// Returns true if the session is FTPS.
|
||||||
|
|
||||||
|
void forceSessionReuse(bool force = true);
|
||||||
|
/// Enable or disable session reusing
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual StreamSocket establishDataConnection(const std::string& command, const std::string& arg);
|
virtual StreamSocket establishDataConnection(const std::string& command, const std::string& arg);
|
||||||
/// Create secure data connection
|
/// Create secure data connection
|
||||||
@@ -80,6 +83,7 @@ private:
|
|||||||
|
|
||||||
bool _enableFTPS = true;
|
bool _enableFTPS = true;
|
||||||
bool _secureDataConnection = false;
|
bool _secureDataConnection = false;
|
||||||
|
bool _forceSessionReuse = false;
|
||||||
Context::Ptr _pContext;
|
Context::Ptr _pContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,6 +99,12 @@ inline bool FTPSClientSession::isSecure() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void FTPSClientSession::forceSessionReuse(bool force)
|
||||||
|
{
|
||||||
|
_forceSessionReuse = force;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Net
|
} } // namespace Poco::Net
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ private:
|
|||||||
bool _needHandshake;
|
bool _needHandshake;
|
||||||
std::string _peerHostName;
|
std::string _peerHostName;
|
||||||
Session::Ptr _pSession;
|
Session::Ptr _pSession;
|
||||||
|
bool _bidirectShutdown = true;
|
||||||
|
|
||||||
friend class SecureStreamSocketImpl;
|
friend class SecureStreamSocketImpl;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ Context::Params::Params():
|
|||||||
loadDefaultCAs(false),
|
loadDefaultCAs(false),
|
||||||
ocspStaplingVerification(false),
|
ocspStaplingVerification(false),
|
||||||
cipherList("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"),
|
cipherList("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"),
|
||||||
dhUse2048Bits(false)
|
dhUse2048Bits(false),
|
||||||
|
securityLevel(SECURITY_LEVEL_NONE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +126,9 @@ void Context::init(const Params& params)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
int errCode = 0;
|
int errCode = 0;
|
||||||
|
|
||||||
|
setSecurityLevel(params.securityLevel);
|
||||||
|
|
||||||
if (!params.caLocation.empty())
|
if (!params.caLocation.empty())
|
||||||
{
|
{
|
||||||
Poco::File aFile(params.caLocation);
|
Poco::File aFile(params.caLocation);
|
||||||
@@ -204,6 +208,14 @@ void Context::init(const Params& params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Context::setSecurityLevel(SecurityLevel level)
|
||||||
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
|
SSL_CTX_set_security_level(_pSSLContext, static_cast<int>(level));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Context::useCertificate(const Poco::Crypto::X509Certificate& certificate)
|
void Context::useCertificate(const Poco::Crypto::X509Certificate& certificate)
|
||||||
{
|
{
|
||||||
int errCode = SSL_CTX_use_certificate(_pSSLContext, const_cast<X509*>(certificate.certificate()));
|
int errCode = SSL_CTX_use_certificate(_pSSLContext, const_cast<X509*>(certificate.certificate()));
|
||||||
|
|||||||
@@ -127,6 +127,14 @@ StreamSocket FTPSClientSession::establishDataConnection(const std::string& comma
|
|||||||
{
|
{
|
||||||
Poco::Net::SecureStreamSocket sss(Poco::Net::SecureStreamSocket::attach(ss, pSecure->context(), pSecure->currentSession()));
|
Poco::Net::SecureStreamSocket sss(Poco::Net::SecureStreamSocket::attach(ss, pSecure->context(), pSecure->currentSession()));
|
||||||
ss = sss;
|
ss = sss;
|
||||||
|
if (_forceSessionReuse)
|
||||||
|
{
|
||||||
|
sss.setLazyHandshake(false);
|
||||||
|
if (sss.completeHandshake() != 1)
|
||||||
|
throw Poco::Net::FTPException("SSL Session HANDSHAKE error");
|
||||||
|
if (!sss.sessionWasReused())
|
||||||
|
throw Poco::Net::FTPException("SSL Session for data connection was not reused");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ss;
|
return ss;
|
||||||
|
|||||||
@@ -255,7 +255,41 @@ void SecureSocketImpl::shutdown()
|
|||||||
// most web browsers, so we just set the shutdown
|
// most web browsers, so we just set the shutdown
|
||||||
// flag by calling SSL_shutdown() once and be
|
// flag by calling SSL_shutdown() once and be
|
||||||
// done with it.
|
// done with it.
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
int rc = 0;
|
||||||
|
if (!_bidirectShutdown)
|
||||||
|
rc = SSL_shutdown(_pSSL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Poco::Timespan recvTimeout = _pSocket->getReceiveTimeout();
|
||||||
|
Poco::Timespan pollTimeout(0, 100000);
|
||||||
|
Poco::Timestamp tsNow;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rc = SSL_shutdown(_pSSL);
|
||||||
|
if (rc == 1) break;
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
int err = SSL_get_error(_pSSL, rc);
|
||||||
|
if (err == SSL_ERROR_WANT_READ)
|
||||||
|
_pSocket->poll(pollTimeout, Poco::Net::Socket::SELECT_READ);
|
||||||
|
else if (err == SSL_ERROR_WANT_WRITE)
|
||||||
|
_pSocket->poll(pollTimeout, Poco::Net::Socket::SELECT_WRITE);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int socketError = SocketImpl::lastError();
|
||||||
|
long lastError = ERR_get_error();
|
||||||
|
if ((err == SSL_ERROR_SSL) && (socketError == 0) && (lastError == 0x0A000123))
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else _pSocket->poll(pollTimeout, Poco::Net::Socket::SELECT_READ);
|
||||||
|
} while (!tsNow.isElapsed(recvTimeout.totalMicroseconds()));
|
||||||
|
}
|
||||||
|
#else
|
||||||
int rc = SSL_shutdown(_pSSL);
|
int rc = SSL_shutdown(_pSSL);
|
||||||
|
#endif
|
||||||
if (rc < 0) handleError(rc);
|
if (rc < 0) handleError(rc);
|
||||||
if (_pSocket->getBlocking())
|
if (_pSocket->getBlocking())
|
||||||
{
|
{
|
||||||
@@ -328,6 +362,7 @@ int SecureSocketImpl::receiveBytes(void* buffer, int length, int flags)
|
|||||||
rc = SSL_read(_pSSL, buffer, length);
|
rc = SSL_read(_pSSL, buffer, length);
|
||||||
}
|
}
|
||||||
while (mustRetry(rc));
|
while (mustRetry(rc));
|
||||||
|
_bidirectShutdown = false;
|
||||||
if (rc <= 0)
|
if (rc <= 0)
|
||||||
{
|
{
|
||||||
return handleError(rc);
|
return handleError(rc);
|
||||||
|
|||||||
Reference in New Issue
Block a user