NetSSL: add support for disabling certain protocols

This commit is contained in:
Guenter Obiltschnig 2016-01-19 11:36:02 +01:00
parent 3afbd82809
commit 556b4bd32f
4 changed files with 78 additions and 0 deletions

View File

@ -95,6 +95,15 @@ public:
///
/// Client: Same as VERIFY_RELAXED.
};
enum Protocols
{
PROTO_SSLV2 = 0x01,
PROTO_SSLV3 = 0x02,
PROTO_TLSV1 = 0x04,
PROTO_TLSV1_1 = 0x08,
PROTO_TLSV1_2 = 0x10
};
Context(
Usage usage,
@ -265,6 +274,14 @@ public:
/// session resumption.
///
/// The feature can be disabled by calling this method.
void disableProtocols(int protocols);
/// Disables the given protocols.
///
/// The protocols to be disabled are specified by OR-ing
/// values from the Protocols enumeration, e.g.:
///
/// context.disableProtocols(PROTO_SSLV2 | PROTO_SSLV3)
private:
void createSSLContext();

View File

@ -94,6 +94,7 @@ class NetSSL_API SSLManager
/// <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>
/// </server|client>
/// <fips>false</fips>
/// </openSSL>
@ -137,6 +138,8 @@ class NetSSL_API SSLManager
/// - 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.
/// - fips: Enable or disable OpenSSL FIPS mode. Only supported if the OpenSSL version
/// that this library is built against supports FIPS mode.
{
@ -320,6 +323,7 @@ private:
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;
#ifdef OPENSSL_FIPS
static const std::string CFG_FIPS_MODE;

View File

@ -317,6 +317,41 @@ void Context::disableStatelessSessionResumption()
}
void Context::disableProtocols(int protocols)
{
if (protocols & PROTO_SSLV2)
{
#if defined(SSL_OP_NO_SSLv2)
SSL_CTX_set_options(_pSSLContext, SSL_OP_NO_SSLv2);
#endif
}
if (protocols & PROTO_SSLV3)
{
#if defined(SSL_OP_NO_SSLv3)
SSL_CTX_set_options(_pSSLContext, SSL_OP_NO_SSLv3);
#endif
}
if (protocols & PROTO_TLSV1)
{
#if defined(SSL_OP_NO_TLSv1)
SSL_CTX_set_options(_pSSLContext, SSL_OP_NO_TLSv1);
#endif
}
if (protocols & PROTO_TLSV1_1)
{
#if defined(SSL_OP_NO_TLSv1_1)
SSL_CTX_set_options(_pSSLContext, SSL_OP_NO_TLSv1_1);
#endif
}
if (protocols & PROTO_TLSV1_2)
{
#if defined(SSL_OP_NO_TLSv1_2)
SSL_CTX_set_options(_pSSLContext, SSL_OP_NO_TLSv1_2);
#endif
}
}
void Context::createSSLContext()
{
if (SSLManager::isFIPSEnabled())

View File

@ -23,6 +23,7 @@
#include "Poco/Net/SSLException.h"
#include "Poco/SingletonHolder.h"
#include "Poco/Delegate.h"
#include "Poco/StringTokenizer.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/OptionException.h"
@ -57,6 +58,7 @@ const std::string SSLManager::CFG_EXTENDED_VERIFICATION("extendedVerification");
const std::string SSLManager::CFG_REQUIRE_TLSV1("requireTLSv1");
const std::string SSLManager::CFG_REQUIRE_TLSV1_1("requireTLSv1_1");
const std::string SSLManager::CFG_REQUIRE_TLSV1_2("requireTLSv1_2");
const std::string SSLManager::CFG_DISABLE_PROTOCOLS("disableProtocols");
#ifdef OPENSSL_FIPS
const std::string SSLManager::CFG_FIPS_MODE("openSSL.fips");
const bool SSLManager::VAL_FIPS_MODE(false);
@ -300,6 +302,26 @@ void SSLManager::initDefaultContext(bool server)
_ptrDefaultClientContext = new Context(usage, privKeyFile, certFile, caLocation, verMode, verDepth, loadDefCA, cipherList);
}
std::string disabledProtocolsList = config.getString(prefix + CFG_DISABLE_PROTOCOLS, "");
Poco::StringTokenizer dpTok(disabledProtocolsList, ";,", Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY);
int disabledProtocols = 0;
for (Poco::StringTokenizer::Iterator it = dpTok.begin(); it != dpTok.end(); ++it)
{
if (*it == "sslv2")
disabledProtocols |= Context::PROTO_SSLV2;
else if (*it == "sslv3")
disabledProtocols |= Context::PROTO_SSLV3;
else if (*it == "tlsv1")
disabledProtocols |= Context::PROTO_TLSV1;
else if (*it == "tlsv1_1")
disabledProtocols |= Context::PROTO_TLSV1_1;
else if (*it == "tlsv1_2")
disabledProtocols |= Context::PROTO_TLSV1_2;
}
if (server)
_ptrDefaultServerContext->disableProtocols(disabledProtocols);
else
_ptrDefaultClientContext->disableProtocols(disabledProtocols);
bool cacheSessions = config.getBool(prefix + CFG_CACHE_SESSIONS, false);
if (server)