Browse Source

[Rework] Rework SSL caching

tags/2.4
Vsevolod Stakhov 4 years ago
parent
commit
ef68f4073a
3 changed files with 120 additions and 58 deletions
  1. 4
    27
      src/libserver/cfg_utils.c
  2. 114
    31
      src/libserver/ssl_util.c
  3. 2
    0
      src/libserver/ssl_util.h

+ 4
- 27
src/libserver/cfg_utils.c View File

@@ -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);

+ 114
- 31
src/libserver/ssl_util.c View File

@@ -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);
}

+ 2
- 0
src/libserver/ssl_util.h View File

@@ -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

Loading…
Cancel
Save