Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion NetSSL_OpenSSL/include/Poco/Net/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
#include "Poco/SharedPtr.h"
#include "Poco/AutoPtr.h"
#include <openssl/ssl.h>

#if POCO_OPENSSL_VERSION_PREREQ(3, 0, 0)
#include <openssl/types.h>
#endif

#include <cstdlib>


Expand Down Expand Up @@ -155,6 +160,11 @@ class NetSSL_API Context: public Poco::RefCountedObject
Params(KeyDHGroup dhBits = KEY_DH_GROUP_2048);
/// Initializes the struct with default values.

#if POCO_OPENSSL_VERSION_PREREQ(3, 0, 0)
std::string providerName;
OSSL_LIB_CTX *libctx = nullptr;
#endif

std::string privateKeyFile;
/// Path to the private key file used for encryption.
/// Can be empty if no private key file is used.
Expand Down Expand Up @@ -304,6 +314,46 @@ class NetSSL_API Context: public Poco::RefCountedObject
/// Note that a private key and/or certificate must be specified with
/// usePrivateKey()/useCertificate() before the Context can be used.

#if POCO_OPENSSL_VERSION_PREREQ(3, 0, 0)
Context( Usage usage,
OSSL_LIB_CTX *libctx,
const std::string &provider,
VerificationMode verificationMode = VERIFY_RELAXED,
int verificationDepth = 9,
bool loadDefaultCAs = false,
const std::string &cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH" );
/// Creates a Context.
///
/// * usage specifies whether the context is used by a client or server.
/// * libctx pointer to OpenSSL library context (i.e. from OSSL_LIB_CTX_new)
/// * provider specifies the custom provider query string
/// * verificationMode specifies whether and how peer certificates are validated.
/// * verificationDepth sets the upper limit for verification chain sizes. Verification
/// will fail if a certificate chain larger than this is encountered.
/// * loadDefaultCAs specifies whether the builtin CA certificates from OpenSSL are used.
/// * cipherList specifies the supported ciphers in OpenSSL notation.
///
/// Note that a private key and/or certificate must be specified with
/// usePrivateKey()/useCertificate() or loaded through a registered provider before the Context can be used.
///
/// Example usage:
/// * // Create a OpenSSL libary context and set default provider library search path.
/// * auto ctx = OSSL_LIB_CTX_new();
/// * OSSL_PROVIDER_set_default_search_path( ctx, "<a valid path>" );
/// *
/// * // Load providers
/// * auto provider = OSSL_PROVIDER_load( ctx, "<a custom provider name>" );
/// * auto providerDefault = OSSL_PROVIDER_load( ctx, "default" );
/// *
/// * // Create context to be used by server.
/// * auto serverCtx = new Poco::Net::Context( Poco::Net::Context::SERVER_USE, ctx, "<a provider query string>", Poco::Net::Context::VERIFY_STRICT );
/// * ...
/// * // clean-up
/// * OSSL_PROVIDER_unload( provider );
/// * OSSL_PROVIDER_unload( providerDefault );
/// * OSSL_LIB_CTX_free( ctx );
#endif

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

Expand Down Expand Up @@ -523,14 +573,17 @@ class NetSSL_API Context: public Poco::RefCountedObject
void init(const Params& params);
/// Initializes the Context with the given parameters.

void initContext(const Params& params, const SSL_METHOD *method);
/// Helper for init.

void initDH(KeyDHGroup keyDHGroup, const std::string& dhFile);
/// Initializes the Context with Diffie-Hellman parameters.

void initECDH(const std::string& curve);
/// Initializes the Context with Elliptic-Curve Diffie-Hellman key
/// exchange curve parameters.

void createSSLContext();
void createSSLContext( const Params &params );
/// Create a SSL_CTX object according to Context configuration.

Usage _usage;
Expand Down
69 changes: 57 additions & 12 deletions NetSSL_OpenSSL/src/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ Context::Params::Params(KeyDHGroup dhBits):
cipherList("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"),
dhGroup(dhBits),
securityLevel(SECURITY_LEVEL_NONE)
#if POCO_OPENSSL_VERSION_PREREQ(3, 0, 0)
,libctx(0)
#endif
{
}

Expand Down Expand Up @@ -113,6 +116,36 @@ Context::Context(
}


#if POCO_OPENSSL_VERSION_PREREQ(3, 0, 0)

Context::Context(
Usage usage,
OSSL_LIB_CTX *libctx,
const std::string &provider,
VerificationMode verificationMode,
int verificationDepth,
bool loadDefaultCAs,
const std::string &cipherList ) :
_usage( usage ),
_mode( verificationMode ),
_pSSLContext( 0 ),
_extendedCertificateVerification( true ),
_ocspStaplingResponseVerification( false )
{
Params params;
params.providerName = provider;
params.libctx = libctx;
params.verificationMode = verificationMode;
params.verificationDepth = verificationDepth;
params.loadDefaultCAs = loadDefaultCAs;
params.cipherList = cipherList;

init( params );
}

#endif


Context::~Context()
{
try
Expand All @@ -131,7 +164,7 @@ void Context::init(const Params& params)
{
Poco::Crypto::OpenSSLInitializer::initialize();

createSSLContext();
createSSLContext( params );

try
{
Expand Down Expand Up @@ -562,63 +595,75 @@ void Context::setInvalidCertificateHandler(InvalidCertificateHandlerPtr pInvalid
_pInvalidCertificateHandler = pInvalidCertificateHandler;
}

void Context::initContext(const Params& params, const SSL_METHOD *method) {
#if POCO_OPENSSL_VERSION_PREREQ(3, 0, 0)
if ( nullptr != params.libctx ) {
_pSSLContext = SSL_CTX_new_ex( params.libctx, params.providerName.empty() ? nullptr : params.providerName.c_str(), method );
}
else {
_pSSLContext = SSL_CTX_new( method );
}
#else
_pSSLContext = SSL_CTX_new( method );
#endif
}

void Context::createSSLContext()
void Context::createSSLContext( const Params &params )
{
int minTLSVersion = 0;

switch (_usage)
{
case CLIENT_USE:
case TLS_CLIENT_USE:
_pSSLContext = SSL_CTX_new(TLS_client_method());
initContext(params, TLS_client_method());
minTLSVersion = TLS1_VERSION;
break;

case SERVER_USE:
case TLS_SERVER_USE:
_pSSLContext = SSL_CTX_new(TLS_server_method());
initContext(params, TLS_server_method());
minTLSVersion = TLS1_VERSION;
break;

case TLSV1_CLIENT_USE:
_pSSLContext = SSL_CTX_new(TLS_client_method());
initContext(params, TLS_client_method());
minTLSVersion = TLS1_VERSION;
break;

case TLSV1_SERVER_USE:
_pSSLContext = SSL_CTX_new(TLS_server_method());
initContext(params, TLS_server_method());
minTLSVersion = TLS1_VERSION;
break;

#if !defined(OPENSSL_NO_TLS1)
case TLSV1_1_CLIENT_USE:
_pSSLContext = SSL_CTX_new(TLS_client_method());
initContext(params, TLS_client_method());
minTLSVersion = TLS1_1_VERSION;
break;

case TLSV1_1_SERVER_USE:
_pSSLContext = SSL_CTX_new(TLS_server_method());
initContext(params, TLS_server_method());
minTLSVersion = TLS1_1_VERSION;
break;

case TLSV1_2_CLIENT_USE:
_pSSLContext = SSL_CTX_new(TLS_client_method());
initContext(params, TLS_client_method());
minTLSVersion = TLS1_2_VERSION;
break;

case TLSV1_2_SERVER_USE:
_pSSLContext = SSL_CTX_new(TLS_server_method());
initContext(params, TLS_server_method());
minTLSVersion = TLS1_2_VERSION;
break;

case TLSV1_3_CLIENT_USE:
_pSSLContext = SSL_CTX_new(TLS_client_method());
initContext(params, TLS_client_method());
minTLSVersion = TLS1_3_VERSION;
break;

case TLSV1_3_SERVER_USE:
_pSSLContext = SSL_CTX_new(TLS_server_method());
initContext(params, TLS_server_method());
minTLSVersion = TLS1_3_VERSION;
break;
#endif
Expand Down
78 changes: 78 additions & 0 deletions NetSSL_OpenSSL/testsuite/src/ContextTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
using Poco::Crypto::X509Certificate;
using Poco::Net::Context;
using Poco::Net::SSLContextException;
using Poco::Net::SSLException;
using Poco::Net::SSLManager;
using Poco::Util::Application;

Expand Down Expand Up @@ -127,6 +128,80 @@ void ContextTest::testBuiltInDHParameters()
assertEqual (std::string("dh_2048_256"), negotiatedDHGroup(Context::KEY_DH_GROUP_2048));
assertEqual (std::string("dh_1024_160"), negotiatedDHGroup(Context::KEY_DH_GROUP_1024));
}


void ContextTest::testProviderContext()
{
using LibCtxPtr = std::unique_ptr<OSSL_LIB_CTX, decltype(&OSSL_LIB_CTX_free)>;
LibCtxPtr pLibCtx(OSSL_LIB_CTX_new(), &OSSL_LIB_CTX_free);
assertNotNullPtr (pLibCtx.get());

OSSL_PROVIDER* pProvider = OSSL_PROVIDER_load(pLibCtx.get(), "default");
assertNotNullPtr (pProvider);

Context::Ptr pContext = new Context(
Context::TLS_SERVER_USE,
pLibCtx.get(),
"provider=default",
Context::VERIFY_NONE);
assertNotNullPtr (pContext->sslContext());

OSSL_PROVIDER_unload(pProvider);
}


void ContextTest::testProviderContextLibctxOnlyIsUsed()
{

using LibCtxPtr = std::unique_ptr<OSSL_LIB_CTX, decltype(&OSSL_LIB_CTX_free)>;
LibCtxPtr pLibCtx(OSSL_LIB_CTX_new(), &OSSL_LIB_CTX_free);
assertNotNullPtr (pLibCtx.get());

OSSL_PROVIDER* pProvider = OSSL_PROVIDER_load(pLibCtx.get(), "default");
assertNotNullPtr (pProvider);

Context::Ptr pContext = new Context(
Context::TLS_SERVER_USE,
pLibCtx.get(),
"", // no provider query string, only a custom libctx
Context::VERIFY_NONE);
assertNotNullPtr (pContext->sslContext());

OSSL_PROVIDER_unload(pProvider);
}


void ContextTest::testProviderContextInvalidProviderQueryRejected()
{
ErrorQueueCleaner cleaner;

using LibCtxPtr = std::unique_ptr<OSSL_LIB_CTX, decltype(&OSSL_LIB_CTX_free)>;
LibCtxPtr pLibCtx(OSSL_LIB_CTX_new(), &OSSL_LIB_CTX_free);
assertNotNullPtr (pLibCtx.get());

using ProviderPtr = std::unique_ptr<OSSL_PROVIDER, decltype(&OSSL_PROVIDER_unload)>;
ProviderPtr pProvider(OSSL_PROVIDER_load(pLibCtx.get(), "default"), &OSSL_PROVIDER_unload);
assertNotNullPtr (pProvider.get());

Context::Params params;
params.libctx = pLibCtx.get();
params.providerName = "provider=nonexistent-provider";
params.cipherSuites = "TLS_AES_256_GCM_SHA384";
params.verificationMode = Context::VERIFY_NONE;

ERR_clear_error();
try
{
Context::Ptr pContext = new Context(Context::TLS_SERVER_USE, params);
fail("unresolvable provider query string - must throw");
}
catch (SSLContextException&)
{
}
catch ( SSLException & )
{
}
}
#endif


Expand Down Expand Up @@ -276,6 +351,9 @@ CppUnit::Test* ContextTest::suite()
CppUnit_addTest(pSuite, ContextTest, testDHParametersRejectedBySecurityLevel);
#if POCO_OPENSSL_VERSION_PREREQ(3, 0, 0)
CppUnit_addTest(pSuite, ContextTest, testBuiltInDHParameters);
CppUnit_addTest(pSuite, ContextTest, testProviderContext);
CppUnit_addTest(pSuite, ContextTest, testProviderContextLibctxOnlyIsUsed);
CppUnit_addTest(pSuite, ContextTest, testProviderContextInvalidProviderQueryRejected);
#endif
CppUnit_addTest(pSuite, ContextTest, testAddChainCertificateWithoutX509);
CppUnit_addTest(pSuite, ContextTest, testClientContextIgnoresDHParameters);
Expand Down
4 changes: 4 additions & 0 deletions NetSSL_OpenSSL/testsuite/src/ContextTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class ContextTest: public CppUnit::TestCase
void testDHParametersRejectedBySecurityLevel();
#if POCO_OPENSSL_VERSION_PREREQ(3, 0, 0)
void testBuiltInDHParameters();
void testProviderContext();
void testProviderContextLibctxOnlyIsUsed();
void testProviderContextInvalidProviderQueryRejected();
#endif
void testAddChainCertificateWithoutX509();
void testClientContextIgnoresDHParameters();
Expand All @@ -50,6 +53,7 @@ class ContextTest: public CppUnit::TestCase
/// Returns the OpenSSL name of the DH group that a server Context with
/// the given built-in parameters sends in a TLS 1.2 DHE handshake.
#endif

};


Expand Down
Loading