GEODE-3415: Fix SSL certificate chain support (#480)

* Fix SSL certificate chain support
* Add new SslException.

Co-authored-by: igodwin@pivotal.io
Co-authored-by: jbarrett@pivotal.io

diff --git a/cppcache/include/geode/ExceptionTypes.hpp b/cppcache/include/geode/ExceptionTypes.hpp
index 9f5a48b..c3fb370 100644
--- a/cppcache/include/geode/ExceptionTypes.hpp
+++ b/cppcache/include/geode/ExceptionTypes.hpp
@@ -812,6 +812,18 @@
   }
 };
 
+/**
+ *@brief Thrown when an error is encountered during an SSL operation.
+ **/
+class APACHE_GEODE_EXPORT SslException : public Exception {
+ public:
+  using Exception::Exception;
+  ~SslException() noexcept override {}
+  std::string getName() const override {
+    return "apache::geode::client::SslException";
+  }
+};
+
 }  // namespace client
 }  // namespace geode
 }  // namespace apache
diff --git a/cppcache/include/geode/PoolFactory.hpp b/cppcache/include/geode/PoolFactory.hpp
index 4a7f416..195e28d 100644
--- a/cppcache/include/geode/PoolFactory.hpp
+++ b/cppcache/include/geode/PoolFactory.hpp
@@ -518,15 +518,15 @@
    * cache operation.
    * If setPRSingleHopEnabled is false the client can do an extra hop on servers
    * to go to the required partition for that cache operation.
-   * The setPRSingleHopEnabled setting avoids extra hops only for the following cache
-   * operations:<br>
+   * The setPRSingleHopEnabled setting avoids extra hops only for the following
+   * cache operations:<br>
    * 1. {@link Region#put(Object, Object)}<br>
    * 2. {@link Region#get(Object)}<br>
    * 3. {@link Region#destroy(Object)}<br>
    * If true, works best when {@link PoolFactory#setMaxConnections(int)} is set
    * to -1.
-   * @param enabled is a boolean indicating whether PR Single Hop optimization should be enabled or
-   * not.
+   * @param enabled is a boolean indicating whether PR Single Hop optimization
+   * should be enabled or not.
    * @return a reference to <code>this</code>
    */
   PoolFactory& setPRSingleHopEnabled(bool enabled);
diff --git a/cryptoimpl/SSLImpl.cpp b/cryptoimpl/SSLImpl.cpp
index 8616590..97d5b40 100644
--- a/cryptoimpl/SSLImpl.cpp
+++ b/cryptoimpl/SSLImpl.cpp
@@ -21,6 +21,10 @@
 
 #include <ace/Guard_T.h>
 
+#include <geode/ExceptionTypes.hpp>
+
+#include "../cppcache/src/util/exception.hpp"
+
 namespace apache {
 namespace geode {
 namespace client {
@@ -56,7 +60,9 @@
 
     SSL_CTX_set_cipher_list(sslctx->context(), "DEFAULT");
     sslctx->set_mode(ACE_SSL_Context::SSLv23_client);
-    sslctx->load_trusted_ca(pubkeyfile);
+    if (sslctx->load_trusted_ca(pubkeyfile) != 0) {
+      throw SslException("Failed to read SSL trust store.");
+    }
 
     if (strlen(password) > 0) {
       SSL_CTX_set_default_passwd_cb(sslctx->context(), pem_passwd_cb);
@@ -64,8 +70,16 @@
                                              const_cast<char *>(password));
     }
 
-    sslctx->private_key(privkeyfile);
-    sslctx->certificate(privkeyfile);
+    if (sslctx->private_key(privkeyfile) != 0) {
+      throw SslException("Invalid SSL keystore password.");
+    }
+    if (sslctx->certificate(privkeyfile) != 0) {
+      throw SslException("Failed to read SSL certificate.");
+    }
+    if (::SSL_CTX_use_certificate_chain_file(sslctx->context(), privkeyfile) <=
+        0) {
+      throw SslException("Failed to read SSL certificate chain.");
+    }
     SSLImpl::s_initialized = true;
   }
   m_io = new ACE_SSL_SOCK_Stream();