You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by mm...@apache.org on 2020/08/04 22:00:34 UTC

[geode-native] 01/06: WIP: Sooooo close! Almost have hostname/port issues worked out for SNI connection

This is an automated email from the ASF dual-hosted git repository.

mmartell pushed a commit to branch GEODE-8398-sni-support-dotnet
in repository https://gitbox.apache.org/repos/asf/geode-native.git

commit a4ea0b647395e815077455eb70650e181eaf282a
Author: Blake Bender <bb...@bblake-a01.vmware.com>
AuthorDate: Fri Jul 31 15:29:15 2020 -0700

    WIP: Sooooo close!  Almost have hostname/port issues worked out for SNI connection
---
 cppcache/include/geode/PoolFactory.hpp             |   5 ++
 cppcache/integration/test/SNITest.cpp              |  26 ++++----
 .../sni-test-config/geode-config/truststore.p12    | Bin 0 -> 8983 bytes
 .../geode-config/truststore_sni.pem                |  68 +++++++++++++++++++++
 cppcache/src/PoolAttributes.cpp                    |  39 +-----------
 cppcache/src/PoolAttributes.hpp                    |  14 ++++-
 cppcache/src/PoolFactory.cpp                       |  21 +++++--
 cppcache/src/TcpSslConn.cpp                        |  18 ++++--
 cppcache/src/TcpSslConn.hpp                        |  42 ++++++++++---
 cppcache/src/ThinClientLocatorHelper.cpp           |  28 +++++++--
 cppcache/src/ThinClientLocatorHelper.hpp           |   5 ++
 cppcache/src/ThinClientPoolDM.cpp                  |   4 +-
 cryptoimpl/SSLImpl.cpp                             |   6 +-
 cryptoimpl/SSLImpl.hpp                             |   3 +-
 cryptoimpl/Ssl.hpp                                 |   3 +-
 ssl_keys/client_keys/truststore_sni.pem            |  68 +++++++++++++++++++++
 16 files changed, 270 insertions(+), 80 deletions(-)

