Expose OpenSSL initialization functions
Otherwise, commit is a logical no-op; it keeps the same OpenSSL
initialization behavior as before. Move the SSL initialization
functionality to one place to make it easier to track.
Signed-off-by: Alan Dunn <amdunn@gmail.com>
Signed-off-by: Roger Meier <roger@apache.org>
diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
index 9a8c758..4b36f8c 100644
--- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
@@ -49,6 +49,87 @@
namespace apache { namespace thrift { namespace transport {
+// OpenSSL initialization/cleanup
+
+static bool openSSLInitialized = false;
+static boost::shared_array<Mutex> mutexes;
+
+static void callbackLocking(int mode, int n, const char*, int) {
+ if (mode & CRYPTO_LOCK) {
+ mutexes[n].lock();
+ } else {
+ mutexes[n].unlock();
+ }
+}
+
+#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID)
+static unsigned long callbackThreadID() {
+ return (unsigned long) pthread_self();
+}
+#endif
+
+static CRYPTO_dynlock_value* dyn_create(const char*, int) {
+ return new CRYPTO_dynlock_value;
+}
+
+static void dyn_lock(int mode,
+ struct CRYPTO_dynlock_value* lock,
+ const char*, int) {
+ if (lock != NULL) {
+ if (mode & CRYPTO_LOCK) {
+ lock->mutex.lock();
+ } else {
+ lock->mutex.unlock();
+ }
+ }
+}
+
+static void dyn_destroy(struct CRYPTO_dynlock_value* lock, const char*, int) {
+ delete lock;
+}
+
+void initializeOpenSSL() {
+ if (openSSLInitialized) {
+ return;
+ }
+ openSSLInitialized = true;
+ SSL_library_init();
+ SSL_load_error_strings();
+ // static locking
+ mutexes = boost::shared_array<Mutex>(new Mutex[::CRYPTO_num_locks()]);
+ if (mutexes == NULL) {
+ throw TTransportException(TTransportException::INTERNAL_ERROR,
+ "initializeOpenSSL() failed, "
+ "out of memory while creating mutex array");
+ }
+#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID)
+ CRYPTO_set_id_callback(callbackThreadID);
+#endif
+ CRYPTO_set_locking_callback(callbackLocking);
+ // dynamic locking
+ CRYPTO_set_dynlock_create_callback(dyn_create);
+ CRYPTO_set_dynlock_lock_callback(dyn_lock);
+ CRYPTO_set_dynlock_destroy_callback(dyn_destroy);
+}
+
+void cleanupOpenSSL() {
+ if (!openSSLInitialized) {
+ return;
+ }
+ openSSLInitialized = false;
+#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID)
+ CRYPTO_set_id_callback(NULL);
+#endif
+ CRYPTO_set_locking_callback(NULL);
+ CRYPTO_set_dynlock_create_callback(NULL);
+ CRYPTO_set_dynlock_lock_callback(NULL);
+ CRYPTO_set_dynlock_destroy_callback(NULL);
+ CRYPTO_cleanup_all_ex_data();
+ ERR_free_strings();
+ EVP_cleanup();
+ ERR_remove_state(0);
+ mutexes.reset();
+}
static void buildErrors(string& message, int error = 0);
static bool matchName(const char* host, const char* pattern, int size);
@@ -377,7 +458,6 @@
}
// TSSLSocketFactory implementation
-bool TSSLSocketFactory::initialized = false;
uint64_t TSSLSocketFactory::count_ = 0;
Mutex TSSLSocketFactory::mutex_;
@@ -520,85 +600,6 @@
return length;
}
-static boost::shared_array<Mutex> mutexes;
-
-static void callbackLocking(int mode, int n, const char*, int) {
- if (mode & CRYPTO_LOCK) {
- mutexes[n].lock();
- } else {
- mutexes[n].unlock();
- }
-}
-
-#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID)
-static unsigned long callbackThreadID() {
- return (unsigned long) pthread_self();
-}
-#endif
-
-static CRYPTO_dynlock_value* dyn_create(const char*, int) {
- return new CRYPTO_dynlock_value;
-}
-
-static void dyn_lock(int mode,
- struct CRYPTO_dynlock_value* lock,
- const char*, int) {
- if (lock != NULL) {
- if (mode & CRYPTO_LOCK) {
- lock->mutex.lock();
- } else {
- lock->mutex.unlock();
- }
- }
-}
-
-static void dyn_destroy(struct CRYPTO_dynlock_value* lock, const char*, int) {
- delete lock;
-}
-
-void TSSLSocketFactory::initializeOpenSSL() {
- if (initialized) {
- return;
- }
- initialized = true;
- SSL_library_init();
- SSL_load_error_strings();
- // static locking
- mutexes = boost::shared_array<Mutex>(new Mutex[::CRYPTO_num_locks()]);
- if (mutexes == NULL) {
- throw TTransportException(TTransportException::INTERNAL_ERROR,
- "initializeOpenSSL() failed, "
- "out of memory while creating mutex array");
- }
-#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID)
- CRYPTO_set_id_callback(callbackThreadID);
-#endif
- CRYPTO_set_locking_callback(callbackLocking);
- // dynamic locking
- CRYPTO_set_dynlock_create_callback(dyn_create);
- CRYPTO_set_dynlock_lock_callback(dyn_lock);
- CRYPTO_set_dynlock_destroy_callback(dyn_destroy);
-}
-
-void TSSLSocketFactory::cleanupOpenSSL() {
- if (!initialized) {
- return;
- }
- initialized = false;
-#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID)
- CRYPTO_set_id_callback(NULL);
-#endif
- CRYPTO_set_locking_callback(NULL);
- CRYPTO_set_dynlock_create_callback(NULL);
- CRYPTO_set_dynlock_lock_callback(NULL);
- CRYPTO_set_dynlock_destroy_callback(NULL);
- CRYPTO_cleanup_all_ex_data();
- ERR_free_strings();
- EVP_cleanup();
- ERR_remove_state(0);
- mutexes.reset();
-}
-
// extract error messages from error queue
void buildErrors(string& errors, int errno_copy) {
unsigned long errorCode;
diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h
index 7c19206..eca9591 100644
--- a/lib/cpp/src/thrift/transport/TSSLSocket.h
+++ b/lib/cpp/src/thrift/transport/TSSLSocket.h
@@ -42,6 +42,21 @@
/**
+ * Initialize OpenSSL library. This function, or some other
+ * equivalent function to initialize OpenSSL, must be called before
+ * TSSLSocket is used. Currently TSSLSocketFactory automatically
+ * calls this function, so you should not.
+ */
+void initializeOpenSSL();
+/**
+ * Cleanup OpenSSL library. This function should be called to clean
+ * up OpenSSL after use of OpenSSL functionality is finished.
+ * Currently TSSLSocketFactory automatically calls this function, so
+ * you should not.
+ */
+void cleanupOpenSSL();
+
+/**
* OpenSSL implementation for SSL socket interface.
*/
class TSSLSocket: public TSocket {
@@ -204,8 +219,6 @@
protected:
boost::shared_ptr<SSLContext> ctx_;
- static void initializeOpenSSL();
- static void cleanupOpenSSL();
/**
* Override this method for custom password callback. It may be called
* multiple times at any time during a session as necessary.
@@ -217,7 +230,6 @@
private:
bool server_;
boost::shared_ptr<AccessManager> access_;
- static bool initialized;
static concurrency::Mutex mutex_;
static uint64_t count_;
void setup(boost::shared_ptr<TSSLSocket> ssl);