Skip to content

Commit 80952e1

Browse files
committed
optimizations, certificate verification, code cleanup
1 parent 5b0fa2e commit 80952e1

10 files changed

Lines changed: 594 additions & 395 deletions

NetSSL_Win/include/Poco/Net/AutoSecBufferDesc.h

Lines changed: 12 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -52,52 +52,20 @@ class AutoSecBufferDesc: public SecBufferDesc
5252
ulVersion = SECBUFFER_VERSION;
5353
}
5454

55-
AutoSecBufferDesc(const AutoSecBufferDesc& desc):
56-
/// Creates a AutoSecBufferDesc from another buffer, resets the other buffer!
57-
_pSec(desc._pSec),
58-
_autoRelease(desc._autoRelease)
59-
{
60-
poco_check_ptr (_pSec);
61-
poco_static_assert (numBufs > 0);
62-
63-
for (int i = 0; i < numBufs; ++i)
64-
{
65-
_buffers[i].pvBuffer = desc._buffers[i].pvBuffer;
66-
_buffers[i].cbBuffer = desc._buffers[i].cbBuffer;
67-
_buffers[i].BufferType = desc._buffers[i].BufferType;
68-
}
69-
cBuffers = numBufs;
70-
pBuffers = _buffers;
71-
ulVersion = SECBUFFER_VERSION;
72-
// steal the buffers from the original one
73-
const_cast<AutoSecBufferDesc*>(&desc)->initBuffers();
74-
}
75-
76-
AutoSecBufferDesc& operator = (const AutoSecBufferDesc& desc)
55+
~AutoSecBufferDesc()
56+
/// Destroys the AutoSecBufferDesc
7757
{
78-
if (&desc != this)
79-
{
80-
_pSec = desc._pSec;
81-
_autoRelease = desc._autoRelease;
82-
for (int i = 0; i < numBufs; ++i)
83-
{
84-
_buffers[i].pvBuffer = desc._buffers[i].pvBuffer;
85-
_buffers[i].cbBuffer = desc._buffers[i].cbBuffer;
86-
_buffers[i].BufferType = desc._buffers[i].BufferType;
87-
}
88-
cBuffers = numBufs;
89-
pBuffers = _buffers;
90-
ulVersion = desc.ulVersion;
91-
// steal the buffers from the original one
92-
const_cast<AutoSecBufferDesc*>(&desc)->initBuffers();
93-
}
94-
return *this;
58+
release();
9559
}
9660

97-
~AutoSecBufferDesc()
98-
/// Destroys the AutoSecBufferDesc
61+
void reset(bool autoRelease)
9962
{
10063
release();
64+
_autoRelease = autoRelease;
65+
initBuffers();
66+
cBuffers = numBufs;
67+
pBuffers = _buffers;
68+
ulVersion = SECBUFFER_VERSION;
10169
}
10270

10371
void release()
@@ -157,6 +125,9 @@ class AutoSecBufferDesc: public SecBufferDesc
157125
}
158126

159127
private:
128+
AutoSecBufferDesc(const AutoSecBufferDesc& desc);
129+
AutoSecBufferDesc& operator = (const AutoSecBufferDesc& desc);
130+
160131
void release(int idx, bool force)
161132
{
162133
if (force && _buffers[idx].pvBuffer)

NetSSL_Win/include/Poco/Net/Context.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,9 @@ class NetSSL_Win_API Context: public Poco::RefCountedObject
9393
///
9494
/// Client: Same as VERIFY_RELAXED.
9595

96-
VERIFY_ONCE = 3
97-
/// Server: Only request a client certificate on the initial
98-
/// TLS/SSL handshake. Do not ask for a client certificate
99-
/// again in case of a renegotiation.
100-
///
101-
/// Client: Same as VERIFY_RELAXED.
96+
VERIFY_ONCE = 1
97+
/// Same as VERIFY_RELAXED (provided for interface compatibility with
98+
/// the OpenSSL implementation.
10299
};
103100

104101
enum Options
@@ -160,6 +157,16 @@ class NetSSL_Win_API Context: public Poco::RefCountedObject
160157
bool sessionCacheEnabled() const;
161158
/// Returns true iff the session cache is enabled.
162159

