commit ef68f40: [Rework] Rework SSL caching
Vsevolod Stakhov
vsevolod at highsecure.ru
Tue Feb 18 13:21:07 UTC 2020
Author: Vsevolod Stakhov
Date: 2020-02-18 12:49:54 +0000
URL: https://github.com/rspamd/rspamd/commit/ef68f4073a524bd1552d63c365a78888ea6969e0
[Rework] Rework SSL caching
---
src/libserver/cfg_utils.c | 31 ++--------
src/libserver/ssl_util.c | 145 ++++++++++++++++++++++++++++++++++++----------
src/libserver/ssl_util.h | 2 +
3 files changed, 120 insertions(+), 58 deletions(-)
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c
index b74759229..bcebb9f93 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.c
@@ -2755,7 +2755,6 @@ gboolean
rspamd_config_libs (struct rspamd_external_libs_ctx *ctx,
struct rspamd_config *cfg)
{
- static const char secure_ciphers[] = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
size_t r;
gboolean ret = TRUE;
@@ -2830,30 +2829,8 @@ rspamd_config_libs (struct rspamd_external_libs_ctx *ctx,
#endif
}
- if (cfg->ssl_ca_path) {
- if (SSL_CTX_load_verify_locations (ctx->ssl_ctx, cfg->ssl_ca_path,
- NULL) != 1) {
- msg_err_config ("cannot load CA certs from %s: %s",
- cfg->ssl_ca_path,
- ERR_error_string (ERR_get_error (), NULL));
- }
- }
- else {
- msg_debug_config ("ssl_ca_path is not set, using default CA path");
- SSL_CTX_set_default_verify_paths (ctx->ssl_ctx);
- }
-
- if (cfg->ssl_ciphers) {
- if (SSL_CTX_set_cipher_list (ctx->ssl_ctx, cfg->ssl_ciphers) != 1) {
- msg_err_config (
- "cannot set ciphers set to %s: %s; fallback to %s",
- cfg->ssl_ciphers,
- ERR_error_string (ERR_get_error (), NULL),
- secure_ciphers);
- /* Default settings */
- SSL_CTX_set_cipher_list (ctx->ssl_ctx, secure_ciphers);
- }
- }
+ rspamd_ssl_ctx_config (cfg, ctx->ssl_ctx);
+ rspamd_ssl_ctx_config (cfg, ctx->ssl_ctx_noverify);
/* Init decompression */
ctx->in_zstream = ZSTD_createDStream ();
@@ -2942,8 +2919,8 @@ rspamd_deinit_libs (struct rspamd_external_libs_ctx *ctx)
#ifdef HAVE_OPENSSL
EVP_cleanup ();
ERR_free_strings ();
- SSL_CTX_free (ctx->ssl_ctx);
- SSL_CTX_free (ctx->ssl_ctx_noverify);
+ rspamd_ssl_ctx_free (ctx->ssl_ctx);
+ rspamd_ssl_ctx_free (ctx->ssl_ctx_noverify);
#endif
rspamd_inet_library_destroy ();
rspamd_free_zstd_dictionary (ctx->in_dict);
diff --git a/src/libserver/ssl_util.c b/src/libserver/ssl_util.c
index a094eaf45..5a1abdeef 100644
--- a/src/libserver/ssl_util.c
+++ b/src/libserver/ssl_util.c
@@ -16,7 +16,9 @@
#include "config.h"
#include "libutil/util.h"
+#include "libutil/hash.h"
#include "libserver/logger.h"
+#include "libserver/cfg_file.h"
#include "ssl_util.h"
#include "unix-std.h"
#include "cryptobox.h"
@@ -44,12 +46,18 @@ enum rspamd_ssl_shutdown {
ssl_shut_unclean,
};
+struct rspamd_ssl_ctx {
+ SSL_CTX *s;
+ rspamd_lru_hash_t *sessions;
+};
+
struct rspamd_ssl_connection {
gint fd;
enum rspamd_ssl_state state;
enum rspamd_ssl_shutdown shut;
gboolean verify_peer;
SSL *ssl;
+ struct rspamd_ssl_ctx *ssl_ctx;
gchar *hostname;
struct rspamd_io_ev *ev;
struct rspamd_io_ev *shut_ev;
@@ -419,6 +427,8 @@ rspamd_tls_set_error (gint retcode, const gchar *stage, GError **err)
static void
rspamd_ssl_connection_dtor (struct rspamd_ssl_connection *conn)
{
+ msg_debug_ssl ("closing SSL connection %p; %d sessions in the cache",
+ conn->ssl, rspamd_lru_hash_size (conn->ssl_ctx->sessions));
SSL_free (conn->ssl);
if (conn->hostname) {
@@ -618,23 +628,24 @@ struct rspamd_ssl_connection *
rspamd_ssl_connection_new (gpointer ssl_ctx, struct ev_loop *ev_base,
gboolean verify_peer, const gchar *log_tag)
{
- struct rspamd_ssl_connection *c;
+ struct rspamd_ssl_connection *conn;
+ struct rspamd_ssl_ctx *ctx = (struct rspamd_ssl_ctx *)ssl_ctx;
g_assert (ssl_ctx != NULL);
- c = g_malloc0 (sizeof (*c));
- c->ssl = SSL_new (ssl_ctx);
- c->event_loop = ev_base;
- c->verify_peer = verify_peer;
+ conn = g_malloc0 (sizeof (*conn));
+ conn->ssl_ctx = ctx;
+ conn->event_loop = ev_base;
+ conn->verify_peer = verify_peer;
if (log_tag) {
- rspamd_strlcpy (c->log_tag, log_tag, sizeof (log_tag));
+ rspamd_strlcpy (conn->log_tag, log_tag, sizeof (log_tag));
}
else {
- rspamd_random_hex (c->log_tag, sizeof (log_tag) - 1);
- c->log_tag[sizeof (log_tag) - 1] = '\0';
+ rspamd_random_hex (conn->log_tag, sizeof (log_tag) - 1);
+ conn->log_tag[sizeof (log_tag) - 1] = '\0';
}
- return c;
+ return conn;
}
@@ -648,6 +659,11 @@ rspamd_ssl_connect_fd (struct rspamd_ssl_connection *conn, gint fd,
g_assert (conn != NULL);
+ conn->ssl = SSL_new (conn->ssl_ctx->s);
+ SSL_set_app_data (conn->ssl, conn);
+ msg_debug_ssl ("new ssl connection %p; session reused=%s",
+ conn->ssl, SSL_session_reused (conn->ssl) ? "true" : "false");
+
if (conn->state != ssl_conn_reset) {
return FALSE;
}
@@ -927,18 +943,32 @@ rspamd_ssl_connection_free (struct rspamd_ssl_connection *conn)
}
}
-gpointer
-rspamd_init_ssl_ctx (void)
+static int
+rspamd_ssl_new_client_session (SSL *ssl, SSL_SESSION *sess)
{
+ struct rspamd_ssl_ctx *ctx;
+ struct rspamd_ssl_connection *conn;
+
+ conn = SSL_get_app_data (ssl);
+
+ msg_debug_ssl ("hui: got new session from %p", conn);
+
+ return 0;
+}
+
+static struct rspamd_ssl_ctx *
+rspamd_init_ssl_ctx_common (void)
+{
+ struct rspamd_ssl_ctx *ret;
SSL_CTX *ssl_ctx;
gint ssl_options;
+ static const guint client_cache_size = 1024;
rspamd_openssl_maybe_init ();
- ssl_ctx = SSL_CTX_new (SSLv23_method ());
- SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_PEER, NULL);
- SSL_CTX_set_verify_depth (ssl_ctx, 4);
+ ret = g_malloc0 (sizeof (*ret));
ssl_options = SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
+ ssl_ctx = SSL_CTX_new (SSLv23_method ());
#ifdef SSL_OP_NO_COMPRESSION
ssl_options |= SSL_OP_NO_COMPRESSION;
@@ -948,30 +978,42 @@ rspamd_init_ssl_ctx (void)
SSL_CTX_set_options (ssl_ctx, ssl_options);
- return ssl_ctx;
+#ifdef TLS1_3_VERSION
+ SSL_CTX_set_min_proto_version (ssl_ctx, 0);
+ SSL_CTX_set_max_proto_version (ssl_ctx, TLS1_3_VERSION);
+#endif
+
+#ifdef SSL_SESS_CACHE_CLIENT
+ SSL_CTX_set_session_cache_mode (ssl_ctx, SSL_SESS_CACHE_CLIENT
+ | SSL_SESS_CACHE_NO_INTERNAL_STORE);
+#endif
+
+ ret->s = ssl_ctx;
+ ret->sessions = rspamd_lru_hash_new_full (client_cache_size,
+ g_free, (GDestroyNotify)SSL_SESSION_free, rspamd_str_hash,
+ rspamd_str_equal);
+ SSL_CTX_set_app_data (ssl_ctx, ret);
+ SSL_CTX_sess_set_new_cb (ssl_ctx, rspamd_ssl_new_client_session);
+
+ return ret;
}
-gpointer rspamd_init_ssl_ctx_noverify (void)
+gpointer
+rspamd_init_ssl_ctx (void)
{
- SSL_CTX *ssl_ctx_noverify;
- gint ssl_options;
+ struct rspamd_ssl_ctx *ssl_ctx = rspamd_init_ssl_ctx_common ();
- rspamd_openssl_maybe_init ();
+ SSL_CTX_set_verify (ssl_ctx->s, SSL_VERIFY_PEER, NULL);
+ SSL_CTX_set_verify_depth (ssl_ctx->s, 4);
- ssl_options = SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
+ return ssl_ctx;
+}
-#ifdef SSL_OP_NO_COMPRESSION
- ssl_options |= SSL_OP_NO_COMPRESSION;
-#elif OPENSSL_VERSION_NUMBER >= 0x00908000L
- sk_SSL_COMP_zero (SSL_COMP_get_compression_methods ());
-#endif
+gpointer rspamd_init_ssl_ctx_noverify (void)
+{
+ struct rspamd_ssl_ctx *ssl_ctx_noverify = rspamd_init_ssl_ctx_common ();
- ssl_ctx_noverify = SSL_CTX_new (SSLv23_method ());
- SSL_CTX_set_verify (ssl_ctx_noverify, SSL_VERIFY_NONE, NULL);
- SSL_CTX_set_options (ssl_ctx_noverify, ssl_options);
-#ifdef SSL_SESS_CACHE_BOTH
- SSL_CTX_set_session_cache_mode (ssl_ctx_noverify, SSL_SESS_CACHE_BOTH);
-#endif
+ SSL_CTX_set_verify (ssl_ctx_noverify->s, SSL_VERIFY_NONE, NULL);
return ssl_ctx_noverify;
}
@@ -1012,4 +1054,45 @@ rspamd_openssl_maybe_init (void)
openssl_initialized = TRUE;
}
+}
+
+void
+rspamd_ssl_ctx_config (struct rspamd_config *cfg, gpointer ssl_ctx)
+{
+ struct rspamd_ssl_ctx *ctx = (struct rspamd_ssl_ctx *)ssl_ctx;
+ static const char default_secure_ciphers[] = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
+
+ if (cfg->ssl_ca_path) {
+ if (SSL_CTX_load_verify_locations (ctx->s, cfg->ssl_ca_path,
+ NULL) != 1) {
+ msg_err_config ("cannot load CA certs from %s: %s",
+ cfg->ssl_ca_path,
+ ERR_error_string (ERR_get_error (), NULL));
+ }
+ }
+ else {
+ msg_debug_config ("ssl_ca_path is not set, using default CA path");
+ SSL_CTX_set_default_verify_paths (ctx->s);
+ }
+
+ if (cfg->ssl_ciphers) {
+ if (SSL_CTX_set_cipher_list (ctx->s, cfg->ssl_ciphers) != 1) {
+ msg_err_config (
+ "cannot set ciphers set to %s: %s; fallback to %s",
+ cfg->ssl_ciphers,
+ ERR_error_string (ERR_get_error (), NULL),
+ default_secure_ciphers);
+ /* Default settings */
+ SSL_CTX_set_cipher_list (ctx->s, default_secure_ciphers);
+ }
+ }
+}
+
+void
+rspamd_ssl_ctx_free (gpointer ssl_ctx)
+{
+ struct rspamd_ssl_ctx *ctx = (struct rspamd_ssl_ctx *)ssl_ctx;
+
+ rspamd_lru_hash_destroy (ctx->sessions);
+ SSL_CTX_free (ctx->s);
}
\ No newline at end of file
diff --git a/src/libserver/ssl_util.h b/src/libserver/ssl_util.h
index 9118c3e8c..f3593387f 100644
--- a/src/libserver/ssl_util.h
+++ b/src/libserver/ssl_util.h
@@ -96,6 +96,8 @@ void rspamd_ssl_connection_free (struct rspamd_ssl_connection *conn);
gpointer rspamd_init_ssl_ctx (void);
gpointer rspamd_init_ssl_ctx_noverify (void);
+void rspamd_ssl_ctx_config (struct rspamd_config *cfg, gpointer ssl_ctx);
+void rspamd_ssl_ctx_free (gpointer ssl_ctx);
void rspamd_openssl_maybe_init (void);
#ifdef __cplusplus
More information about the Commits
mailing list