session CHANGE init/destroy functions reworked
Now, if the user calls them the way one should,
there will be no memory left on application exit.
Quite an achievement...
diff --git a/src/netconf.h b/src/netconf.h
index 25fb9cb..338c5d6 100644
--- a/src/netconf.h
+++ b/src/netconf.h
@@ -113,20 +113,58 @@
NC_PARAMTYPE_DUP_AND_FREE /**< make a copy of the argument, free afterwards */
} NC_PARAMTYPE;
+#if defined(ENABLE_SSH) || defined(ENABLE_TLS)
+
+/**
+ * @brief Free all the dynamically allocated thread-specific libssl/libcrypto
+ * resources.
+ *
+ * This function should be called only if any of #nc_ssh_init(), #nc_tls_init(),
+ * or #nc_ssh_tls_init() was called. Call it in every thread your application
+ * creates just before the thread exits. In the last thread (usually the main one)
+ * call only #nc_ssh_destroy(), #nc_ssh_tls_destroy(), or #nc_tls_destroy,
+ * depending on what you used for initialization.
+ */
+void nc_thread_destroy(void);
+
+#endif /* ENABLE_SSH || ENABLE_TLS */
+
+#if defined(ENABLE_SSH) && defined(ENABLE_TLS)
+
+/**
+ * @brief Initialize both libssh and libssl/libcrypto libraries for thread-safe usage.
+ * Call this function even if you, for instance, will use only SSH transport,
+ * but want to use some libssl/libcrypto functions in your application.
+ *
+ * Must be called before calling any libnetconf2 SSH and/or TLS function.
+ */
+void nc_ssh_tls_init(void);
+
+/**
+ * @brief Free all the dynamically allocated libssh and libssl/libcrypto resources.
+ *
+ * No libnetconf2 SSH/TLS, libssh, and libcrypto/libssl function should be
+ * called afterwards.
+ */
+void nc_ssh_tls_destroy(void);
+
+#endif /* ENABLE_SSH && ENABLE_TLS */
+
#ifdef ENABLE_SSH
/**
- * @brief Initialize libssh so that libnetconf2 can be safely used in a multi-threaded environment.
+ * @brief Initialize libssh for thread-safe usage. If you plan to use libcrypto/
+ * /libssl in your application as well, please call #nc_ssh_tls_init()
+ * instead.
*
- * Must be called before using any other SSH functions. Afterwards can libssh be used in the application
- * as well.
+ * Must be called before calling any libnetconf2 SSH function.
*/
void nc_ssh_init(void);
/**
- * @brief Free all the resources allocated by libssh.
+ * @brief Free all the dynamically allocated libssh resources.
*
- * Must be called before #nc_tls_destroy() (if called) as libssh uses libcrypto as well.
+ * No libnetconf2 SSH and libssh function should be called afterwards.
*/
void nc_ssh_destroy(void);
@@ -135,15 +173,17 @@
#ifdef ENABLE_TLS
/**
- * @brief Initialize libcrypto so that libnetconf2 can be safely used in a multi-threaded environment.
+ * @brief Initialize libssl/libcrypto for thread-safe usage. If you plan to use libssh
+ * in your application as well, please call #nc_ssh_tls_init() instead.
*
- * Must be called before using any other TLS functions. Afterwards can libcrypto be used in the application
- * as well.
+ * Must be called before calling any libnetconf2 TLS function.
*/
void nc_tls_init(void);
/**
- * @brief Free all the resources allocated by libcrypto and libssl.
+ * @brief Free all the dynamically allocated libssl/libcrypto resources.
+ *
+ * No libnetconf2 TLS and libssl/libcrypto function should be called afterwards.
*/
void nc_tls_destroy(void);
diff --git a/src/session.c b/src/session.c
index 21abf8b..090c7fc 100644
--- a/src/session.c
+++ b/src/session.c
@@ -27,6 +27,7 @@
#include <time.h>
#include <libyang/libyang.h>
+#include "session.h"
#include "libnetconf.h"
#include "session_server.h"
@@ -36,11 +37,13 @@
#endif /* ENABLE_SSH */
-#ifdef ENABLE_TLS
+#if defined(ENABLE_SSH) || defined(ENABLE_TLS)
+# include <openssl/engine.h>
+# include <openssl/conf.h>
# include <openssl/err.h>
-#endif /* ENABLE_TLS */
+#endif /* ENABLE_SSH || ENABLE_TLS */
/* in seconds */
#define NC_CLIENT_HELLO_TIMEOUT 60
@@ -916,6 +919,9 @@
API void
nc_ssh_destroy(void)
{
+ ENGINE_cleanup();
+ CONF_modules_unload(1);
+ ERR_remove_state(0);
ssh_finalize();
}
@@ -1005,14 +1011,12 @@
nc_tls_destroy(void)
{
int i;
- CRYPTO_THREADID crypto_tid;
- EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
+ ERR_remove_state(0);
+ EVP_cleanup();
ERR_free_strings();
sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
- CRYPTO_THREADID_current(&crypto_tid);
- ERR_remove_thread_state(&crypto_tid);
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
@@ -1027,3 +1031,48 @@
}
#endif /* ENABLE_TLS */
+
+#if defined(ENABLE_SSH) || defined(ENABLE_TLS)
+
+API void
+nc_thread_destroy(void) {
+ CRYPTO_THREADID crypto_tid;
+
+ CRYPTO_cleanup_all_ex_data();
+
+ CRYPTO_THREADID_current(&crypto_tid);
+ ERR_remove_thread_state(&crypto_tid);
+}
+
+#endif /* ENABLE_SSH || ENABLE_TLS */
+
+#if defined(ENABLE_SSH) && defined(ENABLE_TLS)
+
+API void
+nc_ssh_tls_init(void)
+{
+ SSL_load_error_strings();
+ ERR_load_BIO_strings();
+ SSL_library_init();
+
+ nc_ssh_init();
+
+ CRYPTO_set_dynlock_create_callback(tls_dyn_create_func);
+ CRYPTO_set_dynlock_lock_callback(tls_dyn_lock_func);
+ CRYPTO_set_dynlock_destroy_callback(tls_dyn_destroy_func);
+}
+
+API void
+nc_ssh_tls_destroy(void)
+{
+ ERR_free_strings();
+ sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
+
+ nc_ssh_destroy();
+
+ CRYPTO_set_dynlock_create_callback(NULL);
+ CRYPTO_set_dynlock_lock_callback(NULL);
+ CRYPTO_set_dynlock_destroy_callback(NULL);
+}
+
+#endif /* ENABLE_SSH && ENABLE_TLS */