mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-17 03:03:23 +02:00
optimizations, certificate verification, code cleanup
This commit is contained in:
@@ -52,54 +52,22 @@ public:
|
||||
ulVersion = SECBUFFER_VERSION;
|
||||
}
|
||||
|
||||
AutoSecBufferDesc(const AutoSecBufferDesc& desc):
|
||||
/// Creates a AutoSecBufferDesc from another buffer, resets the other buffer!
|
||||
_pSec(desc._pSec),
|
||||
_autoRelease(desc._autoRelease)
|
||||
{
|
||||
poco_check_ptr (_pSec);
|
||||
poco_static_assert (numBufs > 0);
|
||||
|
||||
for (int i = 0; i < numBufs; ++i)
|
||||
{
|
||||
_buffers[i].pvBuffer = desc._buffers[i].pvBuffer;
|
||||
_buffers[i].cbBuffer = desc._buffers[i].cbBuffer;
|
||||
_buffers[i].BufferType = desc._buffers[i].BufferType;
|
||||
}
|
||||
cBuffers = numBufs;
|
||||
pBuffers = _buffers;
|
||||
ulVersion = SECBUFFER_VERSION;
|
||||
// steal the buffers from the original one
|
||||
const_cast<AutoSecBufferDesc*>(&desc)->initBuffers();
|
||||
}
|
||||
|
||||
AutoSecBufferDesc& operator = (const AutoSecBufferDesc& desc)
|
||||
{
|
||||
if (&desc != this)
|
||||
{
|
||||
_pSec = desc._pSec;
|
||||
_autoRelease = desc._autoRelease;
|
||||
for (int i = 0; i < numBufs; ++i)
|
||||
{
|
||||
_buffers[i].pvBuffer = desc._buffers[i].pvBuffer;
|
||||
_buffers[i].cbBuffer = desc._buffers[i].cbBuffer;
|
||||
_buffers[i].BufferType = desc._buffers[i].BufferType;
|
||||
}
|
||||
cBuffers = numBufs;
|
||||
pBuffers = _buffers;
|
||||
ulVersion = desc.ulVersion;
|
||||
// steal the buffers from the original one
|
||||
const_cast<AutoSecBufferDesc*>(&desc)->initBuffers();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~AutoSecBufferDesc()
|
||||
/// Destroys the AutoSecBufferDesc
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
void reset(bool autoRelease)
|
||||
{
|
||||
release();
|
||||
_autoRelease = autoRelease;
|
||||
initBuffers();
|
||||
cBuffers = numBufs;
|
||||
pBuffers = _buffers;
|
||||
ulVersion = SECBUFFER_VERSION;
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
if (_autoRelease)
|
||||
@@ -157,6 +125,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
AutoSecBufferDesc(const AutoSecBufferDesc& desc);
|
||||
AutoSecBufferDesc& operator = (const AutoSecBufferDesc& desc);
|
||||
|
||||
void release(int idx, bool force)
|
||||
{
|
||||
if (force && _buffers[idx].pvBuffer)
|
||||
|
@@ -93,12 +93,9 @@ public:
|
||||
///
|
||||
/// Client: Same as VERIFY_RELAXED.
|
||||
|
||||
VERIFY_ONCE = 3
|
||||
/// Server: Only request a client certificate on the initial
|
||||
/// TLS/SSL handshake. Do not ask for a client certificate
|
||||
/// again in case of a renegotiation.
|
||||
///
|
||||
/// Client: Same as VERIFY_RELAXED.
|
||||
VERIFY_ONCE = 1
|
||||
/// Same as VERIFY_RELAXED (provided for interface compatibility with
|
||||
/// the OpenSSL implementation.
|
||||
};
|
||||
|
||||
enum Options
|
||||
@@ -160,6 +157,16 @@ public:
|
||||
bool sessionCacheEnabled() const;
|
||||
/// Returns true iff the session cache is enabled.
|
||||
|
||||
void enableExtendedCertificateVerification(bool flag = true);
|
||||
/// Enable or disable the automatic post-connection
|
||||
/// extended certificate verification.
|
||||
///
|
||||
/// See X509Certificate::verify() for more information.
|
||||
|
||||
bool extendedCertificateVerificationEnabled() const;
|
||||
/// Returns true iff automatic extended certificate
|
||||
/// verification is enabled.
|
||||
|
||||
int options() const;
|
||||
/// Returns the options flags.
|
||||
|
||||
@@ -202,6 +209,7 @@ private:
|
||||
Usage _usage;
|
||||
Context::VerificationMode _mode;
|
||||
int _options;
|
||||
bool _extendedCertificateVerification;
|
||||
std::string _certNameOrPath;
|
||||
std::string _certStoreName;
|
||||
HCERTSTORE _hMemCertStore;
|
||||
@@ -245,9 +253,16 @@ inline bool Context::isForServerUse() const
|
||||
}
|
||||
|
||||
|
||||
inline bool Context::extendedCertificateVerificationEnabled() const
|
||||
{
|
||||
return _extendedCertificateVerification;
|
||||
}
|
||||
|
||||
|
||||
inline bool Context::sessionCacheEnabled() const
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
/// Session cache is always enabled with Schannel.
|
||||
}
|
||||
|
||||
|
||||
|
@@ -25,7 +25,6 @@
|
||||
#include "Poco/Net/Context.h"
|
||||
#include "Poco/Net/AutoSecBufferDesc.h"
|
||||
#include "Poco/Net/X509Certificate.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
@@ -46,32 +45,11 @@ class NetSSL_Win_API SecureSocketImpl
|
||||
/// The SocketImpl for SecureStreamSocket.
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
IO_BUFFER_SIZE = 65536,
|
||||
TIMEOUT_MILLISECS = 200
|
||||
};
|
||||
|
||||
enum Mode
|
||||
{
|
||||
MODE_CLIENT,
|
||||
MODE_SERVER
|
||||
};
|
||||
|
||||
enum State
|
||||
{
|
||||
ST_INITIAL = 0,
|
||||
ST_CONNECTING,
|
||||
ST_CLIENTHANDSHAKESTART,
|
||||
ST_CLIENTHANDSHAKECONDREAD,
|
||||
ST_CLIENTHANDSHAKEINCOMPLETE,
|
||||
ST_CLIENTHANDSHAKEOK,
|
||||
ST_CLIENTHANDSHAKEEXTERROR,
|
||||
ST_CLIENTHANDSHAKECONTINUE,
|
||||
ST_VERIFY,
|
||||
ST_DONE,
|
||||
ST_ERROR
|
||||
};
|
||||
|
||||
SecureSocketImpl(Poco::AutoPtr<SocketImpl> pSocketImpl, Context::Ptr pContext);
|
||||
/// Creates the SecureSocketImpl.
|
||||
@@ -160,8 +138,14 @@ public:
|
||||
const std::string& getPeerHostName() const;
|
||||
/// Returns the peer host name.
|
||||
|
||||
State getState() const;
|
||||
/// Returns the state of the socket
|
||||
void verifyPeerCertificate();
|
||||
/// Performs post-connect (or post-accept) peer certificate validation,
|
||||
/// using the peer host name set with setPeerHostName(), or the peer's
|
||||
/// IP address string if no peer host name has been set.
|
||||
|
||||
void verifyPeerCertificate(const std::string& hostName);
|
||||
/// Performs post-connect (or post-accept) peer certificate validation
|
||||
/// using the given peer host name.
|
||||
|
||||
Context::Ptr context() const;
|
||||
/// Returns the Context.
|
||||
@@ -172,23 +156,40 @@ public:
|
||||
poco_socket_t sockfd();
|
||||
/// Returns the underlying socket descriptor.
|
||||
|
||||
int available() const;
|
||||
/// Returns the number of bytes available in the buffer.
|
||||
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
IO_BUFFER_SIZE = 32768,
|
||||
TIMEOUT_MILLISECS = 200
|
||||
};
|
||||
|
||||
enum State
|
||||
{
|
||||
ST_INITIAL = 0,
|
||||
ST_CONNECTING,
|
||||
ST_CLIENTHANDSHAKESTART,
|
||||
ST_CLIENTHANDSHAKECONDREAD,
|
||||
ST_CLIENTHANDSHAKEINCOMPLETE,
|
||||
ST_CLIENTHANDSHAKEOK,
|
||||
ST_CLIENTHANDSHAKEEXTERROR,
|
||||
ST_CLIENTHANDSHAKECONTINUE,
|
||||
ST_VERIFY,
|
||||
ST_DONE,
|
||||
ST_ERROR
|
||||
};
|
||||
|
||||
int sendRawBytes(const void* buffer, int length, int flags = 0);
|
||||
/// Sends the data in clearText
|
||||
|
||||
int receiveRawBytes(void* buffer, int length, int flags = 0);
|
||||
/// Receives raw data from the socket and stores it
|
||||
/// in buffer. Up to length bytes are received.
|
||||
///
|
||||
/// Returns the number of bytes received.
|
||||
|
||||
void clientConnectVerify();
|
||||
void sendInitialTokenOutBuffer();
|
||||
void performServerHandshake();
|
||||
bool serverHandshakeLoop(PCtxtHandle phContext, PCredHandle phCred, bool requireClientAuth, bool doInitialRead, bool newContext);
|
||||
void clientVerifyCertificate(PCCERT_CONTEXT pServerCert, const std::string& serverName, DWORD dwCertFlags);
|
||||
void clientVerifyCertificate(const std::string& hostName);
|
||||
void verifyCertificateChainClient(PCCERT_CONTEXT pServerCert, PCCERT_CHAIN_CONTEXT pChainContext);
|
||||
void serverVerifyCertificate(PCCERT_CONTEXT pPeerCert, DWORD dwCertFlags);
|
||||
void serverVerifyCertificate();
|
||||
LONG serverDisconnect(PCredHandle phCreds, CtxtHandle* phContext);
|
||||
LONG clientDisconnect(PCredHandle phCreds, CtxtHandle* phContext);
|
||||
bool loadSecurityLibrary();
|
||||
@@ -201,8 +202,8 @@ protected:
|
||||
void performInitialClientHandshake();
|
||||
SECURITY_STATUS performClientHandshakeLoop();
|
||||
void performClientHandshakeLoopIncompleteMessage();
|
||||
void performClientHandshakeLoopCondRead();
|
||||
void performClientHandshakeLoopRead();
|
||||
void performClientHandshakeLoopCondReceive();
|
||||
void performClientHandshakeLoopReceive();
|
||||
void performClientHandshakeLoopOK();
|
||||
void performClientHandshakeLoopInit();
|
||||
void performClientHandshakeExtraBuffer();
|
||||
@@ -219,7 +220,9 @@ protected:
|
||||
void completeHandshake();
|
||||
static int lastError();
|
||||
void stateMachine();
|
||||
State getState() const;
|
||||
void setState(State st);
|
||||
static bool isLocalHost(const std::string& hostName);
|
||||
|
||||
private:
|
||||
SecureSocketImpl(const SecureSocketImpl&);
|
||||
@@ -231,34 +234,30 @@ private:
|
||||
std::string _peerHostName;
|
||||
bool _useMachineStore;
|
||||
bool _clientAuthRequired;
|
||||
PCCERT_CONTEXT _pServerCertificate;
|
||||
|
||||
SecurityFunctionTableW& _securityFunctions;
|
||||
|
||||
PCCERT_CONTEXT _pOwnCertificate;
|
||||
PCCERT_CONTEXT _pPeerCertificate;
|
||||
|
||||
CredHandle _hCreds;
|
||||
CtxtHandle _hContext;
|
||||
DWORD _clientFlags;
|
||||
DWORD _serverFlags;
|
||||
DWORD _contextFlags;
|
||||
|
||||
SecurityFunctionTableW& _securityFunctions;
|
||||
|
||||
BYTE* _pReceiveBuffer;
|
||||
DWORD _receiveBufferSize;
|
||||
|
||||
BYTE* _pIOBuffer;
|
||||
DWORD _ioBufferOffset;
|
||||
Poco::Buffer<BYTE> _overflowBuffer;
|
||||
Poco::Buffer<BYTE> _sendBuffer;
|
||||
Poco::Buffer<BYTE> _recvBuffer;
|
||||
DWORD _recvBufferOffset;
|
||||
DWORD _ioBufferSize;
|
||||
|
||||
SecPkgContext_StreamSizes _streamSizes;
|
||||
AutoSecBufferDesc<1> _outSecBuffer;
|
||||
AutoSecBufferDesc<2> _inSecBuffer;
|
||||
Poco::SharedPtr<Poco::Buffer<BYTE> > _pSendBuffer;
|
||||
SecBuffer _extraSecBuffer;
|
||||
bool _doReadFirst;
|
||||
DWORD _bytesRead;
|
||||
SECURITY_STATUS _securityStatus;
|
||||
State _state;
|
||||
DWORD _outFlags;
|
||||
std::string _hostName;
|
||||
bool _needData;
|
||||
bool _needHandshake;
|
||||
|
||||
friend class SecureStreamSocketImpl;
|
||||
|
@@ -123,6 +123,25 @@ public:
|
||||
/// Returns true if verification against the issuer certificate
|
||||
/// was successful, false otherwise.
|
||||
|
||||
bool verify(const std::string& hostName) const;
|
||||
/// Verifies the validity of the certificate against the host name.
|
||||
///
|
||||
/// For this check to be successful, the certificate must contain
|
||||
/// a domain name that matches the domain name
|
||||
/// of the host.
|
||||
///
|
||||
/// Returns true if verification succeeded, or false otherwise.
|
||||
|
||||
static bool verify(const Poco::Net::X509Certificate& cert, const std::string& hostName);
|
||||
/// Verifies the validity of the certificate against the host name.
|
||||
///
|
||||
/// For this check to be successful, the certificate must contain
|
||||
/// a domain name that matches the domain name
|
||||
/// of the host.
|
||||
///
|
||||
/// Returns true if verification succeeded, or false otherwise.
|
||||
|
||||
|
||||
const PCCERT_CONTEXT system() const;
|
||||
/// Returns the underlying WinCrypt certificate.
|
||||
|
||||
@@ -139,6 +158,9 @@ protected:
|
||||
void importPEMCertificate(const char* pBuffer, std::size_t size);
|
||||
void importDERCertificate(const char* pBuffer, std::size_t size);
|
||||
|
||||
static bool containsWildcards(const std::string& commonName);
|
||||
static bool matchWildcard(const std::string& alias, const std::string& hostName);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
|
Reference in New Issue
Block a user