diff --git a/cppcache/include/geode/PoolFactory.hpp b/cppcache/include/geode/PoolFactory.hpp
index 195e28d..d554482 100644
--- a/cppcache/include/geode/PoolFactory.hpp
+++ b/cppcache/include/geode/PoolFactory.hpp
@@ -427,6 +427,11 @@ class APACHE_GEODE_EXPORT PoolFactory {
   PoolFactory& addServer(const std::string& host, int port);
 
   /**
+   * Set proxy info for SNI connection.  Used for connecting via SNI proxy.
+   */
+  PoolFactory& setSniProxy(const std::string& hostname, const int port);
+
+  /**
    * If set to <code>true</code> then the created pool will have
    * server-to-client
    * subscriptions enabled.
diff --git a/cppcache/integration/test/SNITest.cpp b/cppcache/integration/test/SNITest.cpp
index 7e70619..ba8b7d0 100644
--- a/cppcache/integration/test/SNITest.cpp
+++ b/cppcache/integration/test/SNITest.cpp
@@ -28,6 +28,7 @@
 #include <geode/RegionShortcut.hpp>
 
 #include "framework/Cluster.h"
+#include "framework/TestConfig.h"
 
 namespace snitest {
 
@@ -41,7 +42,8 @@ class SNITest : public ::testing::Test {
  protected:
   SNITest() {
     certificatePassword = std::string("apachegeode");
-    currentWorkingDirectory = boost::filesystem::current_path();
+    clientSslKeysDir = boost::filesystem::path(
+        getFrameworkString(FrameworkVariable::TestClientSslKeysDir));
   }
 
   ~SNITest() override = default;
@@ -108,16 +110,16 @@ class SNITest : public ::testing::Test {
   }
 
   std::string certificatePassword;
-  boost::filesystem::path currentWorkingDirectory;
+  boost::filesystem::path clientSslKeysDir;
 };
 
-TEST_F(SNITest, DISABLED_connectViaProxyTest) {
+TEST_F(SNITest, connectViaProxyTest) {
   const auto clientTruststore =
-      (currentWorkingDirectory /
-       boost::filesystem::path("sni-test-config/geode-config/truststore.jks"));
+      (clientSslKeysDir / boost::filesystem::path("/truststore_sni.pem"));
 
   auto cache = CacheFactory()
-                   .set("log-level", "DEBUG")
+                   .set("log-level", "debug")
+                   .set("log-file", "SNITest.log")
                    .set("ssl-enabled", "true")
                    .set("ssl-truststore", clientTruststore.string())
                    .create();
@@ -127,7 +129,8 @@ TEST_F(SNITest, DISABLED_connectViaProxyTest) {
 
   cache.getPoolManager()
       .createFactory()
-      .addLocator("localhost", portNumber)
+      .setSniProxy("localhost", portNumber)
+      .addLocator("locator-maeve", 10334)
       .create("pool");
 
   auto region = cache.createRegionFactory(RegionShortcut::PROXY)
@@ -141,8 +144,7 @@ TEST_F(SNITest, DISABLED_connectViaProxyTest) {
 
 TEST_F(SNITest, connectionFailsTest) {
   const auto clientTruststore =
-      (currentWorkingDirectory /
-       boost::filesystem::path("sni-test-config/geode-config/truststore.jks"));
+      (clientSslKeysDir / boost::filesystem::path("/truststore_sni.pem"));
 
   auto cache = CacheFactory()
                    .set("log-level", "DEBUG")
@@ -152,7 +154,8 @@ TEST_F(SNITest, connectionFailsTest) {
 
   cache.getPoolManager()
       .createFactory()
-      .addLocator("localhost", 10334)
+      .setSniProxy("badProxyName", 40000)
+      .addLocator("locator-maeve", 10334)
       .create("pool");
 
   auto region = cache.createRegionFactory(RegionShortcut::PROXY)
@@ -166,8 +169,7 @@ TEST_F(SNITest, connectionFailsTest) {
 
 TEST_F(SNITest, doNothingTest) {
   const auto clientTruststore =
-      (currentWorkingDirectory /
-       boost::filesystem::path("sni-test-config/geode-config/truststore.jks"));
+      (clientSslKeysDir / boost::filesystem::path("/truststore_sni.pem"));
 
   auto cache = CacheFactory()
                    .set("log-level", "DEBUG")
diff --git a/cppcache/integration/test/sni-test-config/geode-config/truststore.p12 b/cppcache/integration/test/sni-test-config/geode-config/truststore.p12
new file mode 100644
index 0000000..339d775
Binary files /dev/null and b/cppcache/integration/test/sni-test-config/geode-config/truststore.p12 differ
diff --git a/cppcache/integration/test/sni-test-config/geode-config/truststore_sni.pem b/cppcache/integration/test/sni-test-config/geode-config/truststore_sni.pem
new file mode 100644
index 0000000..1857ce6
--- /dev/null
+++ b/cppcache/integration/test/sni-test-config/geode-config/truststore_sni.pem
@@ -0,0 +1,68 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIEXozDxjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1s
+b2NhdG9yLW1hZXZlMB4XDTIwMDQwNzE4MTc0MloXDTI1MDQwNzE4MTc0MlowGDEW
+MBQGA1UEAwwNbG9jYXRvci1tYWV2ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAOJ3jM2Rb50L+1fXyhZbaOHMuVUVGJ5jQV9wH3ijjeCEckaF29LbEtG8
+swMaxSoi4Sp/A4dp/7VI9CFZJKOX3zooZcuHyR7GSta4wH3oO55w0AfyTGeG6KF2
+Ekzj8pDPHyn/141rFAUPmMDnCfbF69Uixfi2XPxEJZw2GDN/YIHndY+X1pJ4ZuXS
+SmrORSEOSmrN9X7pqbL5D2cy15cmTK5449ZqLEfZS72Mv3gve1Ax2JMWCBEwLdob
+xW5utgmEe1/WhlhPzFr5C92znF/5Eucil/Rr+yynp31X+/QYBemYwOxbeZotHBZJ
+tMLMzaInydrZ04wgHRftNeN0TIZkPmcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
+Jj1OSCWoILzWLBU1cAiQK8Gt0DVkqcpO4/vc3CoiU2T/em74cBzTwqmgrBvykWgq
+f05jWQcod2yNg8trHrgx8F9CfyyvTXRIxttyfmbD7DAQk+qn9QBSbRJFfzo8VfNp
+dGcT7KV9UDVyzltiTorqQJHUx3acUgtLYS2XUVlbGclhnNafRO44uobOsteAG01v
+YqFa8ZaZM7qcZ88mbbKLXn6lo203JguM+TM0P7wHnzcww9sLmsP8W2cvsvefwCl4
+O7OYcjhcbEph+mIC3/zN8vF6d8xtLiMSGk6BNCHd003MBEhZHizyquGtAFLaEafX
+V6sLm65i8uF2glnQfwS5JQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIEXozDxjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1s
+b2NhdG9yLW1hZXZlMB4XDTIwMDQwNzE4MTc0MloXDTI1MDQwNzE4MTc0MlowGDEW
+MBQGA1UEAwwNbG9jYXRvci1tYWV2ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAOJ3jM2Rb50L+1fXyhZbaOHMuVUVGJ5jQV9wH3ijjeCEckaF29LbEtG8
+swMaxSoi4Sp/A4dp/7VI9CFZJKOX3zooZcuHyR7GSta4wH3oO55w0AfyTGeG6KF2
+Ekzj8pDPHyn/141rFAUPmMDnCfbF69Uixfi2XPxEJZw2GDN/YIHndY+X1pJ4ZuXS
+SmrORSEOSmrN9X7pqbL5D2cy15cmTK5449ZqLEfZS72Mv3gve1Ax2JMWCBEwLdob
+xW5utgmEe1/WhlhPzFr5C92znF/5Eucil/Rr+yynp31X+/QYBemYwOxbeZotHBZJ
+tMLMzaInydrZ04wgHRftNeN0TIZkPmcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
+Jj1OSCWoILzWLBU1cAiQK8Gt0DVkqcpO4/vc3CoiU2T/em74cBzTwqmgrBvykWgq
+f05jWQcod2yNg8trHrgx8F9CfyyvTXRIxttyfmbD7DAQk+qn9QBSbRJFfzo8VfNp
+dGcT7KV9UDVyzltiTorqQJHUx3acUgtLYS2XUVlbGclhnNafRO44uobOsteAG01v
+YqFa8ZaZM7qcZ88mbbKLXn6lo203JguM+TM0P7wHnzcww9sLmsP8W2cvsvefwCl4
+O7OYcjhcbEph+mIC3/zN8vF6d8xtLiMSGk6BNCHd003MBEhZHizyquGtAFLaEafX
+V6sLm65i8uF2glnQfwS5JQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICtDCCAZygAwIBAgIEXozGnzANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFz
+ZXJ2ZXItY2xlbWVudGluZTAeFw0yMDA0MDcxODI5NTFaFw0yNTA0MDcxODI5NTFa
+MBwxGjAYBgNVBAMMEXNlcnZlci1jbGVtZW50aW5lMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA6IzshjujS5c58AH8nJHBhlqjfNpacoNxhxykeCVsExa9
+vi0l8ezi35pte06j7gpMWhDYHokrHaw6ymp9iTi7D91yIPGeMMNUli8DnzgAzpeY
+V8SGgkrVBalkVe0GimAHXMrzeZF+8D2BEdvDAsIUbrZRACElPlLUoiO93xZZ8ad+
+fAfLVetH4lDJ54FT7ia+St6L0QxSrDLvrqmc/58ZunkQBnQcd4tMjCD1kX4l+5Q1
+eF+Rc/SbY+/8HfyCZcA98voC3dKF13U+0YAf/0ahin+8Ckm6BL/StUxFNftTtJ7l
+iKf56Y3FbSQ84Q9Te8feb05XidkF74Gifa4Q7gOzjwIDAQABMA0GCSqGSIb3DQEB
+CwUAA4IBAQDKvYcnVFryhupo156bB33BU14KN8b5joVyQLeGb2Tx+icZd/jFhqSQ
+c3f8VV+aG9+CtRi/6wesdzf9/CVF+J4ARJ7j3i60NlJi4vQJlZnou+JSBgbBiDkW
+p12ITsw7l1k2zxH8hoMPNbMK1EC/+uwVRJt92L52uShLw9zKtE4MLZxZVa7Amkf4
+zRc78fHwwPXoMjLcQxw+8JRjlciWr/hZccuppXI4qb17l6HAMvW4vCslao0c9pSp
+Opg5Q0PwVXFROIvCANdxNI9ptSrH78Thxh4rggnHs+OZF02D22oTkjquU4Xrar3u
+FXlIS8UmdkqAXGIJf0pqa48aXcqeipRe
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICrjCCAZagAwIBAgIEXozE5DANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDDA5z
+ZXJ2ZXItZG9sb3JlczAeFw0yMDA0MDcxODIyMjhaFw0yNTA0MDcxODIyMjhaMBkx
+FzAVBgNVBAMMDnNlcnZlci1kb2xvcmVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAyRTzsWsih9Boz2/aRFJsgJNDn8/C207kpvJ9lj0uBWNdZGJ86T4i
+CwvIyMFvxeYQB0qO0AHf6FvJfMgunRlCj3fD01s7AHj8kCFoM/akgo04M7iJfSkU
+dDCVuRbrFtz31akNckyxRw/oORiQ6NYGxnuAvtFdjE8jFc77WVXVU5QuqVEueJXs
+HM+t6VGEn+7GwPsSJMIuEERd+05ZlghB1HoQD4Wu4+b/CXU+8aFRad0HRXHInBl0
+0QABETcMtpe3xIotC7H1nsAMipb0jyl3p+1a49FbrAktsiko8Y2iRVv3kZ58xfx9
+2Unmw+ViEb5bVRFytqb5AIgARI/+XX1zBwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
+AQB39QXR3HLEju8B1oNCH1UciZetMxvORC2fwgXhqjbJ2YkHlykaLAAKv6DOSyc2
+HE40F2Q/Y0p0NC41+4YIiujgzKWaDI1Gw22PlceE2B49dO8evmldN2NixkirJbtm
+bEtjINAxHXbhXn8GgUKJxSqtFPTX/fG7OCYvkvGItQAhSrGo9r5ACuDYkTZsBAZp
+9jHc50TZsQ7od4jsPXrtZ6S2doOA0TdQ/+XzNyoadbG0YZbRtUVmhJN7gQfkBcjH
+/AnYeYJL1kg39AuO3PsFhgWCsR2eNizGCh7CnHx7xpJnLYAw/01TGidsku/oYFiI
+5SthBjGC992gTekW54hYtMBU
+-----END CERTIFICATE-----
diff --git a/cppcache/src/PoolAttributes.cpp b/cppcache/src/PoolAttributes.cpp
index 2b4230d..206e1a4 100644
--- a/cppcache/src/PoolAttributes.cpp
+++ b/cppcache/src/PoolAttributes.cpp
@@ -44,46 +44,13 @@ PoolAttributes::PoolAttributes()
       m_subsEnabled(PoolFactory::DEFAULT_SUBSCRIPTION_ENABLED),
       m_multiuserSecurityMode(PoolFactory::DEFAULT_MULTIUSER_SECURE_MODE),
       m_isPRSingleHopEnabled(PoolFactory::DEFAULT_PR_SINGLE_HOP_ENABLED),
-      m_serverGrp(PoolFactory::DEFAULT_SERVER_GROUP) {}
+      m_serverGrp(PoolFactory::DEFAULT_SERVER_GROUP),
+      m_sniProxyPort(0) {}
+
 std::shared_ptr<PoolAttributes> PoolAttributes::clone() {
   return std::make_shared<PoolAttributes>(*this);
 }
 
-/** Return true if all the attributes are equal to those of other. */
-bool PoolAttributes::operator==(const PoolAttributes& other) const {
-  if (m_isThreadLocalConn != other.m_isThreadLocalConn) return false;
-  if (m_freeConnTimeout != other.m_freeConnTimeout) return false;
-  if (m_loadCondInterval != other.m_loadCondInterval) return false;
-  if (m_sockBufferSize != other.m_sockBufferSize) return false;
-  if (m_readTimeout != other.m_readTimeout) return false;
-  if (m_minConns != other.m_minConns) return false;
-  if (m_maxConns != other.m_maxConns) return false;
-  if (m_retryAttempts != other.m_retryAttempts) return false;
-  if (m_statsInterval != other.m_statsInterval) return false;
-  if (m_redundancy != other.m_redundancy) return false;
-  if (m_msgTrackTimeout != other.m_msgTrackTimeout) return false;
-  if (m_subsAckInterval != other.m_subsAckInterval) return false;
-  if (m_idleTimeout != other.m_idleTimeout) return false;
-  if (m_pingInterval != other.m_pingInterval) return false;
-  if (m_updateLocatorListInterval != other.m_updateLocatorListInterval) {
-    return false;
-  }
-  if (m_subsEnabled != other.m_subsEnabled) return false;
-  if (m_multiuserSecurityMode != other.m_multiuserSecurityMode) return false;
-  if (m_isPRSingleHopEnabled != other.m_isPRSingleHopEnabled) return false;
-  if (m_serverGrp != other.m_serverGrp) return false;
-
-  if (m_initLocList.size() != other.m_initLocList.size()) return false;
-  if (m_initServList.size() != other.m_initServList.size()) return false;
-
-  if (!compareVectorOfStrings(m_initLocList, other.m_initLocList)) return false;
-  if (!compareVectorOfStrings(m_initServList, other.m_initServList)) {
-    return false;
-  }
-
-  return true;
-}
-
 bool PoolAttributes::compareVectorOfStrings(
     const std::vector<std::string>& thisVector,
     const std::vector<std::string>& otherVector) {
diff --git a/cppcache/src/PoolAttributes.hpp b/cppcache/src/PoolAttributes.hpp
index 3fee900..44d9633 100644
--- a/cppcache/src/PoolAttributes.hpp
+++ b/cppcache/src/PoolAttributes.hpp
@@ -121,6 +121,14 @@ class PoolAttributes {
     m_statsInterval = statisticInterval;
   }
 
+  const std::string& getSniProxyHost() const { return m_sniProxyHost; }
+
+  void setSniProxyHost(const std::string& host) { m_sniProxyHost = host; }
+
+  int getSniProxyPort() const { return m_sniProxyPort; }
+
+  void setSniProxyPort(const int port) { m_sniProxyPort = port; }
+
   const std::string& getServerGroup() const { return m_serverGrp; }
 
   void setServerGroup(std::string group) { m_serverGrp = group; }
@@ -168,9 +176,6 @@ class PoolAttributes {
 
   std::shared_ptr<PoolAttributes> clone();
 
-  /** Return true if all the attributes are equal to those of other. */
-  bool operator==(const PoolAttributes& other) const;
-
  private:
   bool m_isThreadLocalConn;
   std::chrono::milliseconds m_freeConnTimeout;
@@ -197,6 +202,9 @@ class PoolAttributes {
   std::vector<std::string> m_initLocList;
   std::vector<std::string> m_initServList;
 
+  std::string m_sniProxyHost;
+  int m_sniProxyPort;
+
   static bool compareVectorOfStrings(
       const std::vector<std::string>& thisVector,
       const std::vector<std::string>& otherVector);
diff --git a/cppcache/src/PoolFactory.cpp b/cppcache/src/PoolFactory.cpp
index 0ee2518..9a43f64 100644
--- a/cppcache/src/PoolFactory.cpp
+++ b/cppcache/src/PoolFactory.cpp
@@ -185,6 +185,13 @@ PoolFactory& PoolFactory::addServer(const std::string& host, int port) {
   return *this;
 }
 
+PoolFactory& PoolFactory::setSniProxy(const std::string& hostname,
+                                      const int port) {
+  m_attrs->setSniProxyHost(hostname);
+  m_attrs->setSniProxyPort(port);
+  return *this;
+}
+
 PoolFactory& PoolFactory::setSubscriptionEnabled(bool enabled) {
   m_attrs->setSubscriptionEnabled(enabled);
   return *this;
@@ -304,15 +311,17 @@ PoolFactory& PoolFactory::addCheck(const std::string& host, int port) {
                                    std::to_string(port));
   }
 
-  ACE_INET_Addr addr(port, host.c_str());
+  if (m_attrs->getSniProxyHost().empty()) {
+    ACE_INET_Addr addr(port, host.c_str());
 #ifdef WITH_IPV6
-  // check unknown host
-  // ACE will not initialize port if hostname is not resolved.
-  if (port != addr.get_port_number()) {
+    // check unknown host
+    // ACE will not initialize port if hostname is not resolved.
+    if (port != addr.get_port_number()) {
 #else
-  if (!(addr.get_ip_address())) {
+    if (!(addr.get_ip_address())) {
 #endif
-    throw IllegalArgumentException("Unknown host " + host);
+      throw IllegalArgumentException("Unknown host " + host);
+    }
   }
   return *this;
 }
diff --git a/cppcache/src/TcpSslConn.cpp b/cppcache/src/TcpSslConn.cpp
index 104b4b4..72cb7e1 100644
--- a/cppcache/src/TcpSslConn.cpp
+++ b/cppcache/src/TcpSslConn.cpp
@@ -28,6 +28,16 @@
 namespace apache {
 namespace geode {
 namespace client {
+void TcpSslConn::initSsl(const std::string& pubkeyfile, const std::string&,
+                         const std::string& pemPassword,
+                         const std::string& sniHostname,
+                         const uint16_t sniPort) {
+  LOGDEBUG(
+      "*** TcpSslConn init, pubkeyfile = %s, pemPassword = %s, sniHostname = "
+      "%s",
+      pubkeyfile.c_str(), pemPassword.c_str(), sniHostname.c_str());
+  m_sniPort = sniPort;
+}
 
 Ssl* TcpSslConn::getSSLImpl(ACE_HANDLE sock, const char* pubkeyfile,
                             const char* privkeyfile) {
@@ -50,13 +60,13 @@ Ssl* TcpSslConn::getSSLImpl(ACE_HANDLE sock, const char* pubkeyfile,
     throw IllegalStateException(msg);
   }
   return reinterpret_cast<Ssl*>(
-      func(sock, pubkeyfile, privkeyfile, m_pemPassword));
+      func(sock, pubkeyfile, privkeyfile, m_pemPassword.c_str()));
 }
 
 void TcpSslConn::createSocket(ACE_HANDLE sock) {
   LOGDEBUG("Creating SSL socket stream");
   try {
-    m_ssl = getSSLImpl(sock, m_pubkeyfile, m_privkeyfile);
+    m_ssl = getSSLImpl(sock, m_pubkeyfile.c_str(), m_privkeyfile.c_str());
   } catch (std::exception& e) {
     throw SslException(e.what());
   }
@@ -87,15 +97,13 @@ void TcpSslConn::connect() {
 
   ACE_OS::signal(SIGPIPE, SIG_IGN);  // Ignore broken pipe
 
-  // m_ssl->init();
-
   std::chrono::microseconds waitMicroSeconds = m_waitMilliSeconds;
 
   LOGDEBUG("Connecting SSL socket stream to %s:%d waiting %s micro sec",
            m_addr.get_host_name(), m_addr.get_port_number(),
            to_string(waitMicroSeconds).c_str());
 
-  int32_t retVal = m_ssl->connect(m_addr, waitMicroSeconds);
+  int32_t retVal = m_ssl->connect(m_addr, m_sniHostname, waitMicroSeconds);
 
   if (retVal == -1) {
     char msg[256];
diff --git a/cppcache/src/TcpSslConn.hpp b/cppcache/src/TcpSslConn.hpp
index c14a5b5..eb6afe0 100644
--- a/cppcache/src/TcpSslConn.hpp
+++ b/cppcache/src/TcpSslConn.hpp
@@ -33,11 +33,12 @@ class TcpSslConn : public TcpConn {
  private:
   Ssl* m_ssl;
   ACE_DLL m_dll;
-  const char* m_pubkeyfile;
-  const char* m_privkeyfile;
-  const char* m_pemPassword;
-  // adongre: Added for Ticket #758
-  // Pass extra parameter for the password
+  uint16_t m_sniPort;
+  std::string m_sniHostname;
+  std::string m_pubkeyfile;
+  std::string m_privkeyfile;
+  std::string m_pemPassword;
+
   typedef void* (*gf_create_SslImpl)(ACE_HANDLE, const char*, const char*,
                                      const char*);
   typedef void (*gf_destroy_SslImpl)(void*);
@@ -52,12 +53,27 @@ class TcpSslConn : public TcpConn {
   void createSocket(ACE_HANDLE sock) override;
 
  public:
-  TcpSslConn(const char* hostname, int32_t port,
+  TcpSslConn(
              std::chrono::microseconds waitSeconds, int32_t maxBuffSizePool,
-             const char* pubkeyfile, const char* privkeyfile,
-             const char* pemPassword)
-      : TcpConn(hostname, port, waitSeconds, maxBuffSizePool),
+             const std::string& sniProxyHostname, uint16_t sniProxyPort,
+             const std::string& pubkeyfile, const std::string& privkeyfile,
+             const std::string& pemPassword)
+      : TcpConn(sniProxyHostname.c_str(), sniProxyPort, waitSeconds, maxBuffSizePool),
+        m_ssl(nullptr),
+        m_sniPort(sniProxyPort),
+        m_sniHostname(sniProxyHostname),
+        m_pubkeyfile(pubkeyfile),
+        m_privkeyfile(privkeyfile),
+        m_pemPassword(pemPassword) {}
+
+  TcpSslConn(const std::string& hostname, uint16_t port,
+             std::chrono::microseconds connect_timeout, int32_t maxBuffSizePool,
+             const std::string& pubkeyfile, const std::string& privkeyfile,
+             const std::string& pemPassword)
+      : TcpConn(hostname.c_str(), port, connect_timeout, maxBuffSizePool),
         m_ssl(nullptr),
+        m_sniPort(0),
+        m_sniHostname(""),
         m_pubkeyfile(pubkeyfile),
         m_privkeyfile(privkeyfile),
         m_pemPassword(pemPassword) {}
@@ -67,14 +83,20 @@ class TcpSslConn : public TcpConn {
              const char* privkeyfile, const char* pemPassword)
       : TcpConn(ipaddr, waitSeconds, maxBuffSizePool),
         m_ssl(nullptr),
+        m_sniPort(0),
+        m_sniHostname(""),
         m_pubkeyfile(pubkeyfile),
         m_privkeyfile(privkeyfile),
         m_pemPassword(pemPassword) {}
 
-  // TODO:  Watch out for virt dtor calling virt methods!
+
 
   virtual ~TcpSslConn() override {}
 
+ private:
+  void initSsl(const std::string& pubkeyfile, const std::string& privkeyfile,
+               const std::string& pemPassword,
+               const std::string& sniHostname = "", const uint16_t sniPort = 0);
   // Close this tcp connection
   void close() override;
 
diff --git a/cppcache/src/ThinClientLocatorHelper.cpp b/cppcache/src/ThinClientLocatorHelper.cpp
index e7174ce..bbed2a0 100644
--- a/cppcache/src/ThinClientLocatorHelper.cpp
+++ b/cppcache/src/ThinClientLocatorHelper.cpp
@@ -66,6 +66,18 @@ ThinClientLocatorHelper::ThinClientLocatorHelper(
   }
 }
 
+ThinClientLocatorHelper::ThinClientLocatorHelper(
+    const std::vector<std::string>& locatorAddresses,
+    const std::string& sniProxyHost, int sniProxyPort,
+    const ThinClientPoolDM* poolDM)
+    : m_poolDM(poolDM),
+      m_sniProxyHost(sniProxyHost),
+      m_sniProxyPort(sniProxyPort) {
+  for (auto&& locatorAddress : locatorAddresses) {
+    m_locHostPort.emplace_back(locatorAddress);
+  }
+}
+
 Connector* ThinClientLocatorHelper::createConnection(
     Connector*& conn, const char* hostname, int32_t port,
     std::chrono::microseconds waitSeconds, int32_t maxBuffSizePool) {
@@ -75,10 +87,18 @@ Connector* ThinClientLocatorHelper::createConnection(
                                ->getDistributedSystem()
                                .getSystemProperties();
   if (systemProperties.sslEnabled()) {
-    socket = new TcpSslConn(hostname, port, waitSeconds, maxBuffSizePool,
-                            systemProperties.sslTrustStore().c_str(),
-                            systemProperties.sslKeyStore().c_str(),
-                            systemProperties.sslKeystorePassword().c_str());
+    if (m_sniProxyHost.empty()) {
+      socket = new TcpSslConn(
+          hostname, static_cast<uint16_t>(port), waitSeconds, maxBuffSizePool,
+          systemProperties.sslTrustStore(), systemProperties.sslKeyStore(),
+          systemProperties.sslKeystorePassword());
+    } else {
+      socket = new TcpSslConn(
+                              waitSeconds, maxBuffSizePool, m_sniProxyHost,
+                              m_sniProxyPort, systemProperties.sslTrustStore(),
+                              systemProperties.sslKeyStore(),
+                              systemProperties.sslKeystorePassword());
+    }
   } else {
     socket = new TcpConn(hostname, port, waitSeconds, maxBuffSizePool);
   }
diff --git a/cppcache/src/ThinClientLocatorHelper.hpp b/cppcache/src/ThinClientLocatorHelper.hpp
index c72f950..df522a3 100644
--- a/cppcache/src/ThinClientLocatorHelper.hpp
+++ b/cppcache/src/ThinClientLocatorHelper.hpp
@@ -44,6 +44,9 @@ class ThinClientLocatorHelper {
  public:
   ThinClientLocatorHelper(const std::vector<std::string>& locatorAddresses,
                           const ThinClientPoolDM* poolDM);
+  ThinClientLocatorHelper(const std::vector<std::string>& locatorAddresses,
+                          const std::string& sniProxyHost, int sniProxyPort,
+                          const ThinClientPoolDM* poolDM);
   GfErrType getEndpointForNewFwdConn(
       ServerLocation& outEndpoint, std::string& additionalLoc,
       const std::set<ServerLocation>& exclEndPts,
@@ -71,6 +74,8 @@ class ThinClientLocatorHelper {
   const ThinClientPoolDM* m_poolDM;
   ThinClientLocatorHelper(const ThinClientLocatorHelper&);
   ThinClientLocatorHelper& operator=(const ThinClientLocatorHelper&);
+  std::string m_sniProxyHost;
+  int m_sniProxyPort;
 };
 }  // namespace client
 }  // namespace geode
diff --git a/cppcache/src/ThinClientPoolDM.cpp b/cppcache/src/ThinClientPoolDM.cpp
index aab3200..8b7022d 100644
--- a/cppcache/src/ThinClientPoolDM.cpp
+++ b/cppcache/src/ThinClientPoolDM.cpp
@@ -186,7 +186,9 @@ ThinClientPoolDM::ThinClientPoolDM(const char* name,
     throw IllegalStateException(msg);
   }
   reset();
-  m_locHelper = new ThinClientLocatorHelper(m_attrs->m_initLocList, this);
+  m_locHelper = new ThinClientLocatorHelper(m_attrs->m_initLocList,
+                                            m_attrs->m_sniProxyHost,
+                                            m_attrs->m_sniProxyPort, this);
 
   m_stats = new PoolStats(
       cacheImpl->getStatisticsManager().getStatisticsFactory(), m_poolName);
diff --git a/cryptoimpl/SSLImpl.cpp b/cryptoimpl/SSLImpl.cpp
index dad15a5..fe98e2e 100644
--- a/cryptoimpl/SSLImpl.cpp
+++ b/cryptoimpl/SSLImpl.cpp
@@ -18,7 +18,9 @@
 #include "SSLImpl.hpp"
 
 #include <cstdint>
+#include <iostream>
 #include <stdexcept>
+#include <string>
 
 #include <ace/Guard_T.h>
 
@@ -116,9 +118,11 @@ int SSLImpl::listen(ACE_INET_Addr addr, std::chrono::microseconds waitSeconds) {
   }
 }
 
-int SSLImpl::connect(ACE_INET_Addr ipaddr,
+int SSLImpl::connect(ACE_INET_Addr ipaddr, const std::string &proxyHostname,
                      std::chrono::microseconds waitSeconds) {
   ACE_SSL_SOCK_Connector conn;
+
+  SSL_set_tlsext_host_name(m_io->ssl(), proxyHostname.c_str());
   if (waitSeconds > std::chrono::microseconds::zero()) {
     ACE_Time_Value wtime(waitSeconds);
     return conn.connect(*m_io, ipaddr, &wtime);
diff --git a/cryptoimpl/SSLImpl.hpp b/cryptoimpl/SSLImpl.hpp
index a70e965..9e6095b 100644
--- a/cryptoimpl/SSLImpl.hpp
+++ b/cryptoimpl/SSLImpl.hpp
@@ -66,7 +66,8 @@ class SSLImpl : public apache::geode::client::Ssl {
 
   int setOption(int, int, void*, int) override;
   int listen(ACE_INET_Addr, std::chrono::microseconds) override;
-  int connect(ACE_INET_Addr, std::chrono::microseconds) override;
+  int connect(ACE_INET_Addr, const std::string& proxyHostname,
+              std::chrono::microseconds) override;
   ssize_t recv(void*, size_t, const ACE_Time_Value*, size_t*) override;
   ssize_t send(const void*, size_t, const ACE_Time_Value*, size_t*) override;
   int getLocalAddr(ACE_Addr&) override;
diff --git a/cryptoimpl/Ssl.hpp b/cryptoimpl/Ssl.hpp
index 45b8da5..16b20ba 100644
--- a/cryptoimpl/Ssl.hpp
+++ b/cryptoimpl/Ssl.hpp
@@ -33,7 +33,8 @@ class Ssl {
   virtual ~Ssl() {}
   virtual int setOption(int, int, void*, int) = 0;
   virtual int listen(ACE_INET_Addr, std::chrono::microseconds) = 0;
-  virtual int connect(ACE_INET_Addr, std::chrono::microseconds) = 0;
+  virtual int connect(ACE_INET_Addr, const std::string& proxyHostname,
+                      std::chrono::microseconds) = 0;
   virtual ssize_t recv(void*, size_t, const ACE_Time_Value*, size_t*) = 0;
   virtual ssize_t send(const void*, size_t, const ACE_Time_Value*, size_t*) = 0;
   virtual int getLocalAddr(ACE_Addr&) = 0;
diff --git a/ssl_keys/client_keys/truststore_sni.pem b/ssl_keys/client_keys/truststore_sni.pem
new file mode 100644
index 0000000..1857ce6
--- /dev/null
+++ b/ssl_keys/client_keys/truststore_sni.pem
@@ -0,0 +1,68 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIEXozDxjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1s
+b2NhdG9yLW1hZXZlMB4XDTIwMDQwNzE4MTc0MloXDTI1MDQwNzE4MTc0MlowGDEW
+MBQGA1UEAwwNbG9jYXRvci1tYWV2ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAOJ3jM2Rb50L+1fXyhZbaOHMuVUVGJ5jQV9wH3ijjeCEckaF29LbEtG8
+swMaxSoi4Sp/A4dp/7VI9CFZJKOX3zooZcuHyR7GSta4wH3oO55w0AfyTGeG6KF2
+Ekzj8pDPHyn/141rFAUPmMDnCfbF69Uixfi2XPxEJZw2GDN/YIHndY+X1pJ4ZuXS
+SmrORSEOSmrN9X7pqbL5D2cy15cmTK5449ZqLEfZS72Mv3gve1Ax2JMWCBEwLdob
+xW5utgmEe1/WhlhPzFr5C92znF/5Eucil/Rr+yynp31X+/QYBemYwOxbeZotHBZJ
+tMLMzaInydrZ04wgHRftNeN0TIZkPmcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
+Jj1OSCWoILzWLBU1cAiQK8Gt0DVkqcpO4/vc3CoiU2T/em74cBzTwqmgrBvykWgq
+f05jWQcod2yNg8trHrgx8F9CfyyvTXRIxttyfmbD7DAQk+qn9QBSbRJFfzo8VfNp
+dGcT7KV9UDVyzltiTorqQJHUx3acUgtLYS2XUVlbGclhnNafRO44uobOsteAG01v
+YqFa8ZaZM7qcZ88mbbKLXn6lo203JguM+TM0P7wHnzcww9sLmsP8W2cvsvefwCl4
+O7OYcjhcbEph+mIC3/zN8vF6d8xtLiMSGk6BNCHd003MBEhZHizyquGtAFLaEafX
+V6sLm65i8uF2glnQfwS5JQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIEXozDxjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1s
+b2NhdG9yLW1hZXZlMB4XDTIwMDQwNzE4MTc0MloXDTI1MDQwNzE4MTc0MlowGDEW
+MBQGA1UEAwwNbG9jYXRvci1tYWV2ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAOJ3jM2Rb50L+1fXyhZbaOHMuVUVGJ5jQV9wH3ijjeCEckaF29LbEtG8
+swMaxSoi4Sp/A4dp/7VI9CFZJKOX3zooZcuHyR7GSta4wH3oO55w0AfyTGeG6KF2
+Ekzj8pDPHyn/141rFAUPmMDnCfbF69Uixfi2XPxEJZw2GDN/YIHndY+X1pJ4ZuXS
+SmrORSEOSmrN9X7pqbL5D2cy15cmTK5449ZqLEfZS72Mv3gve1Ax2JMWCBEwLdob
+xW5utgmEe1/WhlhPzFr5C92znF/5Eucil/Rr+yynp31X+/QYBemYwOxbeZotHBZJ
+tMLMzaInydrZ04wgHRftNeN0TIZkPmcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
+Jj1OSCWoILzWLBU1cAiQK8Gt0DVkqcpO4/vc3CoiU2T/em74cBzTwqmgrBvykWgq
+f05jWQcod2yNg8trHrgx8F9CfyyvTXRIxttyfmbD7DAQk+qn9QBSbRJFfzo8VfNp
+dGcT7KV9UDVyzltiTorqQJHUx3acUgtLYS2XUVlbGclhnNafRO44uobOsteAG01v
+YqFa8ZaZM7qcZ88mbbKLXn6lo203JguM+TM0P7wHnzcww9sLmsP8W2cvsvefwCl4
+O7OYcjhcbEph+mIC3/zN8vF6d8xtLiMSGk6BNCHd003MBEhZHizyquGtAFLaEafX
+V6sLm65i8uF2glnQfwS5JQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICtDCCAZygAwIBAgIEXozGnzANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFz
+ZXJ2ZXItY2xlbWVudGluZTAeFw0yMDA0MDcxODI5NTFaFw0yNTA0MDcxODI5NTFa
+MBwxGjAYBgNVBAMMEXNlcnZlci1jbGVtZW50aW5lMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA6IzshjujS5c58AH8nJHBhlqjfNpacoNxhxykeCVsExa9
+vi0l8ezi35pte06j7gpMWhDYHokrHaw6ymp9iTi7D91yIPGeMMNUli8DnzgAzpeY
+V8SGgkrVBalkVe0GimAHXMrzeZF+8D2BEdvDAsIUbrZRACElPlLUoiO93xZZ8ad+
+fAfLVetH4lDJ54FT7ia+St6L0QxSrDLvrqmc/58ZunkQBnQcd4tMjCD1kX4l+5Q1
+eF+Rc/SbY+/8HfyCZcA98voC3dKF13U+0YAf/0ahin+8Ckm6BL/StUxFNftTtJ7l
+iKf56Y3FbSQ84Q9Te8feb05XidkF74Gifa4Q7gOzjwIDAQABMA0GCSqGSIb3DQEB
+CwUAA4IBAQDKvYcnVFryhupo156bB33BU14KN8b5joVyQLeGb2Tx+icZd/jFhqSQ
+c3f8VV+aG9+CtRi/6wesdzf9/CVF+J4ARJ7j3i60NlJi4vQJlZnou+JSBgbBiDkW
+p12ITsw7l1k2zxH8hoMPNbMK1EC/+uwVRJt92L52uShLw9zKtE4MLZxZVa7Amkf4
+zRc78fHwwPXoMjLcQxw+8JRjlciWr/hZccuppXI4qb17l6HAMvW4vCslao0c9pSp
+Opg5Q0PwVXFROIvCANdxNI9ptSrH78Thxh4rggnHs+OZF02D22oTkjquU4Xrar3u
+FXlIS8UmdkqAXGIJf0pqa48aXcqeipRe
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICrjCCAZagAwIBAgIEXozE5DANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDDA5z
+ZXJ2ZXItZG9sb3JlczAeFw0yMDA0MDcxODIyMjhaFw0yNTA0MDcxODIyMjhaMBkx
+FzAVBgNVBAMMDnNlcnZlci1kb2xvcmVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAyRTzsWsih9Boz2/aRFJsgJNDn8/C207kpvJ9lj0uBWNdZGJ86T4i
+CwvIyMFvxeYQB0qO0AHf6FvJfMgunRlCj3fD01s7AHj8kCFoM/akgo04M7iJfSkU
+dDCVuRbrFtz31akNckyxRw/oORiQ6NYGxnuAvtFdjE8jFc77WVXVU5QuqVEueJXs
+HM+t6VGEn+7GwPsSJMIuEERd+05ZlghB1HoQD4Wu4+b/CXU+8aFRad0HRXHInBl0
+0QABETcMtpe3xIotC7H1nsAMipb0jyl3p+1a49FbrAktsiko8Y2iRVv3kZ58xfx9
+2Unmw+ViEb5bVRFytqb5AIgARI/+XX1zBwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
+AQB39QXR3HLEju8B1oNCH1UciZetMxvORC2fwgXhqjbJ2YkHlykaLAAKv6DOSyc2
+HE40F2Q/Y0p0NC41+4YIiujgzKWaDI1Gw22PlceE2B49dO8evmldN2NixkirJbtm
+bEtjINAxHXbhXn8GgUKJxSqtFPTX/fG7OCYvkvGItQAhSrGo9r5ACuDYkTZsBAZp
+9jHc50TZsQ7od4jsPXrtZ6S2doOA0TdQ/+XzNyoadbG0YZbRtUVmhJN7gQfkBcjH
+/AnYeYJL1kg39AuO3PsFhgWCsR2eNizGCh7CnHx7xpJnLYAw/01TGidsku/oYFiI
+5SthBjGC992gTekW54hYtMBU
+-----END CERTIFICATE-----