160+
void enableExtendedCertificateVerification(bool flag = true);
161+
/// Enable or disable the automatic post-connection
162+
/// extended certificate verification.
163+
///
164+
/// See X509Certificate::verify() for more information.
165+
166+
bool extendedCertificateVerificationEnabled() const;
167+
/// Returns true iff automatic extended certificate
168+
/// verification is enabled.
169+
163170
int options() const;
164171
/// Returns the options flags.
165172

@@ -202,6 +209,7 @@ class NetSSL_Win_API Context: public Poco::RefCountedObject
202209
Usage _usage;
203210
Context::VerificationMode _mode;
204211
int _options;
212+
bool _extendedCertificateVerification;
205213
std::string _certNameOrPath;
206214
std::string _certStoreName;
207215
HCERTSTORE _hMemCertStore;
@@ -245,9 +253,16 @@ inline bool Context::isForServerUse() const
245253
}
246254

247255

256+
inline bool Context::extendedCertificateVerificationEnabled() const
257+
{
258+
return _extendedCertificateVerification;
259+
}
260+
261+
248262
inline bool Context::sessionCacheEnabled() const
249263
{
250-
return false;
264+
return true;
265+
/// Session cache is always enabled with Schannel.
251266
}
252267

253268

NetSSL_Win/include/Poco/Net/SecureSocketImpl.h

