THRIFT-2258 cpp: Add TLS v1.1/1.2 support to TSSLSocket.cpp
Patch: Chris Stylianou
diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
index ce971d3..5f91c89 100644
--- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
@@ -55,14 +55,45 @@
 static char uppercase(char c);
 
 // SSLContext implementation
-SSLContext::SSLContext() {
-  ctx_ = SSL_CTX_new(TLSv1_method());
+SSLContext::SSLContext(const SSLProtocol& protocol) {
+  if(protocol == SSLProtocol::SSLTLS)
+  {
+    ctx_ = SSL_CTX_new(SSLv23_method());
+  }
+  else if(protocol == SSLProtocol::SSLv3)
+  {
+    ctx_ = SSL_CTX_new(SSLv3_method());
+  }
+  else if(protocol == SSLProtocol::TLSv1_0)
+  {
+    ctx_ = SSL_CTX_new(TLSv1_method());
+  }
+  else if(protocol == SSLProtocol::TLSv1_1)
+  {
+    ctx_ = SSL_CTX_new(TLSv1_1_method());
+  }
+  else if(protocol == SSLProtocol::TLSv1_2)
+  {
+    ctx_ = SSL_CTX_new(TLSv1_2_method());
+  }
+  else
+  {
+    /// UNKNOWN PROTOCOL!
+    throw TSSLException("SSL_CTX_new: Unknown protocol");
+  }
+
   if (ctx_ == NULL) {
     string errors;
     buildErrors(errors);
     throw TSSLException("SSL_CTX_new: " + errors);
   }
   SSL_CTX_set_mode(ctx_, SSL_MODE_AUTO_RETRY);
+
+  // Disable horribly insecure SSLv2!
+  if(protocol == SSLProtocol::SSLTLS)
+  {
+    SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv2);
+  }
 }
 
 SSLContext::~SSLContext() {
@@ -350,14 +381,14 @@
 uint64_t TSSLSocketFactory::count_ = 0;
 Mutex    TSSLSocketFactory::mutex_;
 
-TSSLSocketFactory::TSSLSocketFactory(): server_(false) {
+TSSLSocketFactory::TSSLSocketFactory(const SSLProtocol& protocol): server_(false) {
   Guard guard(mutex_);
   if (count_ == 0) {
     initializeOpenSSL();
     randomize();
   }
   count_++;
-  ctx_ = boost::shared_ptr<SSLContext>(new SSLContext);
+  ctx_ = boost::shared_ptr<SSLContext>(new SSLContext(protocol));
 }
 
 TSSLSocketFactory::~TSSLSocketFactory() {
diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h
index b379d23..02d5bda 100644
--- a/lib/cpp/src/thrift/transport/TSSLSocket.h
+++ b/lib/cpp/src/thrift/transport/TSSLSocket.h
@@ -31,6 +31,15 @@
 class AccessManager;
 class SSLContext;
 
+enum SSLProtocol {
+  SSLTLS  = 0,  // Supports SSLv3 and TLSv1.
+  SSLv2   = 1,  // Supports SSLv3 only. => HORRIBLY INSECURE!
+  SSLv3   = 2,  // Supports SSLv3 only.
+  TLSv1_0 = 3,  // Supports TLSv1_0 only.
+  TLSv1_1 = 4,  // Supports TLSv1_1 only.
+  TLSv1_2 = 5   // Supports TLSv1_2 only.
+};
+
 /**
  * OpenSSL implementation for SSL socket interface.
  */
@@ -108,8 +117,10 @@
  public:
   /**
    * Constructor/Destructor
+   *
+   * @param protocol The SSL/TLS protocol to use.
    */
-  TSSLSocketFactory();
+  TSSLSocketFactory(const SSLProtocol& protocol = SSLProtocol::SSLTLS);
   virtual ~TSSLSocketFactory();
   /**
    * Create an instance of TSSLSocket with a fresh new socket.
@@ -234,7 +245,7 @@
  */
 class SSLContext {
  public:
-  SSLContext();
+  SSLContext(const SSLProtocol& protocol = SSLProtocol::SSLTLS);
   virtual ~SSLContext();
   SSL* createSSL();
   SSL_CTX* get() { return ctx_; }