aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h
blob: 989515bf012f1b3df6fbe1133499c98f990f9358 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
//
// SSLManager.h
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module:  SSLManager
//
// Definition of the SSLManager class.
//
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier:	BSL-1.0
//


#ifndef NetSSL_SSLManager_INCLUDED
#define NetSSL_SSLManager_INCLUDED


#include "Poco/Net/NetSSL.h"
#include "Poco/Net/VerificationErrorArgs.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/PrivateKeyFactoryMgr.h"
#include "Poco/Net/CertificateHandlerFactoryMgr.h"
#include "Poco/Net/InvalidCertificateHandler.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/BasicEvent.h"
#include "Poco/SharedPtr.h"
#include "Poco/Mutex.h"
#include <openssl/ssl.h>
#if defined(OPENSSL_FIPS) && OPENSSL_VERSION_NUMBER < 0x010001000L
#error #include <openssl/fips.h>
#endif


namespace Poco {
namespace Net {


class Context;


class NetSSL_API SSLManager
	/// SSLManager is a singleton for holding the default server/client
	/// Context and handling callbacks for certificate verification errors
	/// and private key passphrases.
	///
	/// Proper initialization of SSLManager is critical.
	///
	/// SSLManager can be initialized manually, by calling initializeServer()
	/// and/or initializeClient(), or initialization can be automatic. In the latter
	/// case, a Poco::Util::Application instance must be available and the required
	/// configuration properties must be set (see below).
	///
	/// Note that manual initialization must happen very early in the application,
	/// before defaultClientContext() or defaultServerContext() are called.
	///
	/// If defaultClientContext() and defaultServerContext() are never called
	/// in an application, initialization of SSLManager can be omitted.
	/// However, in this case, delegates for the ServerVerificationError,
	/// ClientVerificationError and PrivateKeyPassphraseRequired events
	/// must be registered.
	///
	/// An exemplary documentation which sets either the server or client default context and creates
	/// a PrivateKeyPassphraseHandler that reads the password from the XML file looks like this:
	///
	///    <AppConfig>
	///       <openSSL>
	///          <server|client>
	///            <privateKeyFile>mycert.key</privateKeyFile>
	///            <certificateFile>mycert.crt</certificateFile>
	///            <caConfig>rootcert.pem</caConfig>
	///            <verificationMode>none|relaxed|strict|once</verificationMode>
	///            <verificationDepth>1..9</verificationDepth>
	///            <loadDefaultCAFile>true|false</loadDefaultCAFile>
	///            <cipherList>ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH</cipherList>
	///            <preferServerCiphers>true|false</preferServerCiphers>
	///            <privateKeyPassphraseHandler>
	///                <name>KeyFileHandler</name>
	///                <options>
	///                    <password>test</password>
	///                </options>
	///            </privateKeyPassphraseHandler>
	///            <invalidCertificateHandler>
	///                 <name>ConsoleCertificateHandler</name>
	///            </invalidCertificateHandler>
	///            <cacheSessions>true|false</cacheSessions>
	///            <sessionIdContext>someString</sessionIdContext> <!-- server only -->
	///            <sessionCacheSize>0..n</sessionCacheSize>       <!-- server only -->
	///            <sessionTimeout>0..n</sessionTimeout>           <!-- server only -->
	///            <extendedVerification>true|false</extendedVerification>
	///            <requireTLSv1>true|false</requireTLSv1>
	///            <requireTLSv1_1>true|false</requireTLSv1_1>
	///            <requireTLSv1_2>true|false</requireTLSv1_2>
	///            <disableProtocols>sslv2,sslv3,tlsv1,tlsv1_1,tlsv1_2</disableProtocols>
	///            <dhParamsFile>dh.pem</dhParamsFile>
	///            <ecdhCurve>prime256v1</ecdhCurve>
	///          </server|client>
	///          <fips>false</fips>
	///       </openSSL>
	///    </AppConfig>
	///
	/// Following is a list of supported configuration properties. Property names must always
	/// be prefixed with openSSL.server or openSSL.client. Some properties are only supported
	/// for servers.
	///
	///    - privateKeyFile (string): The path to the file containing the private key for the certificate
	///      in PEM format (or containing both the private key and the certificate).
	///    - certificateFile (string): The Path to the file containing the server's or client's certificate
	///      in PEM format. Can be omitted if the the file given in privateKeyFile contains the certificate as well.
	///    - caConfig (string): The path to the file or directory containing the trusted root certificates.
	///    - verificationMode (string): Specifies whether and how peer certificates are validated (see
	///      the Context class for details). Valid values are none, relaxed, strict, once.
	///    - verificationDepth (integer, 1-9): Sets the upper limit for verification chain sizes. Verification
	///      will fail if a certificate chain larger than this is encountered.
	///    - loadDefaultCAFile (boolean): Specifies whether the builtin CA certificates from OpenSSL are used.
	///    - cipherList (string): Specifies the supported ciphers in OpenSSL notation
	///      (e.g. "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH").
	///    - preferServerCiphers (bool): When choosing a cipher, use the server's preferences instead of the
	///      client preferences. When not called, the SSL server will always follow the clients
	///      preferences. When called, the SSL/TLS server will choose following its own
	///      preferences.
	///    - privateKeyPassphraseHandler.name (string): The name of the class (subclass of PrivateKeyPassphraseHandler)
	///      used for obtaining the passphrase for accessing the private key.
	///    - privateKeyPassphraseHandler.options.password (string): The password to be used by KeyFileHandler.
	///    - invalidCertificateHandler.name: The name of the class (subclass of CertificateHandler)
	///      used for confirming invalid certificates.
	///    - cacheSessions (boolean): Enables or disables session caching.
	///    - sessionIdContext (string): contains the application's unique session ID context, which becomes
	///      part of each session identifier generated by the server. Can be an arbitrary sequence
	///      of bytes with a maximum length of SSL_MAX_SSL_SESSION_ID_LENGTH. Should be specified
	///      for a server to enable session caching. Should be specified even if session caching
	///      is disabled to avoid problems with clients that request session caching (e.g. Firefox 3.6).
	///      If not specified, defaults to ${application.name}.
	///    - sessionCacheSize (integer): Sets the maximum size of the server session cache, in number of
	///      sessions. The default size (according to OpenSSL documentation) is 1024*20, which may be too
	///      large for many applications, especially on embedded platforms with limited memory.
	///      Specifying a size of 0 will set an unlimited cache size.
	///    - sessionTimeout (integer):  Sets the timeout (in seconds) of cached sessions on the server.
	///    - extendedVerification (boolean): Enable or disable the automatic post-connection
	///      extended certificate verification.
	///    - requireTLSv1 (boolean): Require a TLSv1 connection.
	///    - requireTLSv1_1 (boolean): Require a TLSv1.1 connection.
	///    - requireTLSv1_2 (boolean): Require a TLSv1.2 connection.
	///    - disableProtocols (string): A comma-separated list of protocols that should be
	///      disabled. Valid protocol names are sslv2, sslv3, tlsv1, tlsv1_1, tlsv1_2.
	///    - dhParamsFile (string): Specifies a file containing Diffie-Hellman parameters.
	///      If not specified or empty, the default parameters are used.
	///    - ecdhCurve (string): Specifies the name of the curve to use for ECDH, based
	///      on the curve names specified in RFC 4492. Defaults to "prime256v1".
	///    - fips: Enable or disable OpenSSL FIPS mode. Only supported if the OpenSSL version
	///      that this library is built against supports FIPS mode.
{
public:
	typedef Poco::SharedPtr<PrivateKeyPassphraseHandler> PrivateKeyPassphraseHandlerPtr;
	typedef Poco::SharedPtr<InvalidCertificateHandler> InvalidCertificateHandlerPtr;

	Poco::BasicEvent<VerificationErrorArgs> ServerVerificationError;
		/// Fired whenever a certificate verification error is detected by the server during a handshake.

	Poco::BasicEvent<VerificationErrorArgs> ClientVerificationError;
		/// Fired whenever a certificate verification error is detected by the client during a handshake.

	Poco::BasicEvent<std::string> PrivateKeyPassphraseRequired;
		/// Fired when a encrypted certificate is loaded. Not setting the password
		/// in the event parameter will result in a failure to load the certificate.

	static SSLManager& instance();
		/// Returns the instance of the SSLManager singleton.

	void initializeServer(PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler, InvalidCertificateHandlerPtr ptrCertificateHandler, Context::Ptr ptrContext);
		/// Initializes the server side of the SSLManager with a default passphrase handler, a default invalid certificate handler and a default context. If this method
		/// is never called the SSLmanager will try to initialize its members from an application configuration.
		///
		/// PtrPassphraseHandler and ptrCertificateHandler can be 0. However, in this case, event delegates
		/// must be registered with the ServerVerificationError and PrivateKeyPassphraseRequired events.
		///
		/// Note: Always create the handlers (or register the corresponding event delegates) before creating
		/// the Context, as during creation of the Context the passphrase for the private key might be needed.
		///
		/// Valid initialization code would be:
		///     SharedPtr<PrivateKeyPassphraseHandler> pConsoleHandler = new KeyConsoleHandler;
		///     SharedPtr<InvalidCertificateHandler> pInvalidCertHandler = new ConsoleCertificateHandler;
		///     Context::Ptr pContext = new Context(Context::SERVER_USE, "any.pem", "any.pem", "rootcert.pem", Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
		///     SSLManager::instance().initializeServer(pConsoleHandler, pInvalidCertHandler, pContext);

	void initializeClient(PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler, InvalidCertificateHandlerPtr ptrHandler, Context::Ptr ptrContext);
		/// Initializes the client side of the SSLManager with a default passphrase handler, a default invalid certificate handler and a default context. If this method
		/// is never called the SSLmanager will try to initialize its members from an application configuration.
		///
		/// PtrPassphraseHandler and ptrCertificateHandler can be 0. However, in this case, event delegates
		/// must be registered with the ClientVerificationError and PrivateKeyPassphraseRequired events.
		///
		/// Note: Always create the handlers (or register the corresponding event delegates) before creating
		/// the Context, as during creation of the Context the passphrase for the private key might be needed.
		///
		/// Valid initialization code would be:
		///     SharedPtr<PrivateKeyPassphraseHandler> pConsoleHandler = new KeyConsoleHandler;
		///     SharedPtr<InvalidCertificateHandler> pInvalidCertHandler = new ConsoleCertificateHandler;
		///     Context::Ptr pContext = new Context(Context::CLIENT_USE, "", "", "rootcert.pem", Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
		///     SSLManager::instance().initializeClient(pConsoleHandler, pInvalidCertHandler, pContext);

	Context::Ptr defaultServerContext();
		/// Returns the default Context used by the server.
		///
		/// Unless initializeServer() has been called, the first call to this method initializes the default Context
		/// from the application configuration.

	Context::Ptr defaultClientContext();
		/// Returns the default Context used by the client.
		///
		/// Unless initializeClient() has been called, the first call to this method initializes the default Context
		/// from the application configuration.

	PrivateKeyPassphraseHandlerPtr serverPassphraseHandler();
		/// Returns the configured passphrase handler of the server. If none is set, the method will create a default one
		/// from an application configuration.

	InvalidCertificateHandlerPtr serverCertificateHandler();
		/// Returns an initialized certificate handler (used by the server to verify client cert) which determines how invalid certificates are treated.
		/// If none is set, it will try to auto-initialize one from an application configuration.

	PrivateKeyPassphraseHandlerPtr clientPassphraseHandler();
		/// Returns the configured passphrase handler of the client. If none is set, the method will create a default one
		/// from an application configuration.

	InvalidCertificateHandlerPtr clientCertificateHandler();
		/// Returns an initialized certificate handler (used by the client to verify server cert) which determines how invalid certificates are treated.
		/// If none is set, it will try to auto-initialize one from an application configuration.

	PrivateKeyFactoryMgr& privateKeyFactoryMgr();
		/// Returns the private key factory manager which stores the
		/// factories for the different registered passphrase handlers for private keys.

	CertificateHandlerFactoryMgr& certificateHandlerFactoryMgr();
		/// Returns the CertificateHandlerFactoryMgr which stores the
		/// factories for the different registered certificate handlers.

	static bool isFIPSEnabled();
		// Returns true if FIPS mode is enabled, false otherwise.

	void shutdown();
		/// Shuts down the SSLManager and releases the default Context
		/// objects. After a call to shutdown(), the SSLManager can no
		/// longer be used.
		///
		/// Normally, it's not necessary to call this method directly, as this
		/// will be called either by uninitializeSSL(), or when
		/// the SSLManager instance is destroyed.

	static const std::string CFG_SERVER_PREFIX;
	static const std::string CFG_CLIENT_PREFIX;

protected:
	static int verifyClientCallback(int ok, X509_STORE_CTX* pStore);
		/// The return value of this method defines how errors in
		/// verification are handled. Return 0 to terminate the handshake,
		/// or 1 to continue despite the error.

	static int verifyServerCallback(int ok, X509_STORE_CTX* pStore);
		/// The return value of this method defines how errors in
		/// verification are handled. Return 0 to terminate the handshake,
		/// or 1 to continue despite the error.

	static int privateKeyPassphraseCallback(char* pBuf, int size, int flag, void* userData);
		/// Method is invoked by OpenSSL to retrieve a passwd for an encrypted certificate.
		/// The request is delegated to the PrivatekeyPassword event. This method returns the
		/// length of the password.

	static Poco::Util::AbstractConfiguration& appConfig();
		/// Returns the application configuration.
		///
		/// Throws a InvalidStateException if not application instance
		/// is available.

private:
	SSLManager();
		/// Creates the SSLManager.

	~SSLManager();
		/// Destroys the SSLManager.

	void initDefaultContext(bool server);
		/// Inits the default context, the first time it is accessed.

	void initEvents(bool server);
		/// Registers delegates at the events according to the configuration.

	void initPassphraseHandler(bool server);
		/// Inits the passphrase handler.

	void initCertificateHandler(bool server);
		/// Inits the certificate handler.

	static int verifyCallback(bool server, int ok, X509_STORE_CTX* pStore);
		/// The return value of this method defines how errors in
		/// verification are handled. Return 0 to terminate the handshake,
		/// or 1 to continue despite the error.

	PrivateKeyFactoryMgr             _factoryMgr;
	CertificateHandlerFactoryMgr     _certHandlerFactoryMgr;
	Context::Ptr                     _ptrDefaultServerContext;
	PrivateKeyPassphraseHandlerPtr   _ptrServerPassphraseHandler;
	InvalidCertificateHandlerPtr     _ptrServerCertificateHandler;
	Context::Ptr                     _ptrDefaultClientContext;
	PrivateKeyPassphraseHandlerPtr   _ptrClientPassphraseHandler;
	InvalidCertificateHandlerPtr     _ptrClientCertificateHandler;
	Poco::FastMutex                  _mutex;

	static const std::string CFG_PRIV_KEY_FILE;
	static const std::string CFG_CERTIFICATE_FILE;
	static const std::string CFG_CA_LOCATION;
	static const std::string CFG_VER_MODE;
	static const Context::VerificationMode VAL_VER_MODE;
	static const std::string CFG_VER_DEPTH;
	static const int         VAL_VER_DEPTH;
	static const std::string CFG_ENABLE_DEFAULT_CA;
	static const bool        VAL_ENABLE_DEFAULT_CA;
	static const std::string CFG_CIPHER_LIST;
	static const std::string CFG_CYPHER_LIST; // for backwards compatibility
	static const std::string VAL_CIPHER_LIST;
	static const std::string CFG_PREFER_SERVER_CIPHERS;
	static const std::string CFG_DELEGATE_HANDLER;
	static const std::string VAL_DELEGATE_HANDLER;
	static const std::string CFG_CERTIFICATE_HANDLER;
	static const std::string VAL_CERTIFICATE_HANDLER;
	static const std::string CFG_CACHE_SESSIONS;
	static const std::string CFG_SESSION_ID_CONTEXT;
	static const std::string CFG_SESSION_CACHE_SIZE;
	static const std::string CFG_SESSION_TIMEOUT;
	static const std::string CFG_EXTENDED_VERIFICATION;
	static const std::string CFG_REQUIRE_TLSV1;
	static const std::string CFG_REQUIRE_TLSV1_1;
	static const std::string CFG_REQUIRE_TLSV1_2;
	static const std::string CFG_DISABLE_PROTOCOLS;
	static const std::string CFG_DH_PARAMS_FILE;
	static const std::string CFG_ECDH_CURVE;

#ifdef OPENSSL_FIPS
	static const std::string CFG_FIPS_MODE;
	static const bool        VAL_FIPS_MODE;
#endif

	friend class Poco::SingletonHolder<SSLManager>;
	friend class Context;
};


//
// inlines
//
inline PrivateKeyFactoryMgr& SSLManager::privateKeyFactoryMgr()
{
	return _factoryMgr;
}


inline CertificateHandlerFactoryMgr& SSLManager::certificateHandlerFactoryMgr()
{
	return _certHandlerFactoryMgr;
}


inline bool SSLManager::isFIPSEnabled()
{
#ifdef OPENSSL_FIPS
	return FIPS_mode() ? true : false;
#else
	return false;
#endif
}


inline int SSLManager::verifyServerCallback(int ok, X509_STORE_CTX* pStore)
{
	return SSLManager::verifyCallback(true, ok, pStore);
}


inline int SSLManager::verifyClientCallback(int ok, X509_STORE_CTX* pStore)
{
	return SSLManager::verifyCallback(false, ok, pStore);
}


} } // namespace Poco::Net


#endif // NetSSL_SSLManager_INCLUDED