diff --git a/contrib/native/client/src/clientlib/channel.cpp b/contrib/native/client/src/clientlib/channel.cpp index bdc19f7ad33..3af17d6ee69 100644 --- a/contrib/native/client/src/clientlib/channel.cpp +++ b/contrib/native/client/src/clientlib/channel.cpp @@ -210,12 +210,12 @@ ChannelContext* ChannelFactory::getChannelContext(channelType_t t, DrillUserProp verifyMode = boost::asio::ssl::context::verify_none; } - long customSSLCtxOptions = 0; + long customSSLCtxOptions = SSLChannelContext::ApplyMinTLSRestriction(protocol); std::string sslOptions; props->getProp(USERPROP_CUSTOM_SSLCTXOPTIONS, sslOptions); if (!sslOptions.empty()){ try{ - customSSLCtxOptions = boost::lexical_cast(sslOptions); + customSSLCtxOptions |= boost::lexical_cast(sslOptions); } catch (...){ DRILL_LOG(LOG_ERROR) << "Unable to parse custom SSL CTX options." << std::endl; diff --git a/contrib/native/client/src/clientlib/channel.hpp b/contrib/native/client/src/clientlib/channel.hpp index fec4659ccb5..7d4ad60cafa 100644 --- a/contrib/native/client/src/clientlib/channel.hpp +++ b/contrib/native/client/src/clientlib/channel.hpp @@ -82,11 +82,34 @@ class UserProperties; return boost::asio::ssl::context::tlsv11; } else if (version == "tlsv1") { return boost::asio::ssl::context::tlsv1; + } else if ((version == "tlsv1+") || (version == "tlsv11+") || (version == "tlsv12+")) { + // SSLv2 and SSLv3 are disabled, so this is the equivalent of 'tls' only mode. + // In boost version 1.64+, they've added support for context::tls; method. + return boost::asio::ssl::context::sslv23; } else { return boost::asio::ssl::context::tlsv12; } } + /// @brief Applies Minimum TLS protocol restrictions. + /// tlsv11+ means restrict to TLS version 1.1 and higher. + /// tlsv12+ means restrict to TLS version 1.2 and higher. + /// Please note that SSL_OP_NO_TLSv tags are depreecated in openSSL 1.1.0. + /// + /// @param in_ver The protocol version. + /// + /// @return The SSL context options. + static long ApplyMinTLSRestriction(const std::string & in_ver){ +#if defined(IS_SSL_ENABLED) + if (in_ver == "tlsv11+") { + return SSL_OP_NO_TLSv1; + } else if (in_ver == "tlsv12+") { + return (SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); + } +#endif + return SSL_OP_NO_SSLv3; + } + SSLChannelContext(DrillUserProperties *props, boost::asio::ssl::context::method tlsVersion, boost::asio::ssl::verify_mode verifyMode, @@ -256,6 +279,12 @@ class UserProperties; CONN_HANDSHAKE_FAILED, getMessage(ERR_CONN_SSL_CERTVERIFY, in_err.what())); } + else if (boost::asio::error::get_ssl_category() == errcode.category() && + SSL_R_UNSUPPORTED_PROTOCOL == ERR_GET_REASON(errcode.value())){ + return handleError( + CONN_HANDSHAKE_FAILED, + getMessage(ERR_CONN_SSL_PROTOVER, in_err.what())); + } else{ return handleError( CONN_HANDSHAKE_FAILED, diff --git a/contrib/native/client/src/clientlib/errmsgs.cpp b/contrib/native/client/src/clientlib/errmsgs.cpp index 82f24fd202e..5ab8d8eb81d 100644 --- a/contrib/native/client/src/clientlib/errmsgs.cpp +++ b/contrib/native/client/src/clientlib/errmsgs.cpp @@ -60,6 +60,7 @@ static Drill::ErrorMessages errorMessages[]={ {ERR_CONN_SSL_GENERAL, ERR_CATEGORY_CONN, 0, "Encountered an exception during SSL handshake. [Details: %s]"}, {ERR_CONN_SSL_CN, ERR_CATEGORY_CONN, 0, "SSL certificate host name verification failure. [Details: %s]" }, {ERR_CONN_SSL_CERTVERIFY, ERR_CATEGORY_CONN, 0, "SSL certificate verification failed. [Details: %s]"}, + {ERR_CONN_SSL_PROTOVER, ERR_CATEGORY_CONN, 0, "Unsupported TLS protocol version. [Details: %s]" }, {ERR_QRY_OUTOFMEM, ERR_CATEGORY_QRY, 0, "Out of memory."}, {ERR_QRY_COMMERR, ERR_CATEGORY_QRY, 0, "Communication error. %s"}, {ERR_QRY_INVREADLEN, ERR_CATEGORY_QRY, 0, "Internal Error: Received a message with an invalid read length."}, diff --git a/contrib/native/client/src/clientlib/errmsgs.hpp b/contrib/native/client/src/clientlib/errmsgs.hpp index 7bcb80579d8..7230611cd3a 100644 --- a/contrib/native/client/src/clientlib/errmsgs.hpp +++ b/contrib/native/client/src/clientlib/errmsgs.hpp @@ -58,7 +58,8 @@ namespace Drill{ #define ERR_CONN_SSL_GENERAL DRILL_ERR_START+26 #define ERR_CONN_SSL_CN DRILL_ERR_START+27 #define ERR_CONN_SSL_CERTVERIFY DRILL_ERR_START+28 -#define ERR_CONN_MAX DRILL_ERR_START+28 +#define ERR_CONN_SSL_PROTOVER DRILL_ERR_START+29 +#define ERR_CONN_MAX DRILL_ERR_START+29 #define ERR_QRY_OUTOFMEM ERR_CONN_MAX+1 #define ERR_QRY_COMMERR ERR_CONN_MAX+2 diff --git a/contrib/native/client/src/include/drill/common.hpp b/contrib/native/client/src/include/drill/common.hpp index b5bb522bee0..13246017e6c 100644 --- a/contrib/native/client/src/include/drill/common.hpp +++ b/contrib/native/client/src/include/drill/common.hpp @@ -173,7 +173,7 @@ typedef enum{ #define USERPROP_PASSWORD "password" #define USERPROP_SCHEMA "schema" #define USERPROP_USESSL "enableTLS" -#define USERPROP_TLSPROTOCOL "TLSProtocol" //TLS version. The exact TLS version. +#define USERPROP_TLSPROTOCOL "TLSProtocol" //TLS version. #define USERPROP_CUSTOM_SSLCTXOPTIONS "CustomSSLCtxOptions" // The custom SSL CTX options. #define USERPROP_CERTFILEPATH "certFilePath" // pem file path and name // TODO: support truststore protected by password.