From 556b4bd32f64452437a3cd18e98d67b680b7e517 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 19 Jan 2016 11:36:02 +0100 Subject: [PATCH] NetSSL: add support for disabling certain protocols --- NetSSL_OpenSSL/include/Poco/Net/Context.h | 17 ++++++++++ NetSSL_OpenSSL/include/Poco/Net/SSLManager.h | 4 +++ NetSSL_OpenSSL/src/Context.cpp | 35 ++++++++++++++++++++ NetSSL_OpenSSL/src/SSLManager.cpp | 22 ++++++++++++ 4 files changed, 78 insertions(+) diff --git a/NetSSL_OpenSSL/include/Poco/Net/Context.h b/NetSSL_OpenSSL/include/Poco/Net/Context.h index 24a5bc156..805885381 100644 --- a/NetSSL_OpenSSL/include/Poco/Net/Context.h +++ b/NetSSL_OpenSSL/include/Poco/Net/Context.h @@ -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(); diff --git a/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h b/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h index 8aa1c8f81..058c73bac 100644 --- a/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h +++ b/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h @@ -94,6 +94,7 @@ class NetSSL_API SSLManager /// true|false /// true|false /// true|false + /// sslv2,sslv3,tlsv1,tlsv1_1,tlsv1_2 /// /// false /// @@ -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; diff --git a/NetSSL_OpenSSL/src/Context.cpp b/NetSSL_OpenSSL/src/Context.cpp index 20c2ff6be..7a79cf0d0 100644 --- a/NetSSL_OpenSSL/src/Context.cpp +++ b/NetSSL_OpenSSL/src/Context.cpp @@ -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()) diff --git a/NetSSL_OpenSSL/src/SSLManager.cpp b/NetSSL_OpenSSL/src/SSLManager.cpp index e881ebbb1..f58e5ae18 100644 --- a/NetSSL_OpenSSL/src/SSLManager.cpp +++ b/NetSSL_OpenSSL/src/SSLManager.cpp @@ -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)