From ccf2cbc6d00b0e8a2f63be214b6ccf121aa77c99 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 24 Dec 2015 09:49:32 +0000 Subject: Use refcounting logic for dkim keys to avoid some races --- src/libserver/dkim.c | 28 +++++++++++++++++++--------- src/libserver/dkim.h | 5 +++-- 2 files changed, 22 insertions(+), 11 deletions(-) (limited to 'src/libserver') diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c index 3b8fc63b5..d1542c1a0 100644 --- a/src/libserver/dkim.c +++ b/src/libserver/dkim.c @@ -840,6 +840,7 @@ rspamd_dkim_make_key (rspamd_dkim_context_t *ctx, const gchar *keydata, msg_err_dkim ("DKIM key is too short to be valid"); return NULL; } + key = g_slice_alloc0 (sizeof (rspamd_dkim_key_t)); key->keydata = g_slice_alloc (keylen + 1); rspamd_strlcpy (key->keydata, keydata, keylen + 1); @@ -855,6 +856,8 @@ rspamd_dkim_make_key (rspamd_dkim_context_t *ctx, const gchar *keydata, #else g_base64_decode_inplace (key->keydata, &key->decoded_len); #endif + REF_INIT_RETAIN (key, rspamd_dkim_key_free); + #ifdef HAVE_OPENSSL key->key_bio = BIO_new_mem_buf (key->keydata, key->decoded_len); if (key->key_bio == NULL) { @@ -862,7 +865,8 @@ rspamd_dkim_make_key (rspamd_dkim_context_t *ctx, const gchar *keydata, DKIM_ERROR, DKIM_SIGERROR_KEYFAIL, "cannot make ssl bio from key"); - rspamd_dkim_key_free (key); + REF_RELEASE (key); + return NULL; } @@ -872,7 +876,8 @@ rspamd_dkim_make_key (rspamd_dkim_context_t *ctx, const gchar *keydata, DKIM_ERROR, DKIM_SIGERROR_KEYFAIL, "cannot extract pubkey from bio"); - rspamd_dkim_key_free (key); + REF_RELEASE (key); + return NULL; } @@ -882,10 +887,10 @@ rspamd_dkim_make_key (rspamd_dkim_context_t *ctx, const gchar *keydata, DKIM_ERROR, DKIM_SIGERROR_KEYFAIL, "cannot extract rsa key from evp key"); - rspamd_dkim_key_free (key); + REF_RELEASE (key); + return NULL; } - #endif return key; @@ -899,12 +904,12 @@ void rspamd_dkim_key_free (rspamd_dkim_key_t *key) { #ifdef HAVE_OPENSSL - if (key->key_rsa) { - RSA_free (key->key_rsa); - } if (key->key_evp) { EVP_PKEY_free (key->key_evp); } + if (key->key_rsa) { + RSA_free (key->key_rsa); + } if (key->key_bio) { BIO_free (key->key_bio); } @@ -914,8 +919,8 @@ rspamd_dkim_key_free (rspamd_dkim_key_t *key) } static rspamd_dkim_key_t * -rspamd_dkim_parse_key (rspamd_dkim_context_t *ctx, const gchar *txt, gsize -*keylen, GError **err) +rspamd_dkim_parse_key (rspamd_dkim_context_t *ctx, const gchar *txt, + gsize *keylen, GError **err) { const gchar *c, *p, *end; gint state = 0; @@ -943,6 +948,11 @@ rspamd_dkim_parse_key (rspamd_dkim_context_t *ctx, const gchar *txt, gsize /* State when we got p= and looking for some public key */ if ((*p == ';' || p == end) && p > c) { len = p - c; + + if (keylen) { + *keylen = len; + } + return rspamd_dkim_make_key (ctx, c, len, err); } else { diff --git a/src/libserver/dkim.h b/src/libserver/dkim.h index 97f54b912..59735aefe 100644 --- a/src/libserver/dkim.h +++ b/src/libserver/dkim.h @@ -28,6 +28,7 @@ #include "config.h" #include "event.h" #include "dns.h" +#include "ref.h" #ifdef HAVE_OPENSSL #include #include @@ -162,8 +163,8 @@ typedef struct rspamd_dkim_key_s { BIO *key_bio; EVP_PKEY *key_evp; #endif -} -rspamd_dkim_key_t; + ref_entry_t ref; +} rspamd_dkim_key_t; struct rspamd_task; -- cgit v1.2.3