diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-02-18 12:49:54 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-02-18 12:49:54 +0000 |
commit | ef68f4073a524bd1552d63c365a78888ea6969e0 (patch) | |
tree | 8cd365d627151ceeeb343755eb790858ac4933bd /src | |
parent | 3fbf6a9439347238c7e9713686aa811d42e2a7e4 (diff) | |
download | rspamd-ef68f4073a524bd1552d63c365a78888ea6969e0.tar.gz rspamd-ef68f4073a524bd1552d63c365a78888ea6969e0.zip |
[Rework] Rework SSL caching
Diffstat (limited to 'src')
-rw-r--r-- | src/libserver/cfg_utils.c | 31 | ||||
-rw-r--r-- | src/libserver/ssl_util.c | 145 | ||||
-rw-r--r-- | 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 |