mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-04 07:27:23 +01:00
Merge pull request #4787 from pocoproject/fix-ssl-shutdown
NetSSL_OpenSSL and NetSSL_Win: non-blocking support, shutdown behavior fix
This commit is contained in:
commit
d8a423c832
@ -170,12 +170,22 @@ public:
|
|||||||
virtual void shutdownReceive();
|
virtual void shutdownReceive();
|
||||||
/// Shuts down the receiving part of the socket connection.
|
/// Shuts down the receiving part of the socket connection.
|
||||||
|
|
||||||
virtual void shutdownSend();
|
virtual int shutdownSend();
|
||||||
/// Shuts down the sending part of the socket connection.
|
/// Shuts down the sending part of the socket connection.
|
||||||
|
///
|
||||||
|
/// Returns 0 for a non-blocking socket. May return
|
||||||
|
/// a negative value for a non-blocking socket in case
|
||||||
|
/// of a TLS connection. In that case, the operation should
|
||||||
|
/// be retried once the underlying socket becomes writable.
|
||||||
|
|
||||||
virtual void shutdown();
|
virtual int shutdown();
|
||||||
/// Shuts down both the receiving and the sending part
|
/// Shuts down both the receiving and the sending part
|
||||||
/// of the socket connection.
|
/// of the socket connection.
|
||||||
|
///
|
||||||
|
/// Returns 0 for a non-blocking socket. May return
|
||||||
|
/// a negative value for a non-blocking socket in case
|
||||||
|
/// of a TLS connection. In that case, the operation should
|
||||||
|
/// be retried once the underlying socket becomes writable.
|
||||||
|
|
||||||
virtual int sendBytes(const void* buffer, int length, int flags = 0);
|
virtual int sendBytes(const void* buffer, int length, int flags = 0);
|
||||||
/// Sends the contents of the given buffer through
|
/// Sends the contents of the given buffer through
|
||||||
|
@ -157,12 +157,22 @@ public:
|
|||||||
void shutdownReceive();
|
void shutdownReceive();
|
||||||
/// Shuts down the receiving part of the socket connection.
|
/// Shuts down the receiving part of the socket connection.
|
||||||
|
|
||||||
void shutdownSend();
|
int shutdownSend();
|
||||||
/// Shuts down the sending part of the socket connection.
|
/// Shuts down the sending part of the socket connection.
|
||||||
|
///
|
||||||
|
/// Returns 0 for a non-blocking socket. May return
|
||||||
|
/// a negative value for a non-blocking socket in case
|
||||||
|
/// of a TLS connection. In that case, the operation should
|
||||||
|
/// be retried once the underlying socket becomes writable.
|
||||||
|
|
||||||
void shutdown();
|
int shutdown();
|
||||||
/// Shuts down both the receiving and the sending part
|
/// Shuts down both the receiving and the sending part
|
||||||
/// of the socket connection.
|
/// of the socket connection.
|
||||||
|
///
|
||||||
|
/// Returns 0 for a non-blocking socket. May return
|
||||||
|
/// a negative value for a non-blocking socket in case
|
||||||
|
/// of a TLS connection. In that case, the operation should
|
||||||
|
/// be retried once the underlying socket becomes writable.
|
||||||
|
|
||||||
int sendBytes(const void* buffer, int length, int flags = 0);
|
int sendBytes(const void* buffer, int length, int flags = 0);
|
||||||
/// Sends the contents of the given buffer through
|
/// Sends the contents of the given buffer through
|
||||||
|
@ -69,8 +69,8 @@ public:
|
|||||||
virtual void listen(int backlog = 64);
|
virtual void listen(int backlog = 64);
|
||||||
virtual void close();
|
virtual void close();
|
||||||
virtual void shutdownReceive();
|
virtual void shutdownReceive();
|
||||||
virtual void shutdownSend();
|
virtual int shutdownSend();
|
||||||
virtual void shutdown();
|
virtual int shutdown();
|
||||||
virtual int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0);
|
virtual int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0);
|
||||||
virtual int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0);
|
virtual int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0);
|
||||||
virtual void sendUrgent(unsigned char data);
|
virtual void sendUrgent(unsigned char data);
|
||||||
|
@ -67,10 +67,11 @@ public:
|
|||||||
|
|
||||||
response.setChunkedTransferEncoding(true);
|
response.setChunkedTransferEncoding(true);
|
||||||
response.setContentType("text/html");
|
response.setContentType("text/html");
|
||||||
|
response.set("Clear-Site-Data", "\"cookies\"");
|
||||||
|
|
||||||
std::ostream& ostr = response.send();
|
std::ostream& ostr = response.send();
|
||||||
ostr << "<html><head><title>HTTPTimeServer powered by POCO C++ Libraries</title>";
|
ostr << "<html><head><title>HTTPTimeServer powered by POCO C++ Libraries</title>";
|
||||||
ostr << "<meta http-equiv=\"refresh\" content=\"1\"></head>";
|
ostr << "</head>";
|
||||||
ostr << "<body><p style=\"text-align: center; font-size: 48px;\">";
|
ostr << "<body><p style=\"text-align: center; font-size: 48px;\">";
|
||||||
ostr << dt;
|
ostr << dt;
|
||||||
ostr << "</p></body></html>";
|
ostr << "</p></body></html>";
|
||||||
|
@ -327,21 +327,23 @@ void SocketImpl::shutdownReceive()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SocketImpl::shutdownSend()
|
int SocketImpl::shutdownSend()
|
||||||
{
|
{
|
||||||
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
|
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
|
||||||
|
|
||||||
int rc = ::shutdown(_sockfd, 1);
|
int rc = ::shutdown(_sockfd, 1);
|
||||||
if (rc != 0) error();
|
if (rc != 0) error();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SocketImpl::shutdown()
|
int SocketImpl::shutdown()
|
||||||
{
|
{
|
||||||
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
|
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
|
||||||
|
|
||||||
int rc = ::shutdown(_sockfd, 2);
|
int rc = ::shutdown(_sockfd, 2);
|
||||||
if (rc != 0) error();
|
if (rc != 0) error();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,15 +146,15 @@ void StreamSocket::shutdownReceive()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StreamSocket::shutdownSend()
|
int StreamSocket::shutdownSend()
|
||||||
{
|
{
|
||||||
impl()->shutdownSend();
|
return impl()->shutdownSend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StreamSocket::shutdown()
|
int StreamSocket::shutdown()
|
||||||
{
|
{
|
||||||
impl()->shutdown();
|
return impl()->shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -539,15 +539,15 @@ void WebSocketImpl::shutdownReceive()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WebSocketImpl::shutdownSend()
|
int WebSocketImpl::shutdownSend()
|
||||||
{
|
{
|
||||||
_pStreamSocketImpl->shutdownSend();
|
return _pStreamSocketImpl->shutdownSend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WebSocketImpl::shutdown()
|
int WebSocketImpl::shutdown()
|
||||||
{
|
{
|
||||||
_pStreamSocketImpl->shutdown();
|
return _pStreamSocketImpl->shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,10 +148,11 @@ public:
|
|||||||
/// number of connections that can be queued
|
/// number of connections that can be queued
|
||||||
/// for this socket.
|
/// for this socket.
|
||||||
|
|
||||||
void shutdown();
|
int shutdown();
|
||||||
/// Shuts down the connection by attempting
|
/// Shuts down the connection by attempting
|
||||||
/// an orderly SSL shutdown, then actually
|
/// an orderly SSL shutdown, then actually
|
||||||
/// shutting down the TCP connection.
|
/// shutting down the TCP connection in the
|
||||||
|
/// send direction.
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
/// Close the socket.
|
/// Close the socket.
|
||||||
@ -294,7 +295,6 @@ private:
|
|||||||
bool _needHandshake;
|
bool _needHandshake;
|
||||||
std::string _peerHostName;
|
std::string _peerHostName;
|
||||||
Session::Ptr _pSession;
|
Session::Ptr _pSession;
|
||||||
bool _bidirectShutdown = true;
|
|
||||||
mutable MutexT _mutex;
|
mutable MutexT _mutex;
|
||||||
|
|
||||||
friend class SecureStreamSocketImpl;
|
friend class SecureStreamSocketImpl;
|
||||||
|
@ -116,14 +116,25 @@ public:
|
|||||||
/// Since SSL does not support a half shutdown, this does
|
/// Since SSL does not support a half shutdown, this does
|
||||||
/// nothing.
|
/// nothing.
|
||||||
|
|
||||||
void shutdownSend() override;
|
int shutdownSend() override;
|
||||||
/// Shuts down the receiving part of the socket connection.
|
/// Shuts down the receiving part of the socket connection.
|
||||||
///
|
///
|
||||||
/// Since SSL does not support a half shutdown, this does
|
/// Sends a close notify shutdown alert message to the peer
|
||||||
/// nothing.
|
/// (if not sent yet), then calls shutdownSend() on the
|
||||||
|
/// underlying socket.
|
||||||
|
///
|
||||||
|
/// Returns 0 if the message has been sent.
|
||||||
|
/// Returns 1 if the message has been sent, but the peer
|
||||||
|
/// has not yet sent its shutdown alert message.
|
||||||
|
/// In case of a non-blocking socket, returns < 0 if the
|
||||||
|
/// message cannot be sent at the moment. In this case,
|
||||||
|
/// the call to shutdownSend() must be retried after the
|
||||||
|
/// underlying socket becomes writable again.
|
||||||
|
|
||||||
void shutdown() override;
|
int shutdown() override;
|
||||||
/// Shuts down the SSL connection.
|
/// Shuts down the SSL connection.
|
||||||
|
///
|
||||||
|
/// Same as shutdownSend().
|
||||||
|
|
||||||
void abort();
|
void abort();
|
||||||
/// Aborts the connection by closing the underlying
|
/// Aborts the connection by closing the underlying
|
||||||
|
@ -253,69 +253,39 @@ void SecureSocketImpl::listen(int backlog)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SecureSocketImpl::shutdown()
|
int SecureSocketImpl::shutdown()
|
||||||
{
|
{
|
||||||
if (_pSSL)
|
if (_pSSL)
|
||||||
{
|
{
|
||||||
UnLockT l(_mutex);
|
UnLockT l(_mutex);
|
||||||
|
|
||||||
// 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;
|
||||||
if (!shutdownSent)
|
if (!shutdownSent)
|
||||||
{
|
{
|
||||||
// A proper clean shutdown would require us to
|
|
||||||
// retry the shutdown if we get a zero return
|
|
||||||
// value, until SSL_shutdown() returns 1.
|
|
||||||
// However, this will lead to problems with
|
|
||||||
// most web browsers, so we just set the shutdown
|
|
||||||
// flag by calling SSL_shutdown() once and be
|
|
||||||
// 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)
|
||||||
if (rc < 0) handleError(rc);
|
{
|
||||||
|
if (SocketImpl::lastError() == POCO_EWOULDBLOCK)
|
||||||
|
rc = SecureStreamSocket::ERR_SSL_WANT_WRITE;
|
||||||
|
else
|
||||||
|
rc = handleError(rc);
|
||||||
|
}
|
||||||
|
|
||||||
l.unlock();
|
l.unlock();
|
||||||
|
|
||||||
if (_pSocket->getBlocking())
|
if (rc >= 0)
|
||||||
{
|
{
|
||||||
_pSocket->shutdown();
|
_pSocket->shutdownSend();
|
||||||
}
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (shutdownState & SSL_RECEIVED_SHUTDOWN) == SSL_RECEIVED_SHUTDOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -407,7 +377,6 @@ int SecureSocketImpl::receiveBytes(void* buffer, int length, int flags)
|
|||||||
if (tsStart.isElapsed(recvTimeout.totalMicroseconds()))
|
if (tsStart.isElapsed(recvTimeout.totalMicroseconds()))
|
||||||
throw Poco::TimeoutException();
|
throw Poco::TimeoutException();
|
||||||
};
|
};
|
||||||
_bidirectShutdown = false;
|
|
||||||
if (rc <= 0)
|
if (rc <= 0)
|
||||||
{
|
{
|
||||||
return handleError(rc);
|
return handleError(rc);
|
||||||
|
@ -156,14 +156,15 @@ void SecureStreamSocketImpl::shutdownReceive()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SecureStreamSocketImpl::shutdownSend()
|
int SecureStreamSocketImpl::shutdownSend()
|
||||||
{
|
{
|
||||||
|
return _impl.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SecureStreamSocketImpl::shutdown()
|
int SecureStreamSocketImpl::shutdown()
|
||||||
{
|
{
|
||||||
_impl.shutdown();
|
return _impl.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
#define NetSSL_SecureSocketImpl_INCLUDED
|
#define NetSSL_SecureSocketImpl_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
// Temporary debugging aid, to be removed
|
||||||
|
// #define ENABLE_PRINT_STATE
|
||||||
|
|
||||||
|
|
||||||
#include "Poco/Net/SocketImpl.h"
|
#include "Poco/Net/SocketImpl.h"
|
||||||
#include "Poco/Net/NetSSL.h"
|
#include "Poco/Net/NetSSL.h"
|
||||||
#include "Poco/Net/Context.h"
|
#include "Poco/Net/Context.h"
|
||||||
@ -35,6 +39,14 @@
|
|||||||
#include <sspi.h>
|
#include <sspi.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ENABLE_PRINT_STATE
|
||||||
|
#define PRINT_STATE(m) printState(m)
|
||||||
|
#else
|
||||||
|
#define PRINT_STATE(m)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
namespace Net {
|
namespace Net {
|
||||||
|
|
||||||
@ -154,10 +166,11 @@ public:
|
|||||||
/// number of connections that can be queued
|
/// number of connections that can be queued
|
||||||
/// for this socket.
|
/// for this socket.
|
||||||
|
|
||||||
void shutdown();
|
int shutdown();
|
||||||
/// Shuts down the connection by attempting
|
/// Shuts down the connection by attempting
|
||||||
/// an orderly SSL shutdown, then actually
|
/// an orderly SSL shutdown, then actually
|
||||||
/// shutting down the TCP connection.
|
/// shutting down the TCP connection in the
|
||||||
|
/// send direction.
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
/// Close the socket.
|
/// Close the socket.
|
||||||
@ -224,60 +237,95 @@ protected:
|
|||||||
{
|
{
|
||||||
ST_INITIAL = 0,
|
ST_INITIAL = 0,
|
||||||
ST_CONNECTING,
|
ST_CONNECTING,
|
||||||
ST_CLIENTHANDSHAKESTART,
|
ST_CLIENT_HSK_START,
|
||||||
ST_CLIENTHANDSHAKECONDREAD,
|
ST_CLIENT_HSK_SEND_TOKEN,
|
||||||
ST_CLIENTHANDSHAKEINCOMPLETE,
|
ST_CLIENT_HSK_LOOP_INIT,
|
||||||
ST_CLIENTHANDSHAKEOK,
|
ST_CLIENT_HSK_LOOP_RECV,
|
||||||
ST_CLIENTHANDSHAKEEXTERROR,
|
ST_CLIENT_HSK_LOOP_PROCESS,
|
||||||
ST_CLIENTHANDSHAKECONTINUE,
|
ST_CLIENT_HSK_LOOP_SEND,
|
||||||
ST_VERIFY,
|
ST_CLIENT_HSK_LOOP_DONE,
|
||||||
|
ST_CLIENT_HSK_SEND_FINAL,
|
||||||
|
ST_CLIENT_HSK_SEND_ERROR,
|
||||||
|
ST_CLIENT_VERIFY,
|
||||||
|
ST_ACCEPTING,
|
||||||
|
ST_SERVER_HSK_START,
|
||||||
|
ST_SERVER_HSK_LOOP_INIT,
|
||||||
|
ST_SERVER_HSK_LOOP_RECV,
|
||||||
|
ST_SERVER_HSK_LOOP_PROCESS,
|
||||||
|
ST_SERVER_HSK_LOOP_SEND,
|
||||||
|
ST_SERVER_HSK_LOOP_DONE,
|
||||||
|
ST_SERVER_VERIFY,
|
||||||
ST_DONE,
|
ST_DONE,
|
||||||
ST_ERROR
|
ST_ERROR,
|
||||||
|
ST_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TLSShutdown
|
||||||
|
{
|
||||||
|
TLS_SHUTDOWN_SENT = 1,
|
||||||
|
TLS_SHUTDOWN_RECEIVED = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
int sendRawBytes(const void* buffer, int length, int flags = 0);
|
int sendRawBytes(const void* buffer, int length, int flags = 0);
|
||||||
int receiveRawBytes(void* buffer, int length, int flags = 0);
|
int receiveRawBytes(void* buffer, int length, int flags = 0);
|
||||||
void clientConnectVerify();
|
|
||||||
void sendInitialTokenOutBuffer();
|
|
||||||
void performServerHandshake();
|
|
||||||
bool serverHandshakeLoop(PCtxtHandle phContext, PCredHandle phCred, bool requireClientAuth, bool doInitialRead, bool newContext);
|
|
||||||
void clientVerifyCertificate(const std::string& hostName);
|
void clientVerifyCertificate(const std::string& hostName);
|
||||||
void verifyCertificateChainClient(PCCERT_CONTEXT pServerCert);
|
void verifyCertificateChainClient(PCCERT_CONTEXT pServerCert);
|
||||||
void serverVerifyCertificate();
|
void serverVerifyCertificate();
|
||||||
LONG serverDisconnect(PCredHandle phCreds, CtxtHandle* phContext);
|
int serverShutdown(PCredHandle phCreds, CtxtHandle* phContext);
|
||||||
LONG clientDisconnect(PCredHandle phCreds, CtxtHandle* phContext);
|
int clientShutdown(PCredHandle phCreds, CtxtHandle* phContext);
|
||||||
bool loadSecurityLibrary();
|
|
||||||
void initClientContext();
|
|
||||||
void initServerContext();
|
|
||||||
PCCERT_CONTEXT loadCertificate(bool mustFindCertificate);
|
PCCERT_CONTEXT loadCertificate(bool mustFindCertificate);
|
||||||
void initCommon();
|
void initCommon();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
void performClientHandshake();
|
|
||||||
void performInitialClientHandshake();
|
void stateIllegal();
|
||||||
SECURITY_STATUS performClientHandshakeLoop();
|
void stateError();
|
||||||
void performClientHandshakeLoopIncompleteMessage();
|
|
||||||
void performClientHandshakeLoopCondReceive();
|
void stateClientConnected();
|
||||||
void performClientHandshakeLoopReceive();
|
void stateClientHandshakeStart();
|
||||||
void performClientHandshakeLoopOK();
|
void stateClientHandshakeSendToken();
|
||||||
void performClientHandshakeLoopInit();
|
void stateClientHandshakeLoopInit();
|
||||||
void performClientHandshakeExtraBuffer();
|
void stateClientHandshakeLoopRecv();
|
||||||
void performClientHandshakeSendOutBuffer();
|
void stateClientHandshakeLoopProcess();
|
||||||
void performClientHandshakeLoopContinueNeeded();
|
void stateClientHandshakeLoopSend();
|
||||||
void performClientHandshakeLoopError();
|
void stateClientHandshakeLoopDone();
|
||||||
void performClientHandshakeLoopExtError();
|
void stateClientHandshakeSendFinal();
|
||||||
|
void stateClientHandshakeSendError();
|
||||||
|
void stateClientVerify();
|
||||||
|
|
||||||
|
void stateServerAccepted();
|
||||||
|
void stateServerHandshakeStart();
|
||||||
|
void stateServerHandshakeLoopInit();
|
||||||
|
void stateServerHandshakeLoopRecv();
|
||||||
|
void stateServerHandshakeLoopProcess();
|
||||||
|
void stateServerHandshakeLoopSend();
|
||||||
|
void stateServerHandshakeLoopDone();
|
||||||
|
void stateServerHandshakeVerify();
|
||||||
|
|
||||||
|
void sendOutSecBufferAndAdvanceState(State state);
|
||||||
|
void drainExtraBuffer();
|
||||||
|
static int getRecordLength(const BYTE* pBuffer, int length);
|
||||||
|
static bool bufferHasCompleteRecords(const BYTE* pBuffer, int length);
|
||||||
|
|
||||||
|
void initClientCredentials();
|
||||||
|
void initServerCredentials();
|
||||||
|
SECURITY_STATUS doHandshake();
|
||||||
|
int completeHandshake();
|
||||||
|
|
||||||
SECURITY_STATUS decodeMessage(BYTE* pBuffer, DWORD bufSize, AutoSecBufferDesc<4>& msg, SecBuffer*& pData, SecBuffer*& pExtra);
|
SECURITY_STATUS decodeMessage(BYTE* pBuffer, DWORD bufSize, AutoSecBufferDesc<4>& msg, SecBuffer*& pData, SecBuffer*& pExtra);
|
||||||
SECURITY_STATUS decodeBufferFull(BYTE* pBuffer, DWORD bufSize, char* pOutBuffer, int outLength, int& bytesDecoded);
|
SECURITY_STATUS decodeBufferFull(BYTE* pBuffer, DWORD bufSize, char* pOutBuffer, int outLength, int& bytesDecoded);
|
||||||
void stateIllegal();
|
|
||||||
void stateConnected();
|
|
||||||
void acceptSSL();
|
void acceptSSL();
|
||||||
void connectSSL(bool completeHandshake);
|
void connectSSL(bool completeHandshake);
|
||||||
void completeHandshake();
|
|
||||||
static int lastError();
|
static int lastError();
|
||||||
void stateMachine();
|
bool stateMachine();
|
||||||
State getState() const;
|
State getState() const;
|
||||||
void setState(State st);
|
void setState(State st);
|
||||||
static bool isLocalHost(const std::string& hostName);
|
static bool isLocalHost(const std::string& hostName);
|
||||||
|
|
||||||
|
#ifdef ENABLE_PRINT_STATE
|
||||||
|
void printState(const std::string& msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SecureSocketImpl(const SecureSocketImpl&);
|
SecureSocketImpl(const SecureSocketImpl&);
|
||||||
SecureSocketImpl& operator = (const SecureSocketImpl&);
|
SecureSocketImpl& operator = (const SecureSocketImpl&);
|
||||||
@ -285,6 +333,7 @@ private:
|
|||||||
Poco::AutoPtr<SocketImpl> _pSocket;
|
Poco::AutoPtr<SocketImpl> _pSocket;
|
||||||
Context::Ptr _pContext;
|
Context::Ptr _pContext;
|
||||||
Mode _mode;
|
Mode _mode;
|
||||||
|
int _shutdownFlags;
|
||||||
std::string _peerHostName;
|
std::string _peerHostName;
|
||||||
bool _useMachineStore;
|
bool _useMachineStore;
|
||||||
bool _clientAuthRequired;
|
bool _clientAuthRequired;
|
||||||
@ -312,9 +361,9 @@ private:
|
|||||||
SecBuffer _extraSecBuffer;
|
SecBuffer _extraSecBuffer;
|
||||||
SECURITY_STATUS _securityStatus;
|
SECURITY_STATUS _securityStatus;
|
||||||
State _state;
|
State _state;
|
||||||
DWORD _outFlags;
|
|
||||||
bool _needData;
|
bool _needData;
|
||||||
bool _needHandshake;
|
bool _needHandshake;
|
||||||
|
bool _initServerContext = false;
|
||||||
|
|
||||||
friend class SecureStreamSocketImpl;
|
friend class SecureStreamSocketImpl;
|
||||||
friend class StateMachine;
|
friend class StateMachine;
|
||||||
@ -357,6 +406,7 @@ inline SecureSocketImpl::State SecureSocketImpl::getState() const
|
|||||||
inline void SecureSocketImpl::setState(SecureSocketImpl::State st)
|
inline void SecureSocketImpl::setState(SecureSocketImpl::State st)
|
||||||
{
|
{
|
||||||
_state = st;
|
_state = st;
|
||||||
|
PRINT_STATE("setState: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,14 +117,25 @@ public:
|
|||||||
/// Since SSL does not support a half shutdown, this does
|
/// Since SSL does not support a half shutdown, this does
|
||||||
/// nothing.
|
/// nothing.
|
||||||
|
|
||||||
void shutdownSend();
|
int shutdownSend();
|
||||||
/// Shuts down the receiving part of the socket connection.
|
/// Shuts down the receiving part of the socket connection.
|
||||||
///
|
///
|
||||||
/// Since SSL does not support a half shutdown, this does
|
/// Sends a close notify shutdown alert message to the peer
|
||||||
/// nothing.
|
/// (if not sent yet), then calls shutdownSend() on the
|
||||||
|
/// underlying socket.
|
||||||
|
///
|
||||||
|
/// Returns 0 if the message has been sent.
|
||||||
|
/// Returns 1 if the message has been sent, but the peer
|
||||||
|
/// has not yet sent its shutdown alert message.
|
||||||
|
/// In case of a non-blocking socket, returns < 0 if the
|
||||||
|
/// message cannot be sent at the moment. In this case,
|
||||||
|
/// the call to shutdownSend() must be retried after the
|
||||||
|
/// underlying socket becomes writable again.
|
||||||
|
|
||||||
void shutdown();
|
int shutdown();
|
||||||
/// Shuts down the SSL connection.
|
/// Shuts down the SSL connection.
|
||||||
|
///
|
||||||
|
/// Same as shutdownSend().
|
||||||
|
|
||||||
void abort();
|
void abort();
|
||||||
/// Aborts the connection by closing the underlying
|
/// Aborts the connection by closing the underlying
|
||||||
|
@ -35,7 +35,7 @@ public:
|
|||||||
/// Non-case sensitive conversion of a string to a VerificationMode enum.
|
/// Non-case sensitive conversion of a string to a VerificationMode enum.
|
||||||
/// If verMode is illegal an OptionException is thrown.
|
/// If verMode is illegal an OptionException is thrown.
|
||||||
|
|
||||||
static const std::string& formatError(long errCode);
|
static std::string formatError(long errCode);
|
||||||
/// Converts an winerror.h code into human readable form.
|
/// Converts an winerror.h code into human readable form.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -138,7 +138,7 @@ std::istream* HTTPSStreamFactory::open(const URI& uri)
|
|||||||
{
|
{
|
||||||
return new HTTPResponseStream(rs, pSession);
|
return new HTTPResponseStream(rs, pSession);
|
||||||
}
|
}
|
||||||
else if (res.getStatus() == HTTPResponse::HTTP_USEPROXY && !retry)
|
else if (res.getStatus() == HTTPResponse::HTTP_USE_PROXY && !retry)
|
||||||
{
|
{
|
||||||
// The requested resource MUST be accessed through the proxy
|
// The requested resource MUST be accessed through the proxy
|
||||||
// given by the Location field. The Location field gives the
|
// given by the Location field. The Location field gives the
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -149,14 +149,15 @@ void SecureStreamSocketImpl::shutdownReceive()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SecureStreamSocketImpl::shutdownSend()
|
int SecureStreamSocketImpl::shutdownSend()
|
||||||
{
|
{
|
||||||
|
return _impl.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SecureStreamSocketImpl::shutdown()
|
int SecureStreamSocketImpl::shutdown()
|
||||||
{
|
{
|
||||||
_impl.shutdown();
|
return _impl.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -208,8 +209,7 @@ void SecureStreamSocketImpl::verifyPeerCertificate(const std::string& hostName)
|
|||||||
|
|
||||||
int SecureStreamSocketImpl::completeHandshake()
|
int SecureStreamSocketImpl::completeHandshake()
|
||||||
{
|
{
|
||||||
_impl.completeHandshake();
|
return _impl.completeHandshake();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,9 +24,6 @@ namespace Poco {
|
|||||||
namespace Net {
|
namespace Net {
|
||||||
|
|
||||||
|
|
||||||
Poco::FastMutex Utility::_mutex;
|
|
||||||
|
|
||||||
|
|
||||||
Context::VerificationMode Utility::convertVerificationMode(const std::string& vMode)
|
Context::VerificationMode Utility::convertVerificationMode(const std::string& vMode)
|
||||||
{
|
{
|
||||||
std::string mode = Poco::toLower(vMode);
|
std::string mode = Poco::toLower(vMode);
|
||||||
@ -54,6 +51,7 @@ inline void add(std::map<long, const std::string>& messageMap, long key, const s
|
|||||||
std::map<long, const std::string> Utility::initSSPIErr()
|
std::map<long, const std::string> Utility::initSSPIErr()
|
||||||
{
|
{
|
||||||
std::map<long, const std::string> messageMap;
|
std::map<long, const std::string> messageMap;
|
||||||
|
add(messageMap, SEC_E_OK, "OK");
|
||||||
add(messageMap, NTE_BAD_UID, "Bad UID");
|
add(messageMap, NTE_BAD_UID, "Bad UID");
|
||||||
add(messageMap, NTE_BAD_HASH, "Bad Hash");
|
add(messageMap, NTE_BAD_HASH, "Bad Hash");
|
||||||
add(messageMap, NTE_BAD_KEY, "Bad Key");
|
add(messageMap, NTE_BAD_KEY, "Bad Key");
|
||||||
@ -185,18 +183,15 @@ std::map<long, const std::string> Utility::initSSPIErr()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::string& Utility::formatError(long errCode)
|
std::string Utility::formatError(long errCode)
|
||||||
{
|
{
|
||||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
|
||||||
|
|
||||||
static const std::string def("Internal SSPI error");
|
|
||||||
static const std::map<long, const std::string> errs(initSSPIErr());
|
static const std::map<long, const std::string> errs(initSSPIErr());
|
||||||
|
|
||||||
const std::map<long, const std::string>::const_iterator it = errs.find(errCode);
|
const std::map<long, const std::string>::const_iterator it = errs.find(errCode);
|
||||||
if (it != errs.end())
|
if (it != errs.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
else
|
else
|
||||||
return def;
|
return "0x" + Poco::NumberFormatter::formatHex(errCode, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user