Lines changed: 48 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include "Poco/Net/Context.h"
2626
#include "Poco/Net/AutoSecBufferDesc.h"
2727
#include "Poco/Net/X509Certificate.h"
28-
#include "Poco/SharedPtr.h"
2928
#include "Poco/Buffer.h"
3029
#include <winsock2.h>
3130
#include <windows.h>
@@ -46,32 +45,11 @@ class NetSSL_Win_API SecureSocketImpl
4645
/// The SocketImpl for SecureStreamSocket.
4746
{
4847
public:
49-
enum
50-
{
51-
IO_BUFFER_SIZE = 65536,
52-
TIMEOUT_MILLISECS = 200
53-
};
54-
5548
enum Mode
5649
{
5750
MODE_CLIENT,
5851
MODE_SERVER
5952
};
60-
61-
enum State
62-
{
63-
ST_INITIAL = 0,
64-
ST_CONNECTING,
65-
ST_CLIENTHANDSHAKESTART,
66-
ST_CLIENTHANDSHAKECONDREAD,
67-
ST_CLIENTHANDSHAKEINCOMPLETE,
68-
ST_CLIENTHANDSHAKEOK,
69-
ST_CLIENTHANDSHAKEEXTERROR,
70-
ST_CLIENTHANDSHAKECONTINUE,
71-
ST_VERIFY,
72-
ST_DONE,
73-
ST_ERROR
74-
};
7553

7654
SecureSocketImpl(Poco::AutoPtr<SocketImpl> pSocketImpl, Context::Ptr pContext);
7755
/// Creates the SecureSocketImpl.
@@ -160,8 +138,14 @@ class NetSSL_Win_API SecureSocketImpl
160138
const std::string& getPeerHostName() const;
161139
/// Returns the peer host name.
162140

163-
State getState() const;
164-
/// Returns the state of the socket
141+
void verifyPeerCertificate();
142+
/// Performs post-connect (or post-accept) peer certificate validation,
143+
/// using the peer host name set with setPeerHostName(), or the peer's
144+
/// IP address string if no peer host name has been set.
145+
146+
void verifyPeerCertificate(const std::string& hostName);
147+
/// Performs post-connect (or post-accept) peer certificate validation
148+
/// using the given peer host name.
165149

166150
Context::Ptr context() const;
167151
/// Returns the Context.
@@ -172,23 +156,40 @@ class NetSSL_Win_API SecureSocketImpl
172156
poco_socket_t sockfd();
173157
/// Returns the underlying socket descriptor.
174158

159+
int available() const;
160+
/// Returns the number of bytes available in the buffer.
161+
175162
protected:
176-
int sendRawBytes(const void* buffer, int length, int flags = 0);
177-
/// Sends the data in clearText
163+
enum
164+
{
165+
IO_BUFFER_SIZE = 32768,
166+
TIMEOUT_MILLISECS = 200
167+
};
178168

179-
int receiveRawBytes(void* buffer, int length, int flags = 0);
180-
/// Receives raw data from the socket and stores it
181-
/// in buffer. Up to length bytes are received.
182-
///
183-
/// Returns the number of bytes received.
169+
enum State
170+
{
171+
ST_INITIAL = 0,
172+
ST_CONNECTING,
173+
ST_CLIENTHANDSHAKESTART,
174+
ST_CLIENTHANDSHAKECONDREAD,
175+
ST_CLIENTHANDSHAKEINCOMPLETE,
176+
ST_CLIENTHANDSHAKEOK,
177+
ST_CLIENTHANDSHAKEEXTERROR,
178+
ST_CLIENTHANDSHAKECONTINUE,
179+
ST_VERIFY,
180+
ST_DONE,
181+
ST_ERROR
182+
};
184183

184+
int sendRawBytes(const void* buffer, int length, int flags = 0);
185+
int receiveRawBytes(void* buffer, int length, int flags = 0);
185186
void clientConnectVerify();
186187
void sendInitialTokenOutBuffer();
187188
void performServerHandshake();
188189
bool serverHandshakeLoop(PCtxtHandle phContext, PCredHandle phCred, bool requireClientAuth, bool doInitialRead, bool newContext);
189-
void clientVerifyCertificate(PCCERT_CONTEXT pServerCert, const std::string& serverName, DWORD dwCertFlags);
190+
void clientVerifyCertificate(const std::string& hostName);
190191
void verifyCertificateChainClient(PCCERT_CONTEXT pServerCert, PCCERT_CHAIN_CONTEXT pChainContext);
191-
void serverVerifyCertificate(PCCERT_CONTEXT pPeerCert, DWORD dwCertFlags);
192+
void serverVerifyCertificate();
192193
LONG serverDisconnect(PCredHandle phCreds, CtxtHandle* phContext);
193194
LONG clientDisconnect(PCredHandle phCreds, CtxtHandle* phContext);
194195
bool loadSecurityLibrary();
@@ -201,8 +202,8 @@ class NetSSL_Win_API SecureSocketImpl
201202
void performInitialClientHandshake();
202203
SECURITY_STATUS performClientHandshakeLoop();
203204
void performClientHandshakeLoopIncompleteMessage();
204-
void performClientHandshakeLoopCondRead();
205-
void performClientHandshakeLoopRead();
205+
void performClientHandshakeLoopCondReceive();
206+
void performClientHandshakeLoopReceive();
206207
void performClientHandshakeLoopOK();
207208
void performClientHandshakeLoopInit();
208209
void performClientHandshakeExtraBuffer();
@@ -219,7 +220,9 @@ class NetSSL_Win_API SecureSocketImpl
219220
void completeHandshake();
220221
static int lastError();
221222
void stateMachine();
223+
State getState() const;
222224
void setState(State st);
225+
static bool isLocalHost(const std::string& hostName);
223226

224227
private:
225228
SecureSocketImpl(const SecureSocketImpl&);
@@ -231,34 +234,30 @@ class NetSSL_Win_API SecureSocketImpl
231234
std::string _peerHostName;
232235
bool _useMachineStore;
233236
bool _clientAuthRequired;
234-
PCCERT_CONTEXT _pServerCertificate;
237+
238+
SecurityFunctionTableW& _securityFunctions;
239+
240+
PCCERT_CONTEXT _pOwnCertificate;
235241
PCCERT_CONTEXT _pPeerCertificate;
236242

237243
CredHandle _hCreds;
238244
CtxtHandle _hContext;
239-
DWORD _clientFlags;
240-
DWORD _serverFlags;
241-
242-
SecurityFunctionTableW& _securityFunctions;
243-
244-
BYTE* _pReceiveBuffer;
245-
DWORD _receiveBufferSize;
245+
DWORD _contextFlags;
246246

247-
BYTE* _pIOBuffer;
248-
DWORD _ioBufferOffset;
247+
Poco::Buffer<BYTE> _overflowBuffer;
248+
Poco::Buffer<BYTE> _sendBuffer;
249+
Poco::Buffer<BYTE> _recvBuffer;
250+
DWORD _recvBufferOffset;
249251
DWORD _ioBufferSize;
250252

251253
SecPkgContext_StreamSizes _streamSizes;
252254
AutoSecBufferDesc<1> _outSecBuffer;
253255
AutoSecBufferDesc<2> _inSecBuffer;
254-
Poco::SharedPtr<Poco::Buffer<BYTE> > _pSendBuffer;
255256
SecBuffer _extraSecBuffer;
256-
bool _doReadFirst;
257-
DWORD _bytesRead;
258257
SECURITY_STATUS _securityStatus;
259258
State _state;
260259
DWORD _outFlags;
261-
std::string _hostName;
260+
bool _needData;
262261
bool _needHandshake;
263262

264263
friend class SecureStreamSocketImpl;

NetSSL_Win/include/Poco/Net/X509Certificate.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,25 @@ class NetSSL_Win_API X509Certificate
123123
/// Returns true if verification against the issuer certificate
124124
/// was successful, false otherwise.
125125

126+
bool verify(const std::string& hostName) const;
127+
/// Verifies the validity of the certificate against the host name.
128+
///
129+
/// For this check to be successful, the certificate must contain
130+
/// a domain name that matches the domain name
131+
/// of the host.
132+
///
133+
/// Returns true if verification succeeded, or false otherwise.
134+
135+
static bool verify(const Poco::Net::X509Certificate& cert, const std::string& hostName);
136+
/// Verifies the validity of the certificate against the host name.
137+
///
138+
/// For this check to be successful, the certificate must contain
139+
/// a domain name that matches the domain name
140+
/// of the host.
141+
///
142+
/// Returns true if verification succeeded, or false otherwise.
143+
144+
126145
const PCCERT_CONTEXT system() const;
127146
/// Returns the underlying WinCrypt certificate.
128147

@@ -139,6 +158,9 @@ class NetSSL_Win_API X509Certificate
139158
void importPEMCertificate(const char* pBuffer, std::size_t size);
140159
void importDERCertificate(const char* pBuffer, std::size_t size);
141160

161+
static bool containsWildcards(const std::string& commonName);
162+
static bool matchWildcard(const std::string& alias, const std::string& hostName);
163+
142164
private:
143165
enum
144166
{

NetSSL_Win/src/Context.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Context::Context(Usage usage,
4848
_usage(usage),
4949
_mode(verMode),
5050
_options(options),
51+
_extendedCertificateVerification(true),
5152
_certNameOrPath(certNameOrPath),
5253
_certStoreName(certStore),
5354
_hMemCertStore(0),
@@ -126,6 +127,12 @@ void Context::init()
126127
}
127128

128129

130+
void Context::enableExtendedCertificateVerification(bool flag)
131+
{
132+
_extendedCertificateVerification = flag;
133+
}
134+
135+
129136
void Context::addTrustedCert(const Poco::Net::X509Certificate& cert)
130137
{
131138
Poco::FastMutex::ScopedLock lock(_mutex);
@@ -278,21 +285,24 @@ void Context::acquireSchannelCredentials(CredHandle& credHandle) const
278285

279286
if (isForServerUse())
280287
{
281-
if (_mode == Context::VERIFY_STRICT)
288+
if (_mode >= Context::VERIFY_STRICT)
282289
schannelCred.dwFlags |= SCH_CRED_NO_SYSTEM_MAPPER;
283290

284291
if (_mode == Context::VERIFY_NONE)
285292
schannelCred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
286293
}
287294
else
288295
{
289-
if (_mode == Context::VERIFY_STRICT)
296+
if (_mode >= Context::VERIFY_STRICT)
290297
schannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
291298
else
292299
schannelCred.dwFlags |= SCH_CRED_USE_DEFAULT_CREDS;
293300

294301
if (_mode == Context::VERIFY_NONE)
295302
schannelCred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_SERVERNAME_CHECK;
303+
304+
if (!_extendedCertificateVerification)
305+
schannelCred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
296306
}
297307

298308
#if defined(SCH_USE_STRONG_CRYPTO)

0 commit comments

Comments
 (0)