aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rspamd.com>2024-09-05 16:20:46 +0600
committerGitHub <noreply@github.com>2024-09-05 16:20:46 +0600
commit737a2ce03b826f86851d021d628274ab8c8ea7fb (patch)
tree7918e548808c5981fab465726f545a5c6cc9fe49 /src
parentdd47f82a317ad2ed9a9270c9779bf866ff5989fd (diff)
parent40a6ddd69be80e6a4ad8a29053bbfa18d24b3bd8 (diff)
downloadrspamd-737a2ce03b826f86851d021d628274ab8c8ea7fb.tar.gz
rspamd-737a2ce03b826f86851d021d628274ab8c8ea7fb.zip
Merge branch 'master' into vstakhov-utf8-mime
Diffstat (limited to 'src')
-rw-r--r--src/client/rspamc.cxx17
-rw-r--r--src/client/rspamdclient.c6
-rw-r--r--src/controller.c10
-rw-r--r--src/fuzzy_storage.c13
-rw-r--r--src/libcryptobox/cryptobox.c999
-rw-r--r--src/libcryptobox/cryptobox.h405
-rw-r--r--src/libcryptobox/keypair.c276
-rw-r--r--src/libcryptobox/keypair.h31
-rw-r--r--src/libcryptobox/keypair_private.h46
-rw-r--r--src/libcryptobox/keypairs_cache.c27
-rw-r--r--src/libmime/lang_detection.c2
-rw-r--r--src/libmime/scan_result.c48
-rw-r--r--src/libserver/cfg_file.h1
-rw-r--r--src/libserver/cfg_rcl.cxx44
-rw-r--r--src/libserver/cfg_rcl.h3
-rw-r--r--src/libserver/cfg_utils.cxx2
-rw-r--r--src/libserver/dkim.c263
-rw-r--r--src/libserver/http/http_connection.c331
-rw-r--r--src/libserver/http/http_context.c3
-rw-r--r--src/libserver/logger/logger.c20
-rw-r--r--src/libserver/maps/map.c13
-rw-r--r--src/libserver/milter.c8
-rw-r--r--src/libserver/protocol.c19
-rw-r--r--src/libserver/protocol_internal.h1
-rw-r--r--src/libserver/spf.c5
-rw-r--r--src/libserver/spf.h2
-rw-r--r--src/libserver/symcache/symcache_runtime.cxx43
-rw-r--r--src/libserver/symcache/symcache_runtime.hxx7
-rw-r--r--src/libstat/stat_process.c20
-rw-r--r--src/lua/lua_config.c854
-rw-r--r--src/lua/lua_cryptobox.c154
-rw-r--r--src/lua/lua_http.c5
-rw-r--r--src/lua/lua_map.c3
-rw-r--r--src/lua/lua_redis.c23
-rw-r--r--src/lua/lua_rsa.c164
-rw-r--r--src/lua/lua_spf.c7
-rw-r--r--src/lua/lua_task.c1
-rw-r--r--src/plugins/fuzzy_check.c14
-rw-r--r--src/plugins/lua/arc.lua12
-rw-r--r--src/plugins/lua/gpt.lua41
-rw-r--r--src/plugins/lua/history_redis.lua4
-rw-r--r--src/plugins/lua/known_senders.lua3
-rw-r--r--src/plugins/lua/once_received.lua103
-rw-r--r--src/plugins/lua/spf.lua3
-rw-r--r--src/rspamadm/configdump.c5
-rw-r--r--src/rspamadm/signtool.c37
-rw-r--r--src/rspamd_proxy.c14
47 files changed, 1632 insertions, 2480 deletions
diff --git a/src/client/rspamc.cxx b/src/client/rspamc.cxx
index 1e0830493..1c67e4167 100644
--- a/src/client/rspamc.cxx
+++ b/src/client/rspamc.cxx
@@ -524,16 +524,13 @@ rspamc_password_callback(const char *option_name,
else {
/* Strip trailing spaces */
auto *map = (char *) locked_mmap.value().get_map();
- auto *end = map + locked_mmap.value().get_size() - 1;
-
- while (g_ascii_isspace(*end) && end > map) {
- end--;
- }
-
- end++;
- value_view = std::string_view{map, static_cast<std::size_t>(end - map + 1)};
- processed_passwd.assign(std::begin(value_view), std::end(value_view));
- processed_passwd.push_back('\0');
+ value_view = std::string_view{map, locked_mmap->get_size()};
+ auto right = value_view.end() - 1;
+ for (; right > value_view.cbegin() && g_ascii_isspace(*right); --right)
+ ;
+ std::string_view str{value_view.begin(), static_cast<size_t>(right - value_view.begin()) + 1};
+ processed_passwd.assign(std::begin(str), std::end(str));
+ processed_passwd.push_back('\0'); /* Null-terminate for C part */
}
}
else {
diff --git a/src/client/rspamdclient.c b/src/client/rspamdclient.c
index 2b8d0e9bb..bcb3cf67c 100644
--- a/src/client/rspamdclient.c
+++ b/src/client/rspamdclient.c
@@ -302,12 +302,10 @@ rspamd_client_init(struct rspamd_http_context *http_ctx,
conn->timeout = timeout;
if (key) {
- conn->key = rspamd_pubkey_from_base32(key, 0, RSPAMD_KEYPAIR_KEX,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ conn->key = rspamd_pubkey_from_base32(key, 0, RSPAMD_KEYPAIR_KEX);
if (conn->key) {
- conn->keypair = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ conn->keypair = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX);
rspamd_http_connection_set_key(conn->http_conn, conn->keypair);
}
else {
diff --git a/src/controller.c b/src/controller.c
index d91f99098..386448f93 100644
--- a/src/controller.c
+++ b/src/controller.c
@@ -1945,7 +1945,7 @@ rspamd_controller_learn_fin_task(void *ud)
if (task->err != NULL) {
msg_info_session("cannot learn <%s>: %e",
- MESSAGE_FIELD(task, message_id), task->err);
+ MESSAGE_FIELD_CHECK(task, message_id), task->err);
rspamd_controller_send_error(conn_ent, task->err->code, "%s",
task->err->message);
@@ -1957,14 +1957,14 @@ rspamd_controller_learn_fin_task(void *ud)
msg_info_task("<%s> learned message as %s: %s",
rspamd_inet_address_to_string(session->from_addr),
session->is_spam ? "spam" : "ham",
- MESSAGE_FIELD(task, message_id));
+ MESSAGE_FIELD_CHECK(task, message_id));
rspamd_controller_send_string(conn_ent, "{\"success\":true}");
return TRUE;
}
if (!rspamd_task_process(task, RSPAMD_TASK_PROCESS_LEARN)) {
msg_info_task("cannot learn <%s>: %e",
- MESSAGE_FIELD(task, message_id), task->err);
+ MESSAGE_FIELD_CHECK(task, message_id), task->err);
if (task->err) {
rspamd_controller_send_error(conn_ent, task->err->code, "%s",
@@ -1985,7 +1985,7 @@ rspamd_controller_learn_fin_task(void *ud)
msg_info_task("<%s> learned message as %s: %s",
rspamd_inet_address_to_string(session->from_addr),
session->is_spam ? "spam" : "ham",
- MESSAGE_FIELD(task, message_id));
+ MESSAGE_FIELD_CHECK(task, message_id));
rspamd_controller_send_string(conn_ent, "{\"success\":true}");
}
@@ -2114,7 +2114,7 @@ rspamd_controller_handle_learn_common(
if (!rspamd_task_process(task, RSPAMD_TASK_PROCESS_LEARN)) {
msg_warn_session("<%s> message cannot be processed",
- MESSAGE_FIELD(task, message_id));
+ MESSAGE_FIELD_CHECK(task, message_id));
goto end;
}
diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c
index 445289511..5fd3303dc 100644
--- a/src/fuzzy_storage.c
+++ b/src/fuzzy_storage.c
@@ -1088,8 +1088,7 @@ rspamd_fuzzy_make_reply(struct rspamd_fuzzy_cmd *cmd,
len,
session->reply.hdr.nonce,
session->nm,
- session->reply.hdr.mac,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ session->reply.hdr.mac);
}
else if (default_disabled) {
/* Hash is from a forbidden flag by default, and there is no encryption override */
@@ -1668,8 +1667,7 @@ rspamd_fuzzy_decrypt_command(struct fuzzy_session *s, unsigned char *buf, gsize
}
/* Now process the remote pubkey */
- rk = rspamd_pubkey_from_bin(hdr.pubkey, sizeof(hdr.pubkey),
- RSPAMD_KEYPAIR_KEX, RSPAMD_CRYPTOBOX_MODE_25519);
+ rk = rspamd_pubkey_from_bin(hdr.pubkey, sizeof(hdr.pubkey), RSPAMD_KEYPAIR_KEX);
if (rk == NULL) {
msg_err("bad key; ip=%s",
@@ -1683,7 +1681,7 @@ rspamd_fuzzy_decrypt_command(struct fuzzy_session *s, unsigned char *buf, gsize
/* Now decrypt request */
if (!rspamd_cryptobox_decrypt_nm_inplace(buf, buflen, hdr.nonce,
rspamd_pubkey_get_nm(rk, key->key),
- hdr.mac, RSPAMD_CRYPTOBOX_MODE_25519)) {
+ hdr.mac)) {
msg_err("decryption failed; ip=%s",
rspamd_inet_address_to_string(s->addr));
rspamd_pubkey_unref(rk);
@@ -2771,8 +2769,7 @@ fuzzy_add_keypair_from_ucl(const ucl_object_t *obj, khash_t(rspamd_fuzzy_keys_ha
return NULL;
}
- if (rspamd_keypair_alg(kp) != RSPAMD_CRYPTOBOX_MODE_25519 ||
- rspamd_keypair_type(kp) != RSPAMD_KEYPAIR_KEX) {
+ if (rspamd_keypair_type(kp) != RSPAMD_KEYPAIR_KEX) {
return FALSE;
}
@@ -2837,7 +2834,7 @@ fuzzy_add_keypair_from_ucl(const ucl_object_t *obj, khash_t(rspamd_fuzzy_keys_ha
}
}
- msg_debug("loaded keypair %*bs", rspamd_cryptobox_pk_bytes(RSPAMD_CRYPTOBOX_MODE_25519), pk);
+ msg_debug("loaded keypair %*bs", crypto_box_publickeybytes(), pk);
return key;
}
diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c
index aa093d01e..eeeed020c 100644
--- a/src/libcryptobox/cryptobox.c
+++ b/src/libcryptobox/cryptobox.c
@@ -38,19 +38,8 @@
#endif
#ifdef HAVE_OPENSSL
#include <openssl/opensslv.h>
-/* Openssl >= 1.0.1d is required for GCM verification */
-#if OPENSSL_VERSION_NUMBER >= 0x1000104fL
-#define HAVE_USABLE_OPENSSL 1
-#endif
-#endif
-
-#ifdef HAVE_USABLE_OPENSSL
#include <openssl/evp.h>
-#include <openssl/ec.h>
-#include <openssl/ecdh.h>
-#include <openssl/ecdsa.h>
-#include <openssl/rand.h>
-#define CRYPTOBOX_CURVE_NID NID_X9_62_prime256v1
+#include <openssl/rsa.h>
#endif
#include <signal.h>
@@ -324,759 +313,327 @@ void rspamd_cryptobox_deinit(struct rspamd_cryptobox_library_ctx *ctx)
}
}
-void rspamd_cryptobox_keypair(rspamd_pk_t pk, rspamd_sk_t sk,
- enum rspamd_cryptobox_mode mode)
+void rspamd_cryptobox_keypair(rspamd_pk_t pk, rspamd_sk_t sk)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- ottery_rand_bytes(sk, rspamd_cryptobox_MAX_SKBYTES);
- sk[0] &= 248;
- sk[31] &= 127;
- sk[31] |= 64;
-
- crypto_scalarmult_base(pk, sk);
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EC_KEY *ec_sec;
- const BIGNUM *bn_sec;
-
- const EC_POINT *ec_pub;
- gsize len;
-
- ec_sec = EC_KEY_new_by_curve_name(CRYPTOBOX_CURVE_NID);
- g_assert(ec_sec != NULL);
- g_assert(EC_KEY_generate_key(ec_sec) != 0);
-
- bn_sec = EC_KEY_get0_private_key(ec_sec);
- g_assert(bn_sec != NULL);
- ec_pub = EC_KEY_get0_public_key(ec_sec);
- g_assert(ec_pub != NULL);
-#if OPENSSL_VERSION_MAJOR >= 3
- unsigned char *buf = NULL; /* Thanks openssl for this API (no) */
- len = EC_POINT_point2buf(EC_KEY_get0_group(ec_sec), ec_pub,
- POINT_CONVERSION_UNCOMPRESSED, &buf, NULL);
- g_assert(len <= (int) rspamd_cryptobox_pk_bytes(mode));
- memcpy(pk, buf, len);
- OPENSSL_free(buf);
-#else
- BIGNUM *bn_pub;
- bn_pub = EC_POINT_point2bn(EC_KEY_get0_group(ec_sec),
- ec_pub, POINT_CONVERSION_UNCOMPRESSED, NULL, NULL);
- len = BN_num_bytes(bn_pub);
- g_assert(len <= (int) rspamd_cryptobox_pk_bytes(mode));
- BN_bn2bin(bn_pub, pk);
- BN_free(bn_pub);
-#endif
+ ottery_rand_bytes(sk, rspamd_cryptobox_MAX_SKBYTES);
+ sk[0] &= 248;
+ sk[31] &= 127;
+ sk[31] |= 64;
- len = BN_num_bytes(bn_sec);
- g_assert(len <= (int) sizeof(rspamd_sk_t));
- BN_bn2bin(bn_sec, sk);
+ crypto_scalarmult_base(pk, sk);
+}
- EC_KEY_free(ec_sec);
-#endif
- }
+void rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk, rspamd_sig_sk_t sk)
+{
+ crypto_sign_keypair(pk, sk);
}
-void rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk, rspamd_sig_sk_t sk,
- enum rspamd_cryptobox_mode mode)
+void rspamd_cryptobox_nm(rspamd_nm_t nm,
+ const rspamd_pk_t pk, const rspamd_sk_t sk)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- crypto_sign_keypair(pk, sk);
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EC_KEY *ec_sec;
- const BIGNUM *bn_sec;
- const EC_POINT *ec_pub;
- gsize len;
-
- ec_sec = EC_KEY_new_by_curve_name(CRYPTOBOX_CURVE_NID);
- g_assert(ec_sec != NULL);
- g_assert(EC_KEY_generate_key(ec_sec) != 0);
-
- bn_sec = EC_KEY_get0_private_key(ec_sec);
- g_assert(bn_sec != NULL);
- ec_pub = EC_KEY_get0_public_key(ec_sec);
- g_assert(ec_pub != NULL);
-
-#if OPENSSL_VERSION_MAJOR >= 3
- unsigned char *buf = NULL; /* Thanks openssl for this API (no) */
- len = EC_POINT_point2buf(EC_KEY_get0_group(ec_sec), ec_pub,
- POINT_CONVERSION_UNCOMPRESSED, &buf, NULL);
- g_assert(len <= (int) rspamd_cryptobox_pk_bytes(mode));
- memcpy(pk, buf, len);
- OPENSSL_free(buf);
-#else
- BIGNUM *bn_pub;
- bn_pub = EC_POINT_point2bn(EC_KEY_get0_group(ec_sec),
- ec_pub, POINT_CONVERSION_UNCOMPRESSED, NULL, NULL);
- len = BN_num_bytes(bn_pub);
- g_assert(len <= (int) rspamd_cryptobox_pk_bytes(mode));
- BN_bn2bin(bn_pub, pk);
- BN_free(bn_pub);
-#endif
+ unsigned char s[32];
+ unsigned char e[32];
- len = BN_num_bytes(bn_sec);
- g_assert(len <= (int) sizeof(rspamd_sk_t));
- BN_bn2bin(bn_sec, sk);
- EC_KEY_free(ec_sec);
-#endif
+ memcpy(e, sk, 32);
+ e[0] &= 248;
+ e[31] &= 127;
+ e[31] |= 64;
+
+ if (crypto_scalarmult(s, e, pk) != -1) {
+ hchacha(s, n0, nm, 20);
}
+
+ rspamd_explicit_memzero(e, 32);
}
-#if OPENSSL_VERSION_MAJOR >= 3
-/* Compatibility function for OpenSSL 3.0 - thanks for breaking all API one more time */
-EC_POINT *ec_point_bn2point_compat(const EC_GROUP *group,
- const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx)
+void rspamd_cryptobox_sign(unsigned char *sig, unsigned long long *siglen_p,
+ const unsigned char *m, gsize mlen,
+ const rspamd_sig_sk_t sk)
{
- size_t buf_len = 0;
- unsigned char *buf;
- EC_POINT *ret;
-
- if ((buf_len = BN_num_bytes(bn)) == 0)
- buf_len = 1;
- if ((buf = OPENSSL_malloc(buf_len)) == NULL) {
- return NULL;
- }
+ crypto_sign_detached(sig, siglen_p, m, mlen, sk);
+}
- if (!BN_bn2binpad(bn, buf, buf_len)) {
- OPENSSL_free(buf);
- return NULL;
- }
+#ifdef HAVE_OPENSSL
+bool rspamd_cryptobox_verify_evp_ed25519(int nid,
+ const unsigned char *sig,
+ gsize siglen,
+ const unsigned char *digest,
+ gsize dlen,
+ struct evp_pkey_st *pub_key)
+{
+ bool ret = false;
- if (point == NULL) {
- if ((ret = EC_POINT_new(group)) == NULL) {
- OPENSSL_free(buf);
- return NULL;
- }
- }
- else
- ret = point;
-
- if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) {
- if (ret != point)
- EC_POINT_clear_free(ret);
- OPENSSL_free(buf);
- return NULL;
+ if (siglen == crypto_sign_bytes()) {
+ rspamd_pk_t pk;
+ size_t len_pk = sizeof(rspamd_pk_t);
+ EVP_PKEY_get_raw_public_key(pub_key, pk, &len_pk);
+ ret = (crypto_sign_verify_detached(sig, digest, dlen, pk) == 0);
}
- OPENSSL_free(buf);
return ret;
}
-#else
-#define ec_point_bn2point_compat EC_POINT_bn2point
-#endif
-void rspamd_cryptobox_nm(rspamd_nm_t nm,
- const rspamd_pk_t pk, const rspamd_sk_t sk,
- enum rspamd_cryptobox_mode mode)
+bool rspamd_cryptobox_verify_evp_ecdsa(int nid,
+ const unsigned char *sig,
+ gsize siglen,
+ const unsigned char *digest,
+ gsize dlen,
+ EVP_PKEY *pub_key)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- unsigned char s[32];
- unsigned char e[32];
+ bool ret = false;
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pub_key, NULL);
+ g_assert(pctx != NULL);
+ EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
+ const EVP_MD *md = EVP_get_digestbynid(nid);
- memcpy(e, sk, 32);
- e[0] &= 248;
- e[31] &= 127;
- e[31] |= 64;
+ g_assert(EVP_PKEY_verify_init(pctx) == 1);
+ g_assert(EVP_PKEY_CTX_set_signature_md(pctx, md) == 1);
- if (crypto_scalarmult(s, e, pk) != -1) {
- hchacha(s, n0, nm, 20);
- }
+ ret = (EVP_PKEY_verify(pctx, sig, siglen, digest, dlen) == 1);
- rspamd_explicit_memzero(e, 32);
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EC_KEY *lk;
- EC_POINT *ec_pub;
- BIGNUM *bn_pub, *bn_sec;
- int len;
- unsigned char s[32];
-
- lk = EC_KEY_new_by_curve_name(CRYPTOBOX_CURVE_NID);
- g_assert(lk != NULL);
-
- bn_pub = BN_bin2bn(pk, rspamd_cryptobox_pk_bytes(mode), NULL);
- g_assert(bn_pub != NULL);
- bn_sec = BN_bin2bn(sk, sizeof(rspamd_sk_t), NULL);
- g_assert(bn_sec != NULL);
-
- g_assert(EC_KEY_set_private_key(lk, bn_sec) == 1);
- ec_pub = ec_point_bn2point_compat(EC_KEY_get0_group(lk), bn_pub, NULL, NULL);
- g_assert(ec_pub != NULL);
- len = ECDH_compute_key(s, sizeof(s), ec_pub, lk, NULL);
- g_assert(len == sizeof(s));
-
- /* Still do hchacha iteration since we are not using SHA1 KDF */
- hchacha(s, n0, nm, 20);
+ EVP_PKEY_CTX_free(pctx);
+ EVP_MD_CTX_free(mdctx);
- EC_KEY_free(lk);
- EC_POINT_free(ec_pub);
- BN_free(bn_sec);
- BN_free(bn_pub);
-#endif
- }
+ return ret;
}
-
-void rspamd_cryptobox_sign(unsigned char *sig, unsigned long long *siglen_p,
- const unsigned char *m, gsize mlen,
- const rspamd_sk_t sk,
- enum rspamd_cryptobox_mode mode)
+bool rspamd_cryptobox_verify_evp_rsa(int nid,
+ const unsigned char *sig,
+ gsize siglen,
+ const unsigned char *digest,
+ gsize dlen,
+ EVP_PKEY *pub_key)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- crypto_sign_detached(sig, siglen_p, m, mlen, sk);
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EC_KEY *lk;
- BIGNUM *bn_sec;
- EVP_MD_CTX *sha_ctx;
- unsigned char h[64];
- unsigned int diglen = rspamd_cryptobox_signature_bytes(mode);
-
- /* Prehash */
- sha_ctx = EVP_MD_CTX_create();
- g_assert(EVP_DigestInit(sha_ctx, EVP_sha512()) == 1);
- EVP_DigestUpdate(sha_ctx, m, mlen);
- EVP_DigestFinal(sha_ctx, h, NULL);
-
- /* Key setup */
- lk = EC_KEY_new_by_curve_name(CRYPTOBOX_CURVE_NID);
- g_assert(lk != NULL);
- bn_sec = BN_bin2bn(sk, sizeof(rspamd_sk_t), NULL);
- g_assert(bn_sec != NULL);
- g_assert(EC_KEY_set_private_key(lk, bn_sec) == 1);
-
- /* ECDSA */
- g_assert(ECDSA_sign(0, h, sizeof(h), sig, &diglen, lk) == 1);
- g_assert(diglen <= sizeof(rspamd_signature_t));
-
- if (siglen_p) {
- *siglen_p = diglen;
- }
+ bool ret = false;
- EC_KEY_free(lk);
- EVP_MD_CTX_destroy(sha_ctx);
- BN_free(bn_sec);
-#endif
- }
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pub_key, NULL);
+ g_assert(pctx != NULL);
+ EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
+ const EVP_MD *md = EVP_get_digestbynid(nid);
+
+ g_assert(EVP_PKEY_verify_init(pctx) == 1);
+ g_assert(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) == 1);
+ g_assert(EVP_PKEY_CTX_set_signature_md(pctx, md) == 1);
+
+ ret = (EVP_PKEY_verify(pctx, sig, siglen, digest, dlen) == 1);
+
+ EVP_PKEY_CTX_free(pctx);
+ EVP_MD_CTX_free(mdctx);
+
+ return ret;
}
+#endif
bool rspamd_cryptobox_verify(const unsigned char *sig,
gsize siglen,
const unsigned char *m,
gsize mlen,
- const rspamd_pk_t pk,
- enum rspamd_cryptobox_mode mode)
+ const rspamd_sig_pk_t pk)
{
bool ret = false;
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- if (siglen == rspamd_cryptobox_signature_bytes(RSPAMD_CRYPTOBOX_MODE_25519)) {
- ret = (crypto_sign_verify_detached(sig, m, mlen, pk) == 0);
- }
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EC_KEY *lk;
- EC_POINT *ec_pub;
- BIGNUM *bn_pub;
- EVP_MD_CTX *sha_ctx;
- unsigned char h[64];
-
- /* Prehash */
- sha_ctx = EVP_MD_CTX_create();
- g_assert(EVP_DigestInit(sha_ctx, EVP_sha512()) == 1);
- EVP_DigestUpdate(sha_ctx, m, mlen);
- EVP_DigestFinal(sha_ctx, h, NULL);
-
- /* Key setup */
- lk = EC_KEY_new_by_curve_name(CRYPTOBOX_CURVE_NID);
- g_assert(lk != NULL);
- bn_pub = BN_bin2bn(pk, rspamd_cryptobox_pk_bytes(mode), NULL);
- g_assert(bn_pub != NULL);
- ec_pub = ec_point_bn2point_compat(EC_KEY_get0_group(lk), bn_pub, NULL, NULL);
- g_assert(ec_pub != NULL);
- g_assert(EC_KEY_set_public_key(lk, ec_pub) == 1);
-
- /* ECDSA */
- ret = ECDSA_verify(0, h, sizeof(h), sig, siglen, lk) == 1;
-
- EC_KEY_free(lk);
- EVP_MD_CTX_destroy(sha_ctx);
- BN_free(bn_pub);
- EC_POINT_free(ec_pub);
-#endif
+ if (siglen == crypto_sign_bytes()) {
+ ret = (crypto_sign_verify_detached(sig, m, mlen, pk) == 0);
}
return ret;
}
-static gsize
-rspamd_cryptobox_encrypt_ctx_len(enum rspamd_cryptobox_mode mode)
-{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- return sizeof(chacha_state) + CRYPTOBOX_ALIGNMENT;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- return sizeof(EVP_CIPHER_CTX *) + CRYPTOBOX_ALIGNMENT;
-#endif
- }
-
- return 0;
-}
-
-static gsize
-rspamd_cryptobox_auth_ctx_len(enum rspamd_cryptobox_mode mode)
-{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- return sizeof(crypto_onetimeauth_state) + RSPAMD_ALIGNOF(crypto_onetimeauth_state);
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- return sizeof(void *);
-#endif
- }
-
- return 0;
-}
-
static void *
rspamd_cryptobox_encrypt_init(void *enc_ctx, const rspamd_nonce_t nonce,
- const rspamd_nm_t nm,
- enum rspamd_cryptobox_mode mode)
+ const rspamd_nm_t nm)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- chacha_state *s;
+ chacha_state *s;
- s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
- xchacha_init(s,
- (const chacha_key *) nm,
- (const chacha_iv24 *) nonce,
- 20);
-
- return s;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EVP_CIPHER_CTX **s;
-
- s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
- memset(s, 0, sizeof(*s));
- *s = EVP_CIPHER_CTX_new();
- g_assert(EVP_EncryptInit_ex(*s, EVP_aes_256_gcm(), NULL, NULL, NULL) == 1);
- g_assert(EVP_CIPHER_CTX_ctrl(*s, EVP_CTRL_GCM_SET_IVLEN,
- rspamd_cryptobox_nonce_bytes(mode), NULL) == 1);
- g_assert(EVP_EncryptInit_ex(*s, NULL, NULL, nm, nonce) == 1);
-
- return s;
-#endif
- }
+ s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
+ xchacha_init(s,
+ (const chacha_key *) nm,
+ (const chacha_iv24 *) nonce,
+ 20);
- return NULL;
+ return s;
}
static void *
-rspamd_cryptobox_auth_init(void *auth_ctx, void *enc_ctx,
- enum rspamd_cryptobox_mode mode)
+rspamd_cryptobox_auth_init(void *auth_ctx, void *enc_ctx)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- crypto_onetimeauth_state *mac_ctx;
- unsigned char RSPAMD_ALIGNED(32) subkey[CHACHA_BLOCKBYTES];
-
- mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
- memset(subkey, 0, sizeof(subkey));
- chacha_update(enc_ctx, subkey, subkey, sizeof(subkey));
- crypto_onetimeauth_init(mac_ctx, subkey);
- rspamd_explicit_memzero(subkey, sizeof(subkey));
-
- return mac_ctx;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- auth_ctx = enc_ctx;
+ crypto_onetimeauth_state *mac_ctx;
+ unsigned char RSPAMD_ALIGNED(32) subkey[CHACHA_BLOCKBYTES];
- return auth_ctx;
-#endif
- }
+ mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
+ memset(subkey, 0, sizeof(subkey));
+ chacha_update(enc_ctx, subkey, subkey, sizeof(subkey));
+ crypto_onetimeauth_init(mac_ctx, subkey);
+ rspamd_explicit_memzero(subkey, sizeof(subkey));
- return NULL;
+ return mac_ctx;
}
static gboolean
rspamd_cryptobox_encrypt_update(void *enc_ctx, const unsigned char *in, gsize inlen,
- unsigned char *out, gsize *outlen,
- enum rspamd_cryptobox_mode mode)
+ unsigned char *out, gsize *outlen)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- gsize r;
- chacha_state *s;
-
- s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
-
- r = chacha_update(s, in, out, inlen);
-
- if (outlen != NULL) {
- *outlen = r;
- }
-
- return TRUE;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EVP_CIPHER_CTX **s = enc_ctx;
- int r;
+ gsize r;
+ chacha_state *s;
- r = inlen;
- g_assert(EVP_EncryptUpdate(*s, out, &r, in, inlen) == 1);
+ s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
- if (outlen) {
- *outlen = r;
- }
+ r = chacha_update(s, in, out, inlen);
- return TRUE;
-#endif
+ if (outlen != NULL) {
+ *outlen = r;
}
- return FALSE;
+ return TRUE;
}
static gboolean
-rspamd_cryptobox_auth_update(void *auth_ctx, const unsigned char *in, gsize inlen,
- enum rspamd_cryptobox_mode mode)
+rspamd_cryptobox_auth_update(void *auth_ctx, const unsigned char *in, gsize inlen)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- crypto_onetimeauth_state *mac_ctx;
+ crypto_onetimeauth_state *mac_ctx;
- mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
- crypto_onetimeauth_update(mac_ctx, in, inlen);
+ mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
+ crypto_onetimeauth_update(mac_ctx, in, inlen);
- return TRUE;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- return TRUE;
-#endif
- }
-
- return FALSE;
+ return TRUE;
}
static gsize
-rspamd_cryptobox_encrypt_final(void *enc_ctx, unsigned char *out, gsize remain,
- enum rspamd_cryptobox_mode mode)
+rspamd_cryptobox_encrypt_final(void *enc_ctx, unsigned char *out, gsize remain)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- chacha_state *s;
-
- s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
- return chacha_final(s, out);
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EVP_CIPHER_CTX **s = enc_ctx;
- int r = remain;
+ chacha_state *s;
- g_assert(EVP_EncryptFinal_ex(*s, out, &r) == 1);
-
- return r;
-#endif
- }
-
- return 0;
+ s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
+ return chacha_final(s, out);
}
static gboolean
-rspamd_cryptobox_auth_final(void *auth_ctx, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode)
+rspamd_cryptobox_auth_final(void *auth_ctx, rspamd_mac_t sig)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- crypto_onetimeauth_state *mac_ctx;
-
- mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
- crypto_onetimeauth_final(mac_ctx, sig);
-
- return TRUE;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EVP_CIPHER_CTX **s = auth_ctx;
-
- g_assert(EVP_CIPHER_CTX_ctrl(*s, EVP_CTRL_GCM_GET_TAG,
- sizeof(rspamd_mac_t), sig) == 1);
+ crypto_onetimeauth_state *mac_ctx;
- return TRUE;
-#endif
- }
+ mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
+ crypto_onetimeauth_final(mac_ctx, sig);
- return FALSE;
+ return TRUE;
}
static void *
rspamd_cryptobox_decrypt_init(void *enc_ctx, const rspamd_nonce_t nonce,
- const rspamd_nm_t nm,
- enum rspamd_cryptobox_mode mode)
+ const rspamd_nm_t nm)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
-
- chacha_state *s;
+ chacha_state *s;
- s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
- xchacha_init(s,
- (const chacha_key *) nm,
- (const chacha_iv24 *) nonce,
- 20);
+ s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
+ xchacha_init(s,
+ (const chacha_key *) nm,
+ (const chacha_iv24 *) nonce,
+ 20);
- return s;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EVP_CIPHER_CTX **s;
-
- s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
- memset(s, 0, sizeof(*s));
- *s = EVP_CIPHER_CTX_new();
- g_assert(EVP_DecryptInit_ex(*s, EVP_aes_256_gcm(), NULL, NULL, NULL) == 1);
- g_assert(EVP_CIPHER_CTX_ctrl(*s, EVP_CTRL_GCM_SET_IVLEN,
- rspamd_cryptobox_nonce_bytes(mode), NULL) == 1);
- g_assert(EVP_DecryptInit_ex(*s, NULL, NULL, nm, nonce) == 1);
-
- return s;
-#endif
- }
-
- return NULL;
+ return s;
}
static void *
-rspamd_cryptobox_auth_verify_init(void *auth_ctx, void *enc_ctx,
- enum rspamd_cryptobox_mode mode)
+rspamd_cryptobox_auth_verify_init(void *auth_ctx, void *enc_ctx)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- crypto_onetimeauth_state *mac_ctx;
- unsigned char RSPAMD_ALIGNED(32) subkey[CHACHA_BLOCKBYTES];
+ crypto_onetimeauth_state *mac_ctx;
+ unsigned char RSPAMD_ALIGNED(32) subkey[CHACHA_BLOCKBYTES];
- mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
- memset(subkey, 0, sizeof(subkey));
- chacha_update(enc_ctx, subkey, subkey, sizeof(subkey));
- crypto_onetimeauth_init(mac_ctx, subkey);
- rspamd_explicit_memzero(subkey, sizeof(subkey));
+ mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
+ memset(subkey, 0, sizeof(subkey));
+ chacha_update(enc_ctx, subkey, subkey, sizeof(subkey));
+ crypto_onetimeauth_init(mac_ctx, subkey);
+ rspamd_explicit_memzero(subkey, sizeof(subkey));
- return mac_ctx;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- auth_ctx = enc_ctx;
-
- return auth_ctx;
-#endif
- }
-
- return NULL;
+ return mac_ctx;
}
static gboolean
rspamd_cryptobox_decrypt_update(void *enc_ctx, const unsigned char *in, gsize inlen,
- unsigned char *out, gsize *outlen,
- enum rspamd_cryptobox_mode mode)
+ unsigned char *out, gsize *outlen)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- gsize r;
- chacha_state *s;
-
- s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
- r = chacha_update(s, in, out, inlen);
+ gsize r;
+ chacha_state *s;
- if (outlen != NULL) {
- *outlen = r;
- }
+ s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
+ r = chacha_update(s, in, out, inlen);
- return TRUE;
+ if (outlen != NULL) {
+ *outlen = r;
}
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EVP_CIPHER_CTX **s = enc_ctx;
- int r;
-
- r = outlen ? *outlen : inlen;
- g_assert(EVP_DecryptUpdate(*s, out, &r, in, inlen) == 1);
- if (outlen) {
- *outlen = r;
- }
-
- return TRUE;
-#endif
- }
+ return TRUE;
}
static gboolean
rspamd_cryptobox_auth_verify_update(void *auth_ctx,
- const unsigned char *in, gsize inlen,
- enum rspamd_cryptobox_mode mode)
+ const unsigned char *in, gsize inlen)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- crypto_onetimeauth_state *mac_ctx;
-
- mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
- crypto_onetimeauth_update(mac_ctx, in, inlen);
+ crypto_onetimeauth_state *mac_ctx;
- return TRUE;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- /* We do not need to authenticate as a separate process */
- return TRUE;
-#else
-#endif
- }
+ mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
+ crypto_onetimeauth_update(mac_ctx, in, inlen);
- return FALSE;
+ return TRUE;
}
static gboolean
-rspamd_cryptobox_decrypt_final(void *enc_ctx, unsigned char *out, gsize remain,
- enum rspamd_cryptobox_mode mode)
+rspamd_cryptobox_decrypt_final(void *enc_ctx, unsigned char *out, gsize remain)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- chacha_state *s;
+ chacha_state *s;
- s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
- chacha_final(s, out);
+ s = cryptobox_align_ptr(enc_ctx, CRYPTOBOX_ALIGNMENT);
+ chacha_final(s, out);
- return TRUE;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EVP_CIPHER_CTX **s = enc_ctx;
- int r = remain;
-
- if (EVP_DecryptFinal_ex(*s, out, &r) < 0) {
- return FALSE;
- }
-
- return TRUE;
-#endif
- }
-
- return FALSE;
+ return TRUE;
}
static gboolean
-rspamd_cryptobox_auth_verify_final(void *auth_ctx, const rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode)
+rspamd_cryptobox_auth_verify_final(void *auth_ctx, const rspamd_mac_t sig)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- rspamd_mac_t mac;
- crypto_onetimeauth_state *mac_ctx;
+ rspamd_mac_t mac;
+ crypto_onetimeauth_state *mac_ctx;
- mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
- crypto_onetimeauth_final(mac_ctx, mac);
-
- if (crypto_verify_16(mac, sig) != 0) {
- return FALSE;
- }
+ mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
+ crypto_onetimeauth_final(mac_ctx, mac);
- return TRUE;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EVP_CIPHER_CTX **s = auth_ctx;
-
- if (EVP_CIPHER_CTX_ctrl(*s, EVP_CTRL_GCM_SET_TAG, 16, (unsigned char *) sig) != 1) {
- return FALSE;
- }
-
- return TRUE;
-#endif
+ if (crypto_verify_16(mac, sig) != 0) {
+ return FALSE;
}
- return FALSE;
+ return TRUE;
}
static void
-rspamd_cryptobox_cleanup(void *enc_ctx, void *auth_ctx,
- enum rspamd_cryptobox_mode mode)
+rspamd_cryptobox_cleanup(void *enc_ctx, void *auth_ctx)
{
- if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- crypto_onetimeauth_state *mac_ctx;
-
- mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
- rspamd_explicit_memzero(mac_ctx, sizeof(*mac_ctx));
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- EVP_CIPHER_CTX **s = enc_ctx;
+ crypto_onetimeauth_state *mac_ctx;
- EVP_CIPHER_CTX_cleanup(*s);
- EVP_CIPHER_CTX_free(*s);
-#endif
- }
+ mac_ctx = cryptobox_align_ptr(auth_ctx, CRYPTOBOX_ALIGNMENT);
+ rspamd_explicit_memzero(mac_ctx, sizeof(*mac_ctx));
}
void rspamd_cryptobox_encrypt_nm_inplace(unsigned char *data, gsize len,
const rspamd_nonce_t nonce,
const rspamd_nm_t nm,
- rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode)
+ rspamd_mac_t sig)
{
gsize r;
void *enc_ctx, *auth_ctx;
- enc_ctx = g_alloca(rspamd_cryptobox_encrypt_ctx_len(mode));
- auth_ctx = g_alloca(rspamd_cryptobox_auth_ctx_len(mode));
+ enc_ctx = g_alloca(sizeof(chacha_state) + CRYPTOBOX_ALIGNMENT);
+ auth_ctx = g_alloca(sizeof(crypto_onetimeauth_state) + RSPAMD_ALIGNOF(crypto_onetimeauth_state));
- enc_ctx = rspamd_cryptobox_encrypt_init(enc_ctx, nonce, nm, mode);
- auth_ctx = rspamd_cryptobox_auth_init(auth_ctx, enc_ctx, mode);
+ enc_ctx = rspamd_cryptobox_encrypt_init(enc_ctx, nonce, nm);
+ auth_ctx = rspamd_cryptobox_auth_init(auth_ctx, enc_ctx);
- rspamd_cryptobox_encrypt_update(enc_ctx, data, len, data, &r, mode);
- rspamd_cryptobox_encrypt_final(enc_ctx, data + r, len - r, mode);
+ rspamd_cryptobox_encrypt_update(enc_ctx, data, len, data, &r);
+ rspamd_cryptobox_encrypt_final(enc_ctx, data + r, len - r);
- rspamd_cryptobox_auth_update(auth_ctx, data, len, mode);
- rspamd_cryptobox_auth_final(auth_ctx, sig, mode);
+ rspamd_cryptobox_auth_update(auth_ctx, data, len);
+ rspamd_cryptobox_auth_final(auth_ctx, sig);
- rspamd_cryptobox_cleanup(enc_ctx, auth_ctx, mode);
+ rspamd_cryptobox_cleanup(enc_ctx, auth_ctx);
}
static void
@@ -1098,8 +655,7 @@ rspamd_cryptobox_flush_outbuf(struct rspamd_cryptobox_segment *st,
void rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment *segments,
gsize cnt,
const rspamd_nonce_t nonce,
- const rspamd_nm_t nm, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode)
+ const rspamd_nm_t nm, rspamd_mac_t sig)
{
struct rspamd_cryptobox_segment *cur = segments, *start_seg = segments;
unsigned char outbuf[CHACHA_BLOCKBYTES * 16];
@@ -1107,11 +663,11 @@ void rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment *segme
unsigned char *out, *in;
gsize r, remain, inremain, seg_offset;
- enc_ctx = g_alloca(rspamd_cryptobox_encrypt_ctx_len(mode));
- auth_ctx = g_alloca(rspamd_cryptobox_auth_ctx_len(mode));
+ enc_ctx = g_alloca(sizeof(chacha_state) + CRYPTOBOX_ALIGNMENT);
+ auth_ctx = g_alloca(sizeof(crypto_onetimeauth_state) + RSPAMD_ALIGNOF(crypto_onetimeauth_state));
- enc_ctx = rspamd_cryptobox_encrypt_init(enc_ctx, nonce, nm, mode);
- auth_ctx = rspamd_cryptobox_auth_init(auth_ctx, enc_ctx, mode);
+ enc_ctx = rspamd_cryptobox_encrypt_init(enc_ctx, nonce, nm);
+ auth_ctx = rspamd_cryptobox_auth_init(auth_ctx, enc_ctx);
remain = sizeof(outbuf);
out = outbuf;
@@ -1131,9 +687,8 @@ void rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment *segme
if (remain == 0) {
rspamd_cryptobox_encrypt_update(enc_ctx, outbuf, sizeof(outbuf),
- outbuf, NULL, mode);
- rspamd_cryptobox_auth_update(auth_ctx, outbuf, sizeof(outbuf),
- mode);
+ outbuf, NULL);
+ rspamd_cryptobox_auth_update(auth_ctx, outbuf, sizeof(outbuf));
rspamd_cryptobox_flush_outbuf(start_seg, outbuf,
sizeof(outbuf), seg_offset);
start_seg = cur;
@@ -1145,9 +700,8 @@ void rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment *segme
else {
memcpy(out, cur->data, remain);
rspamd_cryptobox_encrypt_update(enc_ctx, outbuf, sizeof(outbuf),
- outbuf, NULL, mode);
- rspamd_cryptobox_auth_update(auth_ctx, outbuf, sizeof(outbuf),
- mode);
+ outbuf, NULL);
+ rspamd_cryptobox_auth_update(auth_ctx, outbuf, sizeof(outbuf));
rspamd_cryptobox_flush_outbuf(start_seg, outbuf, sizeof(outbuf),
seg_offset);
seg_offset = 0;
@@ -1165,12 +719,10 @@ void rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment *segme
outbuf,
sizeof(outbuf),
outbuf,
- NULL,
- mode);
+ NULL);
rspamd_cryptobox_auth_update(auth_ctx,
outbuf,
- sizeof(outbuf),
- mode);
+ sizeof(outbuf));
memcpy(in, outbuf, sizeof(outbuf));
in += sizeof(outbuf);
inremain -= sizeof(outbuf);
@@ -1190,46 +742,44 @@ void rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment *segme
}
rspamd_cryptobox_encrypt_update(enc_ctx, outbuf, sizeof(outbuf) - remain,
- outbuf, &r, mode);
+ outbuf, &r);
out = outbuf + r;
- rspamd_cryptobox_encrypt_final(enc_ctx, out, sizeof(outbuf) - remain - r,
- mode);
+ rspamd_cryptobox_encrypt_final(enc_ctx, out, sizeof(outbuf) - remain - r);
- rspamd_cryptobox_auth_update(auth_ctx, outbuf, sizeof(outbuf) - remain,
- mode);
- rspamd_cryptobox_auth_final(auth_ctx, sig, mode);
+ rspamd_cryptobox_auth_update(auth_ctx, outbuf, sizeof(outbuf) - remain);
+ rspamd_cryptobox_auth_final(auth_ctx, sig);
rspamd_cryptobox_flush_outbuf(start_seg, outbuf, sizeof(outbuf) - remain,
seg_offset);
- rspamd_cryptobox_cleanup(enc_ctx, auth_ctx, mode);
+ rspamd_cryptobox_cleanup(enc_ctx, auth_ctx);
}
gboolean
rspamd_cryptobox_decrypt_nm_inplace(unsigned char *data, gsize len,
const rspamd_nonce_t nonce, const rspamd_nm_t nm,
- const rspamd_mac_t sig, enum rspamd_cryptobox_mode mode)
+ const rspamd_mac_t sig)
{
gsize r = 0;
gboolean ret = TRUE;
void *enc_ctx, *auth_ctx;
- enc_ctx = g_alloca(rspamd_cryptobox_encrypt_ctx_len(mode));
- auth_ctx = g_alloca(rspamd_cryptobox_auth_ctx_len(mode));
+ enc_ctx = g_alloca(sizeof(chacha_state) + CRYPTOBOX_ALIGNMENT);
+ auth_ctx = g_alloca(sizeof(crypto_onetimeauth_state) + RSPAMD_ALIGNOF(crypto_onetimeauth_state));
- enc_ctx = rspamd_cryptobox_decrypt_init(enc_ctx, nonce, nm, mode);
- auth_ctx = rspamd_cryptobox_auth_verify_init(auth_ctx, enc_ctx, mode);
+ enc_ctx = rspamd_cryptobox_decrypt_init(enc_ctx, nonce, nm);
+ auth_ctx = rspamd_cryptobox_auth_verify_init(auth_ctx, enc_ctx);
- rspamd_cryptobox_auth_verify_update(auth_ctx, data, len, mode);
+ rspamd_cryptobox_auth_verify_update(auth_ctx, data, len);
- if (!rspamd_cryptobox_auth_verify_final(auth_ctx, sig, mode)) {
+ if (!rspamd_cryptobox_auth_verify_final(auth_ctx, sig)) {
ret = FALSE;
}
else {
- rspamd_cryptobox_decrypt_update(enc_ctx, data, len, data, &r, mode);
- ret = rspamd_cryptobox_decrypt_final(enc_ctx, data + r, len - r, mode);
+ rspamd_cryptobox_decrypt_update(enc_ctx, data, len, data, &r);
+ ret = rspamd_cryptobox_decrypt_final(enc_ctx, data + r, len - r);
}
- rspamd_cryptobox_cleanup(enc_ctx, auth_ctx, mode);
+ rspamd_cryptobox_cleanup(enc_ctx, auth_ctx);
return ret;
}
@@ -1238,14 +788,13 @@ gboolean
rspamd_cryptobox_decrypt_inplace(unsigned char *data, gsize len,
const rspamd_nonce_t nonce,
const rspamd_pk_t pk, const rspamd_sk_t sk,
- const rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode)
+ const rspamd_mac_t sig)
{
unsigned char nm[rspamd_cryptobox_MAX_NMBYTES];
gboolean ret;
- rspamd_cryptobox_nm(nm, pk, sk, mode);
- ret = rspamd_cryptobox_decrypt_nm_inplace(data, len, nonce, nm, sig, mode);
+ rspamd_cryptobox_nm(nm, pk, sk);
+ ret = rspamd_cryptobox_decrypt_nm_inplace(data, len, nonce, nm, sig);
rspamd_explicit_memzero(nm, sizeof(nm));
@@ -1255,13 +804,12 @@ rspamd_cryptobox_decrypt_inplace(unsigned char *data, gsize len,
void rspamd_cryptobox_encrypt_inplace(unsigned char *data, gsize len,
const rspamd_nonce_t nonce,
const rspamd_pk_t pk, const rspamd_sk_t sk,
- rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode)
+ rspamd_mac_t sig)
{
unsigned char nm[rspamd_cryptobox_MAX_NMBYTES];
- rspamd_cryptobox_nm(nm, pk, sk, mode);
- rspamd_cryptobox_encrypt_nm_inplace(data, len, nonce, nm, sig, mode);
+ rspamd_cryptobox_nm(nm, pk, sk);
+ rspamd_cryptobox_encrypt_nm_inplace(data, len, nonce, nm, sig);
rspamd_explicit_memzero(nm, sizeof(nm));
}
@@ -1269,13 +817,12 @@ void rspamd_cryptobox_encryptv_inplace(struct rspamd_cryptobox_segment *segments
gsize cnt,
const rspamd_nonce_t nonce,
const rspamd_pk_t pk, const rspamd_sk_t sk,
- rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode)
+ rspamd_mac_t sig)
{
unsigned char nm[rspamd_cryptobox_MAX_NMBYTES];
- rspamd_cryptobox_nm(nm, pk, sk, mode);
- rspamd_cryptobox_encryptv_nm_inplace(segments, cnt, nonce, nm, sig, mode);
+ rspamd_cryptobox_nm(nm, pk, sk);
+ rspamd_cryptobox_encryptv_nm_inplace(segments, cnt, nonce, nm, sig);
rspamd_explicit_memzero(nm, sizeof(nm));
}
@@ -1288,9 +835,9 @@ void rspamd_cryptobox_siphash(unsigned char *out, const unsigned char *in,
}
/*
- * Password-Based Key Derivation Function 2 (PKCS #5 v2.0).
- * Code based on IEEE Std 802.11-2007, Annex H.4.2.
- */
+* Password-Based Key Derivation Function 2 (PKCS #5 v2.0).
+* Code based on IEEE Std 802.11-2007, Annex H.4.2.
+*/
static gboolean
rspamd_cryptobox_pbkdf2(const char *pass, gsize pass_len,
const uint8_t *salt, gsize salt_len, uint8_t *key, gsize key_len,
@@ -1327,9 +874,9 @@ rspamd_cryptobox_pbkdf2(const char *pass, gsize pass_len,
uint8_t k[crypto_generichash_blake2b_BYTES_MAX];
/*
- * We use additional blake2 iteration to store large key
- * XXX: it is not compatible with the original implementation but safe
- */
+ * We use additional blake2 iteration to store large key
+ * XXX: it is not compatible with the original implementation but safe
+ */
crypto_generichash_blake2b(k, sizeof(k), pass, pass_len,
NULL, 0);
crypto_generichash_blake2b(d1, sizeof(d1), asalt, salt_len + 4,
@@ -1347,9 +894,9 @@ rspamd_cryptobox_pbkdf2(const char *pass, gsize pass_len,
uint8_t k[crypto_generichash_blake2b_BYTES_MAX];
/*
- * We use additional blake2 iteration to store large key
- * XXX: it is not compatible with the original implementation but safe
- */
+ * We use additional blake2 iteration to store large key
+ * XXX: it is not compatible with the original implementation but safe
+ */
crypto_generichash_blake2b(k, sizeof(k), pass, pass_len,
NULL, 0);
crypto_generichash_blake2b(d2, sizeof(d2), d1, sizeof(d1),
@@ -1402,84 +949,6 @@ rspamd_cryptobox_pbkdf(const char *pass, gsize pass_len,
return ret;
}
-unsigned int rspamd_cryptobox_pk_bytes(enum rspamd_cryptobox_mode mode)
-{
- if (G_UNLIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- return 32;
- }
- else {
- return 65;
- }
-}
-
-unsigned int rspamd_cryptobox_pk_sig_bytes(enum rspamd_cryptobox_mode mode)
-{
- if (G_UNLIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- return 32;
- }
- else {
- return 65;
- }
-}
-
-unsigned int rspamd_cryptobox_nonce_bytes(enum rspamd_cryptobox_mode mode)
-{
- if (G_UNLIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- return 24;
- }
- else {
- return 16;
- }
-}
-
-
-unsigned int rspamd_cryptobox_sk_bytes(enum rspamd_cryptobox_mode mode)
-{
- return 32;
-}
-
-unsigned int rspamd_cryptobox_sk_sig_bytes(enum rspamd_cryptobox_mode mode)
-{
- if (G_UNLIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- return 64;
- }
- else {
- return 32;
- }
-}
-
-unsigned int rspamd_cryptobox_signature_bytes(enum rspamd_cryptobox_mode mode)
-{
- static unsigned int ssl_keylen;
-
- if (G_UNLIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
- return 64;
- }
- else {
-#ifndef HAVE_USABLE_OPENSSL
- g_assert(0);
-#else
- if (ssl_keylen == 0) {
- EC_KEY *lk;
- lk = EC_KEY_new_by_curve_name(CRYPTOBOX_CURVE_NID);
- ssl_keylen = ECDSA_size(lk);
- EC_KEY_free(lk);
- }
-#endif
- return ssl_keylen;
- }
-}
-
-unsigned int rspamd_cryptobox_nm_bytes(enum rspamd_cryptobox_mode mode)
-{
- return 32;
-}
-
-unsigned int rspamd_cryptobox_mac_bytes(enum rspamd_cryptobox_mode mode)
-{
- return 16;
-}
-
void rspamd_cryptobox_hash_init(rspamd_cryptobox_hash_state_t *p, const unsigned char *key, gsize keylen)
{
crypto_generichash_blake2b_state *st = cryptobox_align_ptr(p,
@@ -1489,8 +958,8 @@ void rspamd_cryptobox_hash_init(rspamd_cryptobox_hash_state_t *p, const unsigned
}
/**
- * Update hash with data portion
- */
+* Update hash with data portion
+*/
void rspamd_cryptobox_hash_update(rspamd_cryptobox_hash_state_t *p, const unsigned char *data, gsize len)
{
crypto_generichash_blake2b_state *st = cryptobox_align_ptr(p,
@@ -1499,8 +968,8 @@ void rspamd_cryptobox_hash_update(rspamd_cryptobox_hash_state_t *p, const unsign
}
/**
- * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length
- */
+* Output hash to the buffer of rspamd_cryptobox_HASHBYTES length
+*/
void rspamd_cryptobox_hash_final(rspamd_cryptobox_hash_state_t *p, unsigned char *out)
{
crypto_generichash_blake2b_state *st = cryptobox_align_ptr(p,
@@ -1509,8 +978,8 @@ void rspamd_cryptobox_hash_final(rspamd_cryptobox_hash_state_t *p, unsigned char
}
/**
- * One in all function
- */
+* One in all function
+*/
void rspamd_cryptobox_hash(unsigned char *out,
const unsigned char *data,
gsize len,
@@ -1729,8 +1198,8 @@ rspamd_cryptobox_fast_hash_final(rspamd_cryptobox_fast_hash_state_t *st)
}
/**
- * One in all function
- */
+* One in all function
+*/
static inline uint64_t
rspamd_cryptobox_fast_hash_machdep(const void *data,
gsize len, uint64_t seed)
diff --git a/src/libcryptobox/cryptobox.h b/src/libcryptobox/cryptobox.h
index 8382c8f68..afe9c4f9a 100644
--- a/src/libcryptobox/cryptobox.h
+++ b/src/libcryptobox/cryptobox.h
@@ -13,11 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#ifndef CRYPTOBOX_H_
#define CRYPTOBOX_H_
#include "config.h"
+#ifdef HAVE_OPENSSL
+#include <openssl/evp.h>
+#endif
+
#include <sodium.h>
#ifdef __cplusplus
@@ -35,18 +40,18 @@ struct rspamd_cryptobox_segment {
#define RSPAMD_HAS_TARGET_ATTR 1
#endif
-#define rspamd_cryptobox_MAX_NONCEBYTES 24
-#define rspamd_cryptobox_MAX_PKBYTES 65
-#define rspamd_cryptobox_MAX_SKBYTES 32
-#define rspamd_cryptobox_MAX_MACBYTES 16
-#define rspamd_cryptobox_MAX_NMBYTES 32
+#define rspamd_cryptobox_MAX_NONCEBYTES crypto_box_NONCEBYTES
+#define rspamd_cryptobox_MAX_PKBYTES crypto_box_PUBLICKEYBYTES
+#define rspamd_cryptobox_MAX_SKBYTES crypto_box_SECRETKEYBYTES
+#define rspamd_cryptobox_MAX_MACBYTES crypto_box_MACBYTES
+#define rspamd_cryptobox_MAX_NMBYTES crypto_box_BEFORENMBYTES
#define rspamd_cryptobox_SIPKEYBYTES 16
#define rspamd_cryptobox_HASHBYTES 64
#define rspamd_cryptobox_HASHKEYBYTES 64
#define rspamd_cryptobox_HASHSTATEBYTES sizeof(crypto_generichash_blake2b_state) + 64
-#define rspamd_cryptobox_MAX_SIGSKBYTES 64
-#define rspamd_cryptobox_MAX_SIGPKBYTES 32
-#define rspamd_cryptobox_MAX_SIGBYTES 72
+#define rspamd_cryptobox_MAX_SIGSKBYTES crypto_sign_SECRETKEYBYTES
+#define rspamd_cryptobox_MAX_SIGPKBYTES crypto_sign_PUBLICKEYBYTES
+#define rspamd_cryptobox_MAX_SIGBYTES crypto_sign_BYTES
#define CPUID_AVX2 0x1
#define CPUID_AVX 0x2
@@ -67,10 +72,6 @@ typedef unsigned char rspamd_signature_t[rspamd_cryptobox_MAX_SIGBYTES];
typedef unsigned char rspamd_sig_pk_t[rspamd_cryptobox_MAX_SIGPKBYTES];
typedef unsigned char rspamd_sig_sk_t[rspamd_cryptobox_MAX_SIGSKBYTES];
-enum rspamd_cryptobox_mode {
- RSPAMD_CRYPTOBOX_MODE_25519 = 0,
- RSPAMD_CRYPTOBOX_MODE_NIST
-};
struct rspamd_cryptobox_library_ctx {
char *cpu_extensions;
@@ -80,172 +81,190 @@ struct rspamd_cryptobox_library_ctx {
};
/**
- * Init cryptobox library
- */
+* Init cryptobox library
+*/
struct rspamd_cryptobox_library_ctx *rspamd_cryptobox_init(void);
void rspamd_cryptobox_deinit(struct rspamd_cryptobox_library_ctx *);
/**
- * Generate new keypair
- * @param pk public key buffer
- * @param sk secret key buffer
- */
-void rspamd_cryptobox_keypair(rspamd_pk_t pk, rspamd_sk_t sk,
- enum rspamd_cryptobox_mode mode);
+* Generate new keypair
+* @param pk public key buffer
+* @param sk secret key buffer
+*/
+void rspamd_cryptobox_keypair(rspamd_pk_t pk, rspamd_sk_t sk);
/**
- * Generate new keypair for signing
- * @param pk public key buffer
- * @param sk secret key buffer
- */
-void rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk, rspamd_sig_sk_t sk,
- enum rspamd_cryptobox_mode mode);
+* Generate new keypair for signing
+* @param pk public key buffer
+* @param sk secret key buffer
+*/
+void rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk, rspamd_sig_sk_t sk);
/**
- * Encrypt data inplace adding signature to sig afterwards
- * @param data input buffer
- * @param pk remote pubkey
- * @param sk local secret key
- * @param sig output signature
- */
+* Encrypt data inplace adding signature to sig afterwards
+* @param data input buffer
+* @param pk remote pubkey
+* @param sk local secret key
+* @param sig output signature
+*/
void rspamd_cryptobox_encrypt_inplace(unsigned char *data, gsize len,
const rspamd_nonce_t nonce,
- const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
+ const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig);
/**
- * Encrypt segments of data inplace adding signature to sig afterwards
- * @param segments segments of data
- * @param cnt count of segments
- * @param pk remote pubkey
- * @param sk local secret key
- * @param sig output signature
- */
+* Encrypt segments of data inplace adding signature to sig afterwards
+* @param segments segments of data
+* @param cnt count of segments
+* @param pk remote pubkey
+* @param sk local secret key
+* @param sig output signature
+*/
void rspamd_cryptobox_encryptv_inplace(struct rspamd_cryptobox_segment *segments,
gsize cnt,
const rspamd_nonce_t nonce,
- const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
+ const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig);
/**
- * Decrypt and verify data chunk inplace
- * @param data data to decrypt
- * @param len length of data
- * @param pk remote pubkey
- * @param sk local privkey
- * @param sig signature input
- * @return TRUE if input has been verified successfully
- */
+* Decrypt and verify data chunk inplace
+* @param data data to decrypt
+* @param len length of data
+* @param pk remote pubkey
+* @param sk local privkey
+* @param sig signature input
+* @return TRUE if input has been verified successfully
+*/
gboolean rspamd_cryptobox_decrypt_inplace(unsigned char *data, gsize len,
const rspamd_nonce_t nonce,
- const rspamd_pk_t pk, const rspamd_sk_t sk, const rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
+ const rspamd_pk_t pk, const rspamd_sk_t sk, const rspamd_mac_t sig);
/**
- * Encrypt segments of data inplace adding signature to sig afterwards
- * @param segments segments of data
- * @param cnt count of segments
- * @param pk remote pubkey
- * @param sk local secret key
- * @param sig output signature
- */
+* Encrypt segments of data inplace adding signature to sig afterwards
+* @param segments segments of data
+* @param cnt count of segments
+* @param pk remote pubkey
+* @param sk local secret key
+* @param sig output signature
+*/
void rspamd_cryptobox_encrypt_nm_inplace(unsigned char *data, gsize len,
const rspamd_nonce_t nonce,
- const rspamd_nm_t nm, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
+ const rspamd_nm_t nm, rspamd_mac_t sig);
/**
- * Encrypt segments of data inplace adding signature to sig afterwards
- * @param segments segments of data
- * @param cnt count of segments
- * @param pk remote pubkey
- * @param sk local secret key
- * @param sig output signature
- */
+* Encrypt segments of data inplace adding signature to sig afterwards
+* @param segments segments of data
+* @param cnt count of segments
+* @param pk remote pubkey
+* @param sk local secret key
+* @param sig output signature
+*/
void rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment *segments,
gsize cnt,
const rspamd_nonce_t nonce,
- const rspamd_nm_t nm, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
+ const rspamd_nm_t nm, rspamd_mac_t sig);
/**
- * Decrypt and verify data chunk inplace
- * @param data data to decrypt
- * @param len length of data
- * @param pk remote pubkey
- * @param sk local privkey
- * @param sig signature input
- * @return TRUE if input has been verified successfully
- */
+* Decrypt and verify data chunk inplace
+* @param data data to decrypt
+* @param len length of data
+* @param pk remote pubkey
+* @param sk local privkey
+* @param sig signature input
+* @return TRUE if input has been verified successfully
+*/
gboolean rspamd_cryptobox_decrypt_nm_inplace(unsigned char *data, gsize len,
const rspamd_nonce_t nonce,
- const rspamd_nm_t nm, const rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
+ const rspamd_nm_t nm, const rspamd_mac_t sig);
/**
- * Generate shared secret from local sk and remote pk
- * @param nm shared secret
- * @param pk remote pubkey
- * @param sk local privkey
- */
-void rspamd_cryptobox_nm(rspamd_nm_t nm, const rspamd_pk_t pk,
- const rspamd_sk_t sk, enum rspamd_cryptobox_mode mode);
+* Generate shared secret from local sk and remote pk
+* @param nm shared secret
+* @param pk remote pubkey
+* @param sk local privkey
+*/
+void rspamd_cryptobox_nm(rspamd_nm_t nm, const rspamd_pk_t pk, const rspamd_sk_t sk);
/**
- * Create digital signature for the specified message and place result in `sig`
- * @param sig signature target
- * @param siglen_p pointer to signature length (might be NULL)
- * @param m input message
- * @param mlen input length
- * @param sk secret key
- */
+* Create digital signature for the specified message and place result in `sig`
+* @param sig signature target
+* @param siglen_p pointer to signature length (might be NULL)
+* @param m input message
+* @param mlen input length
+* @param sk secret key
+*/
void rspamd_cryptobox_sign(unsigned char *sig, unsigned long long *siglen_p,
const unsigned char *m, gsize mlen,
- const rspamd_sk_t sk,
- enum rspamd_cryptobox_mode mode);
+ const rspamd_sig_sk_t sk);
/**
- * Verifies digital signature for the specified message using the specified
- * pubkey
- * @param sig signature source
- * @param m input message
- * @param mlen message length
- * @param pk public key for verification
- * @return true if signature is valid, false otherwise
- */
+* Verifies digital signature for the specified message using the specified
+* pubkey
+* @param sig signature source
+* @param m input message
+* @param mlen message length
+* @param pk public key for verification
+* @return true if signature is valid, false otherwise
+*/
bool rspamd_cryptobox_verify(const unsigned char *sig,
gsize siglen,
const unsigned char *m,
gsize mlen,
- const rspamd_pk_t pk,
- enum rspamd_cryptobox_mode mode);
+ const rspamd_sig_pk_t pk);
+#ifdef HAVE_OPENSSL
/**
- * Securely clear the buffer specified
- * @param buf buffer to zero
- * @param buflen length of buffer
+ * Verifies digital signature for specified raw digest with specified pubkey
+ * @param nid signing algorithm nid
+ * @param sig signature source
+ * @param digest raw digest
+ * @param pub_key public key for verification
+ * @return true if signature is valid, false otherwise
*/
+bool rspamd_cryptobox_verify_evp_ed25519(int nid,
+ const unsigned char *sig,
+ gsize siglen,
+ const unsigned char *digest,
+ gsize dlen,
+ EVP_PKEY *pub_key);
+bool rspamd_cryptobox_verify_evp_ecdsa(int nid,
+ const unsigned char *sig,
+ gsize siglen,
+ const unsigned char *digest,
+ gsize dlen,
+ EVP_PKEY *pub_key);
+bool rspamd_cryptobox_verify_evp_rsa(int nid,
+ const unsigned char *sig,
+ gsize siglen,
+ const unsigned char *digest,
+ gsize dlen,
+ EVP_PKEY *pub_key);
+#endif
+
+/**
+* Securely clear the buffer specified
+* @param buf buffer to zero
+* @param buflen length of buffer
+*/
#define rspamd_explicit_memzero sodium_memzero
/**
- * Constant time memcmp
- * @param b1_
- * @param b2_
- * @param len
- * @return
- */
+* Constant time memcmp
+* @param b1_
+* @param b2_
+* @param len
+* @return
+*/
#define rspamd_cryptobox_memcmp sodium_memcmp
/**
- * Calculates siphash-2-4 for a message
- * @param out (8 bytes output)
- * @param in
- * @param inlen
- * @param k key (must be 16 bytes)
- */
+* Calculates siphash-2-4 for a message
+* @param out (8 bytes output)
+* @param in
+* @param inlen
+* @param k key (must be 16 bytes)
+*/
void rspamd_cryptobox_siphash(unsigned char *out, const unsigned char *in,
unsigned long long inlen,
const rspamd_sipkey_t k);
@@ -257,16 +276,16 @@ enum rspamd_cryptobox_pbkdf_type {
/**
- * Derive key from password using the specified algorithm
- * @param pass input password
- * @param pass_len length of the password
- * @param salt input salt
- * @param salt_len length of salt
- * @param key output key
- * @param key_len size of the key
- * @param complexity empiric number of complexity (rounds for pbkdf2 and garlic for catena)
- * @return TRUE in case of success and FALSE if failed
- */
+* Derive key from password using the specified algorithm
+* @param pass input password
+* @param pass_len length of the password
+* @param salt input salt
+* @param salt_len length of salt
+* @param key output key
+* @param key_len size of the key
+* @param complexity empiric number of complexity (rounds for pbkdf2 and garlic for catena)
+* @return TRUE in case of success and FALSE if failed
+*/
gboolean rspamd_cryptobox_pbkdf(const char *pass, gsize pass_len,
const uint8_t *salt, gsize salt_len,
uint8_t *key, gsize key_len,
@@ -274,71 +293,31 @@ gboolean rspamd_cryptobox_pbkdf(const char *pass, gsize pass_len,
enum rspamd_cryptobox_pbkdf_type type);
-/**
- * Real size of rspamd cryptobox public key
- */
-unsigned int rspamd_cryptobox_pk_bytes(enum rspamd_cryptobox_mode mode);
-
-/**
- * Real size of rspamd cryptobox signing public key
- */
-unsigned int rspamd_cryptobox_pk_sig_bytes(enum rspamd_cryptobox_mode mode);
-
-/**
- * Real size of crypto nonce
- */
-unsigned int rspamd_cryptobox_nonce_bytes(enum rspamd_cryptobox_mode mode);
-
-/**
- * Real size of rspamd cryptobox secret key
- */
-unsigned int rspamd_cryptobox_sk_bytes(enum rspamd_cryptobox_mode mode);
-
-/**
- * Real size of rspamd cryptobox signing secret key
- */
-unsigned int rspamd_cryptobox_sk_sig_bytes(enum rspamd_cryptobox_mode mode);
-
-/**
- * Real size of rspamd cryptobox shared key
- */
-unsigned int rspamd_cryptobox_nm_bytes(enum rspamd_cryptobox_mode mode);
-
-/**
- * Real size of rspamd cryptobox MAC signature
- */
-unsigned int rspamd_cryptobox_mac_bytes(enum rspamd_cryptobox_mode mode);
-
-/**
- * Real size of rspamd cryptobox digital signature
- */
-unsigned int rspamd_cryptobox_signature_bytes(enum rspamd_cryptobox_mode mode);
-
/* Hash IUF interface */
typedef crypto_generichash_blake2b_state rspamd_cryptobox_hash_state_t;
/**
- * Init cryptobox hash state using key if needed, `st` must point to the buffer
- * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
- * non-keyed hash is generated
- */
+* Init cryptobox hash state using key if needed, `st` must point to the buffer
+* with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
+* non-keyed hash is generated
+*/
void rspamd_cryptobox_hash_init(rspamd_cryptobox_hash_state_t *st,
const unsigned char *key, gsize keylen);
/**
- * Update hash with data portion
- */
+* Update hash with data portion
+*/
void rspamd_cryptobox_hash_update(rspamd_cryptobox_hash_state_t *st,
const unsigned char *data, gsize len);
/**
- * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length
- */
+* Output hash to the buffer of rspamd_cryptobox_HASHBYTES length
+*/
void rspamd_cryptobox_hash_final(rspamd_cryptobox_hash_state_t *st, unsigned char *out);
/**
- * One in all function
- */
+* One in all function
+*/
void rspamd_cryptobox_hash(unsigned char *out,
const unsigned char *data,
gsize len,
@@ -363,71 +342,71 @@ typedef struct CRYPTO_ALIGN(64) rspamd_cryptobox_fast_hash_state_s {
/**
- * Creates a new cryptobox state properly aligned
- * @return
- */
+* Creates a new cryptobox state properly aligned
+* @return
+*/
rspamd_cryptobox_fast_hash_state_t *rspamd_cryptobox_fast_hash_new(void);
void rspamd_cryptobox_fast_hash_free(rspamd_cryptobox_fast_hash_state_t *st);
/**
- * Init cryptobox hash state using key if needed, `st` must point to the buffer
- * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
- * non-keyed hash is generated
- */
+* Init cryptobox hash state using key if needed, `st` must point to the buffer
+* with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
+* non-keyed hash is generated
+*/
void rspamd_cryptobox_fast_hash_init(rspamd_cryptobox_fast_hash_state_t *st,
uint64_t seed);
/**
- * Init cryptobox hash state using key if needed, `st` must point to the buffer
- * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
- * non-keyed hash is generated
- */
+* Init cryptobox hash state using key if needed, `st` must point to the buffer
+* with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
+* non-keyed hash is generated
+*/
void rspamd_cryptobox_fast_hash_init_specific(rspamd_cryptobox_fast_hash_state_t *st,
enum rspamd_cryptobox_fast_hash_type type,
uint64_t seed);
/**
- * Update hash with data portion
- */
+* Update hash with data portion
+*/
void rspamd_cryptobox_fast_hash_update(rspamd_cryptobox_fast_hash_state_t *st,
const void *data, gsize len);
/**
- * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length
- */
+* Output hash to the buffer of rspamd_cryptobox_HASHBYTES length
+*/
uint64_t rspamd_cryptobox_fast_hash_final(rspamd_cryptobox_fast_hash_state_t *st);
/**
- * One in all function
- */
+* One in all function
+*/
uint64_t rspamd_cryptobox_fast_hash(const void *data,
gsize len, uint64_t seed);
/**
- * Platform independent version
- */
+* Platform independent version
+*/
uint64_t rspamd_cryptobox_fast_hash_specific(
enum rspamd_cryptobox_fast_hash_type type,
const void *data,
gsize len, uint64_t seed);
/**
- * Decode base64 using platform optimized code
- * @param in
- * @param inlen
- * @param out
- * @param outlen
- * @return
- */
+* Decode base64 using platform optimized code
+* @param in
+* @param inlen
+* @param out
+* @param outlen
+* @return
+*/
gboolean rspamd_cryptobox_base64_decode(const char *in, gsize inlen,
unsigned char *out, gsize *outlen);
/**
- * Returns TRUE if data looks like a valid base64 string
- * @param in
- * @param inlen
- * @return
- */
+* Returns TRUE if data looks like a valid base64 string
+* @param in
+* @param inlen
+* @return
+*/
gboolean rspamd_cryptobox_base64_is_valid(const char *in, gsize inlen);
#ifdef __cplusplus
diff --git a/src/libcryptobox/keypair.c b/src/libcryptobox/keypair.c
index 02070bb46..d3f81ee2d 100644
--- a/src/libcryptobox/keypair.c
+++ b/src/libcryptobox/keypair.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -38,29 +38,14 @@ rspamd_cryptobox_keypair_sk(struct rspamd_cryptobox_keypair *kp,
{
g_assert(kp != NULL);
- if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
- if (kp->type == RSPAMD_KEYPAIR_KEX) {
- *len = 32;
- return RSPAMD_CRYPTOBOX_KEYPAIR_25519(kp)->sk;
- }
- else {
- *len = 64;
- return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_25519(kp)->sk;
- }
+ if (kp->type == RSPAMD_KEYPAIR_KEX) {
+ *len = 32;
+ return RSPAMD_CRYPTOBOX_KEYPAIR_25519(kp)->sk;
}
else {
- if (kp->type == RSPAMD_KEYPAIR_KEX) {
- *len = 32;
- return RSPAMD_CRYPTOBOX_KEYPAIR_NIST(kp)->sk;
- }
- else {
- *len = 32;
- return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_NIST(kp)->sk;
- }
+ *len = 64;
+ return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_25519(kp)->sk;
}
-
- /* Not reached */
- return NULL;
}
static void *
@@ -69,29 +54,14 @@ rspamd_cryptobox_keypair_pk(struct rspamd_cryptobox_keypair *kp,
{
g_assert(kp != NULL);
- if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
- if (kp->type == RSPAMD_KEYPAIR_KEX) {
- *len = 32;
- return RSPAMD_CRYPTOBOX_KEYPAIR_25519(kp)->pk;
- }
- else {
- *len = 32;
- return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_25519(kp)->pk;
- }
+ if (kp->type == RSPAMD_KEYPAIR_KEX) {
+ *len = 32;
+ return RSPAMD_CRYPTOBOX_KEYPAIR_25519(kp)->pk;
}
else {
- if (kp->type == RSPAMD_KEYPAIR_KEX) {
- *len = 65;
- return RSPAMD_CRYPTOBOX_KEYPAIR_NIST(kp)->pk;
- }
- else {
- *len = 65;
- return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_NIST(kp)->pk;
- }
+ *len = 32;
+ return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_25519(kp)->pk;
}
-
- /* Not reached */
- return NULL;
}
static void *
@@ -100,53 +70,27 @@ rspamd_cryptobox_pubkey_pk(const struct rspamd_cryptobox_pubkey *kp,
{
g_assert(kp != NULL);
- if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
- if (kp->type == RSPAMD_KEYPAIR_KEX) {
- *len = 32;
- return RSPAMD_CRYPTOBOX_PUBKEY_25519(kp)->pk;
- }
- else {
- *len = 32;
- return RSPAMD_CRYPTOBOX_PUBKEY_SIG_25519(kp)->pk;
- }
+ if (kp->type == RSPAMD_KEYPAIR_KEX) {
+ *len = 32;
+ return RSPAMD_CRYPTOBOX_PUBKEY_25519(kp)->pk;
}
else {
- if (kp->type == RSPAMD_KEYPAIR_KEX) {
- *len = 65;
- return RSPAMD_CRYPTOBOX_PUBKEY_NIST(kp)->pk;
- }
- else {
- *len = 65;
- return RSPAMD_CRYPTOBOX_PUBKEY_SIG_NIST(kp)->pk;
- }
+ *len = 32;
+ return RSPAMD_CRYPTOBOX_PUBKEY_SIG_25519(kp)->pk;
}
-
- /* Not reached */
- return NULL;
}
static struct rspamd_cryptobox_keypair *
-rspamd_cryptobox_keypair_alloc(enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg)
+rspamd_cryptobox_keypair_alloc(enum rspamd_cryptobox_keypair_type type)
{
struct rspamd_cryptobox_keypair *kp;
unsigned int size = 0;
- if (alg == RSPAMD_CRYPTOBOX_MODE_25519) {
- if (type == RSPAMD_KEYPAIR_KEX) {
- size = sizeof(struct rspamd_cryptobox_keypair_25519);
- }
- else {
- size = sizeof(struct rspamd_cryptobox_keypair_sig_25519);
- }
+ if (type == RSPAMD_KEYPAIR_KEX) {
+ size = sizeof(struct rspamd_cryptobox_keypair_25519);
}
else {
- if (type == RSPAMD_KEYPAIR_KEX) {
- size = sizeof(struct rspamd_cryptobox_keypair_nist);
- }
- else {
- size = sizeof(struct rspamd_cryptobox_keypair_sig_nist);
- }
+ size = sizeof(struct rspamd_cryptobox_keypair_sig_25519);
}
g_assert(size >= sizeof(*kp));
@@ -161,27 +105,17 @@ rspamd_cryptobox_keypair_alloc(enum rspamd_cryptobox_keypair_type type,
}
static struct rspamd_cryptobox_pubkey *
-rspamd_cryptobox_pubkey_alloc(enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg)
+rspamd_cryptobox_pubkey_alloc(enum rspamd_cryptobox_keypair_type type)
{
struct rspamd_cryptobox_pubkey *pk;
unsigned int size = 0;
- if (alg == RSPAMD_CRYPTOBOX_MODE_25519) {
- if (type == RSPAMD_KEYPAIR_KEX) {
- size = sizeof(struct rspamd_cryptobox_pubkey_25519);
- }
- else {
- size = sizeof(struct rspamd_cryptobox_pubkey_sig_25519);
- }
+
+ if (type == RSPAMD_KEYPAIR_KEX) {
+ size = sizeof(struct rspamd_cryptobox_pubkey_25519);
}
else {
- if (type == RSPAMD_KEYPAIR_KEX) {
- size = sizeof(struct rspamd_cryptobox_pubkey_nist);
- }
- else {
- size = sizeof(struct rspamd_cryptobox_pubkey_sig_nist);
- }
+ size = sizeof(struct rspamd_cryptobox_pubkey_sig_25519);
}
g_assert(size >= sizeof(*pk));
@@ -230,25 +164,23 @@ void rspamd_cryptobox_pubkey_dtor(struct rspamd_cryptobox_pubkey *p)
}
struct rspamd_cryptobox_keypair *
-rspamd_keypair_new(enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg)
+rspamd_keypair_new(enum rspamd_cryptobox_keypair_type type)
{
struct rspamd_cryptobox_keypair *kp;
void *pk, *sk;
unsigned int size;
- kp = rspamd_cryptobox_keypair_alloc(type, alg);
- kp->alg = alg;
+ kp = rspamd_cryptobox_keypair_alloc(type);
kp->type = type;
sk = rspamd_cryptobox_keypair_sk(kp, &size);
pk = rspamd_cryptobox_keypair_pk(kp, &size);
if (type == RSPAMD_KEYPAIR_KEX) {
- rspamd_cryptobox_keypair(pk, sk, alg);
+ rspamd_cryptobox_keypair(pk, sk);
}
else {
- rspamd_cryptobox_keypair_sig(pk, sk, alg);
+ rspamd_cryptobox_keypair_sig(pk, sk);
}
rspamd_cryptobox_hash(kp->id, pk, size, NULL, 0);
@@ -302,27 +234,10 @@ rspamd_pubkey_type(struct rspamd_cryptobox_pubkey *p)
}
-enum rspamd_cryptobox_mode
-rspamd_keypair_alg(struct rspamd_cryptobox_keypair *kp)
-{
- g_assert(kp != NULL);
-
- return kp->alg;
-}
-
-enum rspamd_cryptobox_mode
-rspamd_pubkey_alg(struct rspamd_cryptobox_pubkey *p)
-{
- g_assert(p != NULL);
-
- return p->alg;
-}
-
struct rspamd_cryptobox_pubkey *
rspamd_pubkey_from_base32(const char *b32,
gsize len,
- enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg)
+ enum rspamd_cryptobox_keypair_type type)
{
unsigned char *decoded;
gsize dlen, expected_len;
@@ -342,16 +257,15 @@ rspamd_pubkey_from_base32(const char *b32,
return NULL;
}
- expected_len = (type == RSPAMD_KEYPAIR_KEX) ? rspamd_cryptobox_pk_bytes(alg) : rspamd_cryptobox_pk_sig_bytes(alg);
+ expected_len = (type == RSPAMD_KEYPAIR_KEX) ? crypto_box_PUBLICKEYBYTES : crypto_sign_PUBLICKEYBYTES;
if (dlen != expected_len) {
g_free(decoded);
return NULL;
}
- pk = rspamd_cryptobox_pubkey_alloc(type, alg);
+ pk = rspamd_cryptobox_pubkey_alloc(type);
REF_INIT_RETAIN(pk, rspamd_cryptobox_pubkey_dtor);
- pk->alg = alg;
pk->type = type;
pk_data = rspamd_cryptobox_pubkey_pk(pk, &pklen);
@@ -365,8 +279,7 @@ rspamd_pubkey_from_base32(const char *b32,
struct rspamd_cryptobox_pubkey *
rspamd_pubkey_from_hex(const char *hex,
gsize len,
- enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg)
+ enum rspamd_cryptobox_keypair_type type)
{
unsigned char *decoded;
gsize dlen, expected_len;
@@ -388,16 +301,15 @@ rspamd_pubkey_from_hex(const char *hex,
return NULL;
}
- expected_len = (type == RSPAMD_KEYPAIR_KEX) ? rspamd_cryptobox_pk_bytes(alg) : rspamd_cryptobox_pk_sig_bytes(alg);
+ expected_len = (type == RSPAMD_KEYPAIR_KEX) ? crypto_box_PUBLICKEYBYTES : crypto_sign_PUBLICKEYBYTES;
if (dlen != expected_len) {
g_free(decoded);
return NULL;
}
- pk = rspamd_cryptobox_pubkey_alloc(type, alg);
+ pk = rspamd_cryptobox_pubkey_alloc(type);
REF_INIT_RETAIN(pk, rspamd_cryptobox_pubkey_dtor);
- pk->alg = alg;
pk->type = type;
pk_data = rspamd_cryptobox_pubkey_pk(pk, &pklen);
@@ -411,25 +323,20 @@ rspamd_pubkey_from_hex(const char *hex,
struct rspamd_cryptobox_pubkey *
rspamd_pubkey_from_bin(const unsigned char *raw,
gsize len,
- enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg)
+ enum rspamd_cryptobox_keypair_type type)
{
- gsize expected_len;
unsigned int pklen;
struct rspamd_cryptobox_pubkey *pk;
unsigned char *pk_data;
g_assert(raw != NULL && len > 0);
- expected_len = (type == RSPAMD_KEYPAIR_KEX) ? rspamd_cryptobox_pk_bytes(alg) : rspamd_cryptobox_pk_sig_bytes(alg);
-
- if (len != expected_len) {
+ if (len != crypto_box_PUBLICKEYBYTES) {
return NULL;
}
- pk = rspamd_cryptobox_pubkey_alloc(type, alg);
+ pk = rspamd_cryptobox_pubkey_alloc(type);
REF_INIT_RETAIN(pk, rspamd_cryptobox_pubkey_dtor);
- pk->alg = alg;
pk->type = type;
pk_data = rspamd_cryptobox_pubkey_pk(pk, &pklen);
@@ -463,7 +370,6 @@ const unsigned char *
rspamd_pubkey_calculate_nm(struct rspamd_cryptobox_pubkey *p,
struct rspamd_cryptobox_keypair *kp)
{
- g_assert(kp->alg == p->alg);
g_assert(kp->type == p->type);
g_assert(p->type == RSPAMD_KEYPAIR_KEX);
@@ -476,22 +382,12 @@ rspamd_pubkey_calculate_nm(struct rspamd_cryptobox_pubkey *p,
REF_INIT_RETAIN(p->nm, rspamd_cryptobox_nm_dtor);
}
- if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
- struct rspamd_cryptobox_pubkey_25519 *rk_25519 =
- RSPAMD_CRYPTOBOX_PUBKEY_25519(p);
- struct rspamd_cryptobox_keypair_25519 *sk_25519 =
- RSPAMD_CRYPTOBOX_KEYPAIR_25519(kp);
+ struct rspamd_cryptobox_pubkey_25519 *rk_25519 =
+ RSPAMD_CRYPTOBOX_PUBKEY_25519(p);
+ struct rspamd_cryptobox_keypair_25519 *sk_25519 =
+ RSPAMD_CRYPTOBOX_KEYPAIR_25519(kp);
- rspamd_cryptobox_nm(p->nm->nm, rk_25519->pk, sk_25519->sk, p->alg);
- }
- else {
- struct rspamd_cryptobox_pubkey_nist *rk_nist =
- RSPAMD_CRYPTOBOX_PUBKEY_NIST(p);
- struct rspamd_cryptobox_keypair_nist *sk_nist =
- RSPAMD_CRYPTOBOX_KEYPAIR_NIST(kp);
-
- rspamd_cryptobox_nm(p->nm->nm, rk_nist->pk, sk_nist->sk, p->alg);
- }
+ rspamd_cryptobox_nm(p->nm->nm, rk_25519->pk, sk_25519->sk);
return p->nm->nm;
}
@@ -662,7 +558,6 @@ rspamd_keypair_from_ucl(const ucl_object_t *obj)
const ucl_object_t *privkey, *pubkey, *elt;
const char *str;
enum rspamd_cryptobox_keypair_type type = RSPAMD_KEYPAIR_KEX;
- enum rspamd_cryptobox_mode mode = RSPAMD_CRYPTOBOX_MODE_25519;
gboolean is_hex = FALSE;
struct rspamd_cryptobox_keypair *kp;
unsigned int len;
@@ -705,19 +600,6 @@ rspamd_keypair_from_ucl(const ucl_object_t *obj)
/* TODO: handle errors */
}
- elt = ucl_object_lookup(obj, "algorithm");
- if (elt && ucl_object_type(elt) == UCL_STRING) {
- str = ucl_object_tostring(elt);
-
- if (g_ascii_strcasecmp(str, "curve25519") == 0) {
- mode = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else if (g_ascii_strcasecmp(str, "nistp256") == 0) {
- mode = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- /* TODO: handle errors */
- }
-
elt = ucl_object_lookup(obj, "encoding");
if (elt && ucl_object_type(elt) == UCL_STRING) {
str = ucl_object_tostring(elt);
@@ -728,9 +610,8 @@ rspamd_keypair_from_ucl(const ucl_object_t *obj)
/* TODO: handle errors */
}
- kp = rspamd_cryptobox_keypair_alloc(type, mode);
+ kp = rspamd_cryptobox_keypair_alloc(type);
kp->type = type;
- kp->alg = mode;
REF_INIT_RETAIN(kp, rspamd_cryptobox_keypair_dtor);
g_assert(kp != NULL);
@@ -838,8 +719,7 @@ rspamd_keypair_to_ucl(struct rspamd_cryptobox_keypair *kp,
"encoding", 0, false);
ucl_object_insert_key(elt,
- ucl_object_fromstring(
- kp->alg == RSPAMD_CRYPTOBOX_MODE_NIST ? "nistp256" : "curve25519"),
+ ucl_object_fromstring("curve25519"),
"algorithm", 0, false);
ucl_object_insert_key(elt,
@@ -873,9 +753,9 @@ rspamd_keypair_decrypt(struct rspamd_cryptobox_keypair *kp,
return FALSE;
}
- if (inlen < sizeof(encrypted_magic) + rspamd_cryptobox_pk_bytes(kp->alg) +
- rspamd_cryptobox_mac_bytes(kp->alg) +
- rspamd_cryptobox_nonce_bytes(kp->alg)) {
+ if (inlen < sizeof(encrypted_magic) + crypto_box_publickeybytes() +
+ crypto_box_macbytes() +
+ crypto_box_noncebytes()) {
g_set_error(err, rspamd_keypair_quark(), E2BIG, "invalid size: too small");
return FALSE;
@@ -890,9 +770,9 @@ rspamd_keypair_decrypt(struct rspamd_cryptobox_keypair *kp,
/* Set pointers */
pubkey = in + sizeof(encrypted_magic);
- mac = pubkey + rspamd_cryptobox_pk_bytes(kp->alg);
- nonce = mac + rspamd_cryptobox_mac_bytes(kp->alg);
- data = nonce + rspamd_cryptobox_nonce_bytes(kp->alg);
+ mac = pubkey + crypto_box_publickeybytes();
+ nonce = mac + crypto_box_macbytes();
+ data = nonce + crypto_box_noncebytes();
if (data - in >= inlen) {
g_set_error(err, rspamd_keypair_quark(), E2BIG, "invalid size: too small");
@@ -908,7 +788,7 @@ rspamd_keypair_decrypt(struct rspamd_cryptobox_keypair *kp,
if (!rspamd_cryptobox_decrypt_inplace(*out, inlen, nonce, pubkey,
rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL),
- mac, kp->alg)) {
+ mac)) {
g_set_error(err, rspamd_keypair_quark(), EPERM, "verification failed");
g_free(*out);
@@ -942,26 +822,26 @@ rspamd_keypair_encrypt(struct rspamd_cryptobox_keypair *kp,
return FALSE;
}
- local = rspamd_keypair_new(kp->type, kp->alg);
+ local = rspamd_keypair_new(kp->type);
olen = inlen + sizeof(encrypted_magic) +
- rspamd_cryptobox_pk_bytes(kp->alg) +
- rspamd_cryptobox_mac_bytes(kp->alg) +
- rspamd_cryptobox_nonce_bytes(kp->alg);
+ crypto_box_publickeybytes() +
+ crypto_box_macbytes() +
+ crypto_box_noncebytes();
*out = g_malloc(olen);
memcpy(*out, encrypted_magic, sizeof(encrypted_magic));
pubkey = *out + sizeof(encrypted_magic);
- mac = pubkey + rspamd_cryptobox_pk_bytes(kp->alg);
- nonce = mac + rspamd_cryptobox_mac_bytes(kp->alg);
- data = nonce + rspamd_cryptobox_nonce_bytes(kp->alg);
+ mac = pubkey + crypto_box_publickeybytes();
+ nonce = mac + crypto_box_macbytes();
+ data = nonce + crypto_box_noncebytes();
- ottery_rand_bytes(nonce, rspamd_cryptobox_nonce_bytes(kp->alg));
+ ottery_rand_bytes(nonce, crypto_box_noncebytes());
memcpy(data, in, inlen);
- memcpy(pubkey, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_PK, NULL),
- rspamd_cryptobox_pk_bytes(kp->alg));
- rspamd_cryptobox_encrypt_inplace(data, inlen, nonce, pubkey,
+ memcpy(pubkey, rspamd_keypair_component(local, RSPAMD_KEYPAIR_COMPONENT_PK, NULL),
+ crypto_box_publickeybytes());
+ rspamd_cryptobox_encrypt_inplace(data, inlen, nonce, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_PK, NULL),
rspamd_keypair_component(local, RSPAMD_KEYPAIR_COMPONENT_SK, NULL),
- mac, kp->alg);
+ mac);
rspamd_keypair_unref(local);
if (outlen) {
@@ -991,26 +871,26 @@ rspamd_pubkey_encrypt(struct rspamd_cryptobox_pubkey *pk,
return FALSE;
}
- local = rspamd_keypair_new(pk->type, pk->alg);
+ local = rspamd_keypair_new(pk->type);
olen = inlen + sizeof(encrypted_magic) +
- rspamd_cryptobox_pk_bytes(pk->alg) +
- rspamd_cryptobox_mac_bytes(pk->alg) +
- rspamd_cryptobox_nonce_bytes(pk->alg);
+ crypto_box_publickeybytes() +
+ crypto_box_macbytes() +
+ crypto_box_noncebytes();
*out = g_malloc(olen);
memcpy(*out, encrypted_magic, sizeof(encrypted_magic));
pubkey = *out + sizeof(encrypted_magic);
- mac = pubkey + rspamd_cryptobox_pk_bytes(pk->alg);
- nonce = mac + rspamd_cryptobox_mac_bytes(pk->alg);
- data = nonce + rspamd_cryptobox_nonce_bytes(pk->alg);
+ mac = pubkey + crypto_box_publickeybytes();
+ nonce = mac + crypto_box_macbytes();
+ data = nonce + crypto_box_noncebytes();
- ottery_rand_bytes(nonce, rspamd_cryptobox_nonce_bytes(pk->alg));
+ ottery_rand_bytes(nonce, crypto_box_noncebytes());
memcpy(data, in, inlen);
- memcpy(pubkey, rspamd_pubkey_get_pk(pk, NULL),
- rspamd_cryptobox_pk_bytes(pk->alg));
- rspamd_cryptobox_encrypt_inplace(data, inlen, nonce, pubkey,
+ memcpy(pubkey, rspamd_keypair_component(local, RSPAMD_KEYPAIR_COMPONENT_PK, NULL),
+ crypto_box_publickeybytes());
+ rspamd_cryptobox_encrypt_inplace(data, inlen, nonce, rspamd_pubkey_get_pk(pk, NULL),
rspamd_keypair_component(local, RSPAMD_KEYPAIR_COMPONENT_SK, NULL),
- mac, pk->alg);
+ mac);
rspamd_keypair_unref(local);
if (outlen) {
diff --git a/src/libcryptobox/keypair.h b/src/libcryptobox/keypair.h
index 849246255..97b46cbf5 100644
--- a/src/libcryptobox/keypair.h
+++ b/src/libcryptobox/keypair.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -50,8 +50,7 @@ struct rspamd_cryptobox_pubkey;
* @return fresh keypair generated
*/
struct rspamd_cryptobox_keypair *rspamd_keypair_new(
- enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg);
+ enum rspamd_cryptobox_keypair_type type);
/**
* Increase refcount for the specific keypair
@@ -84,8 +83,7 @@ struct rspamd_cryptobox_pubkey *rspamd_pubkey_ref(
*/
struct rspamd_cryptobox_pubkey *rspamd_pubkey_from_base32(const char *b32,
gsize len,
- enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg);
+ enum rspamd_cryptobox_keypair_type type);
/**
* Load pubkey from hex string
@@ -96,8 +94,7 @@ struct rspamd_cryptobox_pubkey *rspamd_pubkey_from_base32(const char *b32,
*/
struct rspamd_cryptobox_pubkey *rspamd_pubkey_from_hex(const char *hex,
gsize len,
- enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg);
+ enum rspamd_cryptobox_keypair_type type);
/**
* Load pubkey from raw chunk string
@@ -108,8 +105,7 @@ struct rspamd_cryptobox_pubkey *rspamd_pubkey_from_hex(const char *hex,
*/
struct rspamd_cryptobox_pubkey *rspamd_pubkey_from_bin(const unsigned char *raw,
gsize len,
- enum rspamd_cryptobox_keypair_type type,
- enum rspamd_cryptobox_mode alg);
+ enum rspamd_cryptobox_keypair_type type);
/**
@@ -127,18 +123,7 @@ enum rspamd_cryptobox_keypair_type rspamd_keypair_type(
/**
* Get type of pubkey
*/
-enum rspamd_cryptobox_keypair_type rspamd_pubkey_type(
- struct rspamd_cryptobox_pubkey *p);
-
-/**
- * Get algorithm of keypair
- */
-enum rspamd_cryptobox_mode rspamd_keypair_alg(struct rspamd_cryptobox_keypair *kp);
-
-/**
- * Get algorithm of pubkey
- */
-enum rspamd_cryptobox_mode rspamd_pubkey_alg(struct rspamd_cryptobox_pubkey *p);
+enum rspamd_cryptobox_keypair_type rspamd_pubkey_type(struct rspamd_cryptobox_pubkey *p);
/**
* Get cached NM for this specific pubkey
diff --git a/src/libcryptobox/keypair_private.h b/src/libcryptobox/keypair_private.h
index 793231701..2e372777c 100644
--- a/src/libcryptobox/keypair_private.h
+++ b/src/libcryptobox/keypair_private.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -38,22 +38,11 @@ struct rspamd_cryptobox_nm {
struct rspamd_cryptobox_keypair {
unsigned char id[rspamd_cryptobox_HASHBYTES];
enum rspamd_cryptobox_keypair_type type;
- enum rspamd_cryptobox_mode alg;
ucl_object_t *extensions;
ref_entry_t ref;
};
/*
- * NIST p256 ecdh keypair
- */
-#define RSPAMD_CRYPTOBOX_KEYPAIR_NIST(x) ((struct rspamd_cryptobox_keypair_nist *) (x))
-struct rspamd_cryptobox_keypair_nist {
- struct rspamd_cryptobox_keypair parent;
- unsigned char sk[32];
- unsigned char pk[65];
-};
-
-/*
* Curve25519 ecdh keypair
*/
#define RSPAMD_CRYPTOBOX_KEYPAIR_25519(x) ((struct rspamd_cryptobox_keypair_25519 *) (x))
@@ -64,16 +53,6 @@ struct rspamd_cryptobox_keypair_25519 {
};
/*
- * NIST p256 ecdsa keypair
- */
-#define RSPAMD_CRYPTOBOX_KEYPAIR_SIG_NIST(x) ((struct rspamd_cryptobox_keypair_sig_nist *) (x))
-struct rspamd_cryptobox_keypair_sig_nist {
- struct rspamd_cryptobox_keypair parent;
- unsigned char sk[32];
- unsigned char pk[65];
-};
-
-/*
* Ed25519 keypair
*/
#define RSPAMD_CRYPTOBOX_KEYPAIR_SIG_25519(x) ((struct rspamd_cryptobox_keypair_sig_25519 *) (x))
@@ -90,20 +69,10 @@ struct rspamd_cryptobox_pubkey {
unsigned char id[rspamd_cryptobox_HASHBYTES];
struct rspamd_cryptobox_nm *nm;
enum rspamd_cryptobox_keypair_type type;
- enum rspamd_cryptobox_mode alg;
ref_entry_t ref;
};
/*
- * Public p256 ecdh
- */
-#define RSPAMD_CRYPTOBOX_PUBKEY_NIST(x) ((struct rspamd_cryptobox_pubkey_nist *) (x))
-struct rspamd_cryptobox_pubkey_nist {
- struct rspamd_cryptobox_pubkey parent;
- unsigned char pk[65];
-};
-
-/*
* Public curve25519 ecdh
*/
#define RSPAMD_CRYPTOBOX_PUBKEY_25519(x) ((struct rspamd_cryptobox_pubkey_25519 *) (x))
@@ -113,15 +82,6 @@ struct rspamd_cryptobox_pubkey_25519 {
};
/*
- * Public p256 ecdsa
- */
-#define RSPAMD_CRYPTOBOX_PUBKEY_SIG_NIST(x) ((struct rspamd_cryptobox_pubkey_sig_nist *) (x))
-struct rspamd_cryptobox_pubkey_sig_nist {
- struct rspamd_cryptobox_pubkey parent;
- unsigned char pk[65];
-};
-
-/*
* Public ed25519
*/
#define RSPAMD_CRYPTOBOX_PUBKEY_SIG_25519(x) ((struct rspamd_cryptobox_pubkey_sig_25519 *) (x))
diff --git a/src/libcryptobox/keypairs_cache.c b/src/libcryptobox/keypairs_cache.c
index 6003d9923..0b069a64b 100644
--- a/src/libcryptobox/keypairs_cache.c
+++ b/src/libcryptobox/keypairs_cache.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -77,7 +77,6 @@ void rspamd_keypair_cache_process(struct rspamd_keypair_cache *c,
g_assert(lk != NULL);
g_assert(rk != NULL);
- g_assert(rk->alg == lk->alg);
g_assert(rk->type == lk->type);
g_assert(rk->type == RSPAMD_KEYPAIR_KEX);
@@ -106,22 +105,12 @@ void rspamd_keypair_cache_process(struct rspamd_keypair_cache *c,
rspamd_cryptobox_HASHBYTES);
memcpy(&new->nm->sk_id, lk->id, sizeof(uint64_t));
- if (rk->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
- struct rspamd_cryptobox_pubkey_25519 *rk_25519 =
- RSPAMD_CRYPTOBOX_PUBKEY_25519(rk);
- struct rspamd_cryptobox_keypair_25519 *sk_25519 =
- RSPAMD_CRYPTOBOX_KEYPAIR_25519(lk);
+ struct rspamd_cryptobox_pubkey_25519 *rk_25519 =
+ RSPAMD_CRYPTOBOX_PUBKEY_25519(rk);
+ struct rspamd_cryptobox_keypair_25519 *sk_25519 =
+ RSPAMD_CRYPTOBOX_KEYPAIR_25519(lk);
- rspamd_cryptobox_nm(new->nm->nm, rk_25519->pk, sk_25519->sk, rk->alg);
- }
- else {
- struct rspamd_cryptobox_pubkey_nist *rk_nist =
- RSPAMD_CRYPTOBOX_PUBKEY_NIST(rk);
- struct rspamd_cryptobox_keypair_nist *sk_nist =
- RSPAMD_CRYPTOBOX_KEYPAIR_NIST(lk);
-
- rspamd_cryptobox_nm(new->nm->nm, rk_nist->pk, sk_nist->sk, rk->alg);
- }
+ rspamd_cryptobox_nm(new->nm->nm, rk_25519->pk, sk_25519->sk);
rspamd_lru_hash_insert(c->hash, new, new, time(NULL), -1);
}
diff --git a/src/libmime/lang_detection.c b/src/libmime/lang_detection.c
index 4796e4834..6e180ea66 100644
--- a/src/libmime/lang_detection.c
+++ b/src/libmime/lang_detection.c
@@ -1828,7 +1828,7 @@ rspamd_language_detector_detect(struct rspamd_task *task,
unsigned int cand_len;
enum rspamd_language_category cat;
struct rspamd_lang_detector_res *cand;
- enum rspamd_language_detected_type r;
+ enum rspamd_language_detected_type r = rs_detect_none;
struct rspamd_frequency_sort_cbdata cbd;
/* Check if we have sorted candidates based on frequency */
gboolean frequency_heuristic_applied = FALSE, ret = FALSE, internal_heuristic_applied = FALSE;
diff --git a/src/libmime/scan_result.c b/src/libmime/scan_result.c
index f15290b95..894ae4f9e 100644
--- a/src/libmime/scan_result.c
+++ b/src/libmime/scan_result.c
@@ -201,16 +201,34 @@ rspamd_check_group_score(struct rspamd_task *task,
double *group_score,
double w)
{
- if (gr != NULL && group_score && gr->max_score > 0.0 && w > 0.0) {
- if (*group_score >= gr->max_score && w > 0) {
+ double group_limit = NAN;
+
+ if (gr != NULL && group_score) {
+ if ((*group_score + w) >= 0 && !isnan(gr->max_score) && gr->max_score > 0) {
+ group_limit = gr->max_score;
+ }
+ else if ((*group_score + w) < 0 && !isnan(gr->min_score) && gr->min_score < 0) {
+ group_limit = -gr->min_score;
+ }
+ }
+
+ if (gr != NULL && group_limit && !isnan(group_limit)) {
+ if (fabs(*group_score) >= group_limit && signbit(*group_score) == signbit(w)) {
+ /* Cannot add more to the group */
msg_info_task("maximum group score %.2f for group %s has been reached,"
" ignoring symbol %s with weight %.2f",
- gr->max_score,
+ group_limit,
gr->name, symbol, w);
return NAN;
}
- else if (*group_score + w > gr->max_score) {
- w = gr->max_score - *group_score;
+ else if (fabs(*group_score + w) > group_limit) {
+ /* Reduce weight */
+ double new_w = signbit(w) ? -group_limit - *group_score : group_limit - *group_score;
+ msg_info_task("maximum group score %.2f for group %s has been reached,"
+ " reduce weight of symbol %s from %.2f to %.2f",
+ group_limit,
+ gr->name, symbol, w, new_w);
+ w = new_w;
}
}
@@ -393,15 +411,7 @@ insert_metric_result(struct rspamd_task *task,
}
else if (gr_score) {
*gr_score += cur_diff;
-
- if (cur_diff < diff) {
- /* Reduce */
- msg_debug_metric(
- "group limit %.2f is reached for %s when inserting symbol %s;"
- " reduce score %.2f - %.2f",
- *gr_score, gr->name, symbol, diff, cur_diff);
- diff = cur_diff;
- }
+ diff = cur_diff;
}
}
}
@@ -461,15 +471,7 @@ insert_metric_result(struct rspamd_task *task,
}
else if (gr_score) {
*gr_score += cur_score;
-
- if (cur_score < final_score) {
- /* Reduce */
- msg_debug_metric(
- "group limit %.2f is reached for %s when inserting symbol %s;"
- " reduce score %.2f - %.2f",
- *gr_score, gr->name, symbol, final_score, cur_score);
- final_score = cur_score;
- }
+ final_score = cur_score;
}
}
}
diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index a963f952f..f59c6ff89 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -102,6 +102,7 @@ struct rspamd_symbols_group {
char *description;
GHashTable *symbols;
double max_score;
+ double min_score;
unsigned int flags;
};
diff --git a/src/libserver/cfg_rcl.cxx b/src/libserver/cfg_rcl.cxx
index 2fe37f18e..79509e12e 100644
--- a/src/libserver/cfg_rcl.cxx
+++ b/src/libserver/cfg_rcl.cxx
@@ -420,6 +420,18 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
return FALSE;
}
+ if (!std::isnan(gr->max_score) && gr->max_score < 0) {
+ msg_err_config("group %s has negative max_score which is broken, use min_score if required", gr->name);
+
+ return FALSE;
+ }
+ if (!std::isnan(gr->min_score) && gr->min_score > 0) {
+ msg_err_config("group %s has positive min_score which is broken, use max_score if required", gr->name);
+
+ return FALSE;
+ }
+
+
if (const auto *elt = ucl_object_lookup(obj, "one_shot"); elt != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
@@ -2355,6 +2367,12 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
G_STRUCT_OFFSET(struct rspamd_symbols_group, max_score),
0,
"Maximum score that could be reached by this symbols group");
+ rspamd_rcl_add_default_handler(sub,
+ "min_score",
+ rspamd_rcl_parse_struct_double,
+ G_STRUCT_OFFSET(struct rspamd_symbols_group, min_score),
+ 0,
+ "Maximum negative score that could be reached by this symbols group");
}
if (!(skip_sections && g_hash_table_lookup(skip_sections, "worker"))) {
@@ -3039,21 +3057,16 @@ rspamd_rcl_parse_struct_pubkey(rspamd_mempool_t *pool,
gsize len;
const char *str;
rspamd_cryptobox_keypair_type keypair_type = RSPAMD_KEYPAIR_KEX;
- rspamd_cryptobox_mode keypair_mode = RSPAMD_CRYPTOBOX_MODE_25519;
if (pd->flags & RSPAMD_CL_FLAG_SIGNKEY) {
keypair_type = RSPAMD_KEYPAIR_SIGN;
}
- if (pd->flags & RSPAMD_CL_FLAG_NISTKEY) {
- keypair_mode = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
target = (struct rspamd_cryptobox_pubkey **) (((char *) pd->user_struct) +
pd->offset);
if (obj->type == UCL_STRING) {
str = ucl_object_tolstring(obj, &len);
- pk = rspamd_pubkey_from_base32(str, len, keypair_type,
- keypair_mode);
+ pk = rspamd_pubkey_from_base32(str, len, keypair_type);
if (pk != nullptr) {
*target = pk;
@@ -3482,7 +3495,7 @@ void rspamd_rcl_maybe_apply_lua_transform(struct rspamd_config *cfg)
lua_pushvalue(L, -2);
/* Push the existing config */
- ucl_object_push_lua(L, cfg->cfg_ucl_obj, true);
+ ucl_object_push_lua_unwrapped(L, cfg->cfg_ucl_obj);
if (auto ret = lua_pcall(L, 1, 2, err_idx); ret != 0) {
msg_err("call to rspamadm lua script failed (%d): %s", ret,
@@ -3492,12 +3505,8 @@ void rspamd_rcl_maybe_apply_lua_transform(struct rspamd_config *cfg)
return;
}
- if (lua_toboolean(L, -2) && lua_type(L, -1) == LUA_TTABLE) {
- ucl_object_t *old_cfg = cfg->cfg_ucl_obj;
-
+ if (lua_toboolean(L, -2) && lua_type(L, -1) == LUA_TUSERDATA) {
msg_info_config("configuration has been transformed in Lua");
- cfg->cfg_ucl_obj = ucl_object_lua_import(L, -1);
- ucl_object_unref(old_cfg);
}
/* error function */
@@ -3629,7 +3638,8 @@ rspamd_config_parse_ucl(struct rspamd_config *cfg,
auto &cfg_file = cfg_file_maybe.value();
/* Try to load keyfile if available */
- rspamd::util::raii_file::open(fmt::format("{}.key", filename), O_RDONLY).map([&](const auto &keyfile) {
+ auto keyfile_name = fmt::format("{}.key", filename);
+ rspamd::util::raii_file::open(keyfile_name, O_RDONLY).map([&](const auto &keyfile) {
auto *kp_parser = ucl_parser_new(0);
if (ucl_parser_add_fd(kp_parser, keyfile.get_fd())) {
auto *kp_obj = ucl_parser_get_object(kp_parser);
@@ -3638,8 +3648,8 @@ rspamd_config_parse_ucl(struct rspamd_config *cfg,
decrypt_keypair = rspamd_keypair_from_ucl(kp_obj);
if (decrypt_keypair == nullptr) {
- msg_err_config_forced("cannot load keypair from %s.key: invalid keypair",
- filename);
+ msg_err_config_forced("cannot load keypair from %s: invalid keypair",
+ keyfile_name.c_str());
}
else {
/* Add decryption support to UCL */
@@ -3651,8 +3661,8 @@ rspamd_config_parse_ucl(struct rspamd_config *cfg,
ucl_object_unref(kp_obj);
}
else {
- msg_err_config_forced("cannot load keypair from %s.key: %s",
- filename, ucl_parser_get_error(kp_parser));
+ msg_err_config_forced("cannot load keypair from %s: %s",
+ keyfile_name.c_str(), ucl_parser_get_error(kp_parser));
}
ucl_parser_free(kp_parser);
});
diff --git a/src/libserver/cfg_rcl.h b/src/libserver/cfg_rcl.h
index e33656b72..35b9b931f 100644
--- a/src/libserver/cfg_rcl.h
+++ b/src/libserver/cfg_rcl.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Vsevolod Stakhov
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,7 +53,6 @@ enum rspamd_rcl_flag {
RSPAMD_CL_FLAG_STRING_LIST_HASH = 0x1 << 12,
RSPAMD_CL_FLAG_MULTIPLE = 0x1 << 13,
RSPAMD_CL_FLAG_SIGNKEY = 0x1 << 14,
- RSPAMD_CL_FLAG_NISTKEY = 0x1 << 15,
};
struct rspamd_rcl_struct_parser {
diff --git a/src/libserver/cfg_utils.cxx b/src/libserver/cfg_utils.cxx
index f17caa8a5..38adf8390 100644
--- a/src/libserver/cfg_utils.cxx
+++ b/src/libserver/cfg_utils.cxx
@@ -1053,6 +1053,8 @@ rspamd_config_new_group(struct rspamd_config *cfg, const char *name)
rspamd_mempool_add_destructor(cfg->cfg_pool,
(rspamd_mempool_destruct_t) g_hash_table_unref, gr->symbols);
gr->name = rspamd_mempool_strdup(cfg->cfg_pool, name);
+ gr->max_score = NAN;
+ gr->min_score = NAN;
if (strcmp(gr->name, "ungrouped") == 0) {
gr->flags |= RSPAMD_SYMBOL_GROUP_UNGROUPED;
diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c
index 742e4db8b..a76ed31ab 100644
--- a/src/libserver/dkim.c
+++ b/src/libserver/dkim.c
@@ -155,12 +155,12 @@ struct rspamd_dkim_key_s {
gsize decoded_len;
char key_id[RSPAMD_DKIM_KEY_ID_LEN];
union {
- RSA *key_rsa;
- EC_KEY *key_ecdsa;
unsigned char *key_eddsa;
- } key;
- BIO *key_bio;
- EVP_PKEY *key_evp;
+ struct {
+ BIO *key_bio;
+ EVP_PKEY *key_evp;
+ } key_ssl;
+ } specific;
time_t mtime;
unsigned int ttl;
enum rspamd_dkim_key_type type;
@@ -790,12 +790,12 @@ rspamd_dkim_add_arc_seal_headers(rspamd_mempool_t *pool,
}
/**
- * Create new dkim context from signature
- * @param sig message's signature
- * @param pool pool to allocate memory from
- * @param err pointer to error object
- * @return new context or NULL
- */
+* Create new dkim context from signature
+* @param sig message's signature
+* @param pool pool to allocate memory from
+* @param err pointer to error object
+* @return new context or NULL
+*/
rspamd_dkim_context_t *
rspamd_create_dkim_context(const char *sig,
rspamd_mempool_t *pool,
@@ -1097,9 +1097,9 @@ rspamd_create_dkim_context(const char *sig,
if (state == DKIM_STATE_ERROR) {
/*
- * We need to return from here as state machine won't
- * do any more steps after p == end
- */
+ * We need to return from here as state machine won't
+ * do any more steps after p == end
+ */
if (err) {
msg_info_dkim("dkim parse failed: %e", *err);
}
@@ -1391,25 +1391,24 @@ rspamd_dkim_make_key(const char *keydata,
EVP_MD_CTX_destroy(mdctx);
if (key->type == RSPAMD_DKIM_KEY_EDDSA) {
- key->key.key_eddsa = key->keydata;
+ key->specific.key_eddsa = key->keydata;
- if (key->decoded_len != rspamd_cryptobox_pk_sig_bytes(
- RSPAMD_CRYPTOBOX_MODE_25519)) {
+ if (key->decoded_len != crypto_sign_publickeybytes()) {
g_set_error(err,
DKIM_ERROR,
DKIM_SIGERROR_KEYFAIL,
- "DKIM key is has invalid length %d for eddsa; expected %d",
+ "DKIM key is has invalid length %d for eddsa; expected %zd",
(int) key->decoded_len,
- rspamd_cryptobox_pk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519));
+ crypto_sign_publickeybytes());
REF_RELEASE(key);
return NULL;
}
}
else {
- key->key_bio = BIO_new_mem_buf(key->keydata, key->decoded_len);
+ key->specific.key_ssl.key_bio = BIO_new_mem_buf(key->keydata, key->decoded_len);
- if (key->key_bio == NULL) {
+ if (key->specific.key_ssl.key_bio == NULL) {
g_set_error(err,
DKIM_ERROR,
DKIM_SIGERROR_KEYFAIL,
@@ -1419,9 +1418,9 @@ rspamd_dkim_make_key(const char *keydata,
return NULL;
}
- key->key_evp = d2i_PUBKEY_bio(key->key_bio, NULL);
+ key->specific.key_ssl.key_evp = d2i_PUBKEY_bio(key->specific.key_ssl.key_bio, NULL);
- if (key->key_evp == NULL) {
+ if (key->specific.key_ssl.key_evp == NULL) {
g_set_error(err,
DKIM_ERROR,
DKIM_SIGERROR_KEYFAIL,
@@ -1430,33 +1429,6 @@ rspamd_dkim_make_key(const char *keydata,
return NULL;
}
-
- if (type == RSPAMD_DKIM_KEY_RSA) {
- key->key.key_rsa = EVP_PKEY_get1_RSA(key->key_evp);
-
- if (key->key.key_rsa == NULL) {
- g_set_error(err,
- DKIM_ERROR,
- DKIM_SIGERROR_KEYFAIL,
- "cannot extract rsa key from evp key");
- REF_RELEASE(key);
-
- return NULL;
- }
- }
- else {
- key->key.key_ecdsa = EVP_PKEY_get1_EC_KEY(key->key_evp);
-
- if (key->key.key_ecdsa == NULL) {
- g_set_error(err,
- DKIM_ERROR,
- DKIM_SIGERROR_KEYFAIL,
- "cannot extract ecdsa key from evp key");
- REF_RELEASE(key);
-
- return NULL;
- }
- }
}
return key;
@@ -1473,29 +1445,19 @@ rspamd_dkim_key_id(rspamd_dkim_key_t *key)
}
/**
- * Free DKIM key
- * @param key
- */
+* Free DKIM key
+* @param key
+*/
void rspamd_dkim_key_free(rspamd_dkim_key_t *key)
{
- if (key->key_evp) {
- EVP_PKEY_free(key->key_evp);
- }
-
- if (key->type == RSPAMD_DKIM_KEY_RSA) {
- if (key->key.key_rsa) {
- RSA_free(key->key.key_rsa);
+ if (key->type != RSPAMD_DKIM_KEY_EDDSA) {
+ if (key->specific.key_ssl.key_evp) {
+ EVP_PKEY_free(key->specific.key_ssl.key_evp);
}
- }
- else if (key->type == RSPAMD_DKIM_KEY_ECDSA) {
- if (key->key.key_ecdsa) {
- EC_KEY_free(key->key.key_ecdsa);
+ if (key->specific.key_ssl.key_bio) {
+ BIO_free(key->specific.key_ssl.key_bio);
}
}
- /* Nothing in case of eddsa key */
- if (key->key_bio) {
- BIO_free(key->key_bio);
- }
g_free(key->raw_key);
g_free(key->keydata);
@@ -1504,20 +1466,16 @@ void rspamd_dkim_key_free(rspamd_dkim_key_t *key)
void rspamd_dkim_sign_key_free(rspamd_dkim_sign_key_t *key)
{
- if (key->key_evp) {
- EVP_PKEY_free(key->key_evp);
- }
- if (key->type == RSPAMD_DKIM_KEY_RSA) {
- if (key->key.key_rsa) {
- RSA_free(key->key.key_rsa);
+ if (key->type != RSPAMD_DKIM_KEY_EDDSA) {
+ if (key->specific.key_ssl.key_evp) {
+ EVP_PKEY_free(key->specific.key_ssl.key_evp);
+ }
+ if (key->specific.key_ssl.key_bio) {
+ BIO_free(key->specific.key_ssl.key_bio);
}
}
- if (key->key_bio) {
- BIO_free(key->key_bio);
- }
-
- if (key->type == RSPAMD_DKIM_KEY_EDDSA) {
- rspamd_explicit_memzero(key->key.key_eddsa, key->keylen);
+ else {
+ rspamd_explicit_memzero(key->specific.key_eddsa, key->keylen);
g_free(key->keydata);
}
@@ -1570,9 +1528,9 @@ rspamd_dkim_parse_key(const char *txt, gsize *keylen, GError **err)
break;
case read_tag_before_eqsign:
/* Input: spaces before eqsign
- * Output: either read a next tag (previous had no value), or read value
- * p is moved forward
- */
+ * Output: either read a next tag (previous had no value), or read value
+ * p is moved forward
+ */
if (*p == '=') {
state = read_eqsign;
}
@@ -1759,12 +1717,12 @@ rspamd_dkim_dns_cb(struct rdns_reply *reply, gpointer arg)
}
/**
- * Make DNS request for specified context and obtain and parse key
- * @param ctx dkim context from signature
- * @param resolver dns resolver object
- * @param s async session to make request
- * @return
- */
+* Make DNS request for specified context and obtain and parse key
+* @param ctx dkim context from signature
+* @param resolver dns resolver object
+* @param s async session to make request
+* @return
+*/
gboolean
rspamd_get_dkim_key(rspamd_dkim_context_t *ctx,
struct rspamd_task *task,
@@ -2187,8 +2145,8 @@ rspamd_dkim_canonize_body(struct rspamd_task *task,
;
/*
- * If we have l= tag then we cannot add crlf...
- */
+ * If we have l= tag then we cannot add crlf...
+ */
if (need_crlf) {
/* l is evil... */
if (ctx->len == 0) {
@@ -2241,7 +2199,6 @@ rspamd_dkim_canonize_body(struct rspamd_task *task,
return TRUE;
}
- /* TODO: Implement relaxed algorithm */
return FALSE;
}
@@ -2461,9 +2418,9 @@ rspamd_dkim_canonize_header(struct rspamd_dkim_common_ctx *ctx,
bool use_idx = false, is_sign = ctx->is_sign;
/*
- * TODO:
- * Temporary hack to prevent linked list being misused until refactored
- */
+ * TODO:
+ * Temporary hack to prevent linked list being misused until refactored
+ */
const unsigned int max_list_iters = 1000;
if (count < 0) {
@@ -2509,17 +2466,17 @@ rspamd_dkim_canonize_header(struct rspamd_dkim_common_ctx *ctx,
if (hdr_cnt <= count) {
/*
- * If DKIM has less headers requested than there are in a
- * message, then it's fine, it allows adding extra headers
- */
+ * If DKIM has less headers requested than there are in a
+ * message, then it's fine, it allows adding extra headers
+ */
return TRUE;
}
}
else {
/*
- * This branch is used for ARC headers, and it orders them based on
- * i=<number> string and not their real order in the list of headers
- */
+ * This branch is used for ARC headers, and it orders them based on
+ * i=<number> string and not their real order in the list of headers
+ */
char idx_buf[16];
int id_len, i;
@@ -2692,12 +2649,12 @@ rspamd_dkim_type_to_string(enum rspamd_dkim_type t)
}
/**
- * Check task for dkim context using dkim key
- * @param ctx dkim verify context
- * @param key dkim key (from cache or from dns request)
- * @param task task to check
- * @return
- */
+* Check task for dkim context using dkim key
+* @param ctx dkim verify context
+* @param key dkim key (from cache or from dns request)
+* @param task task to check
+* @return
+*/
struct rspamd_dkim_check_result *
rspamd_dkim_check(rspamd_dkim_context_t *ctx,
rspamd_dkim_key_t *key,
@@ -2913,11 +2870,10 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx,
/* Not reached */
nid = NID_sha1;
}
-
switch (key->type) {
case RSPAMD_DKIM_KEY_RSA:
- if (RSA_verify(nid, raw_digest, dlen, ctx->b, ctx->blen,
- key->key.key_rsa) != 1) {
+ if (!rspamd_cryptobox_verify_evp_rsa(nid, ctx->b, ctx->blen, raw_digest, dlen,
+ key->specific.key_ssl.key_evp)) {
msg_debug_dkim("headers rsa verify failed");
ERR_clear_error();
res->rcode = DKIM_REJECT;
@@ -2935,8 +2891,8 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx,
}
break;
case RSPAMD_DKIM_KEY_ECDSA:
- if (ECDSA_verify(nid, raw_digest, dlen, ctx->b, ctx->blen,
- key->key.key_ecdsa) != 1) {
+ if (rspamd_cryptobox_verify_evp_ecdsa(nid, ctx->b, ctx->blen, raw_digest, dlen,
+ key->specific.key_ssl.key_evp) != 1) {
msg_info_dkim(
"%s: headers ECDSA verification failure; "
"body length %d->%d; headers length %d; d=%s; s=%s; key_md5=%*xs; orig header: %s",
@@ -2952,9 +2908,10 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx,
res->fail_reason = "headers ecdsa verify failed";
}
break;
+
case RSPAMD_DKIM_KEY_EDDSA:
if (!rspamd_cryptobox_verify(ctx->b, ctx->blen, raw_digest, dlen,
- key->key.key_eddsa, RSPAMD_CRYPTOBOX_MODE_25519)) {
+ key->specific.key_eddsa)) {
msg_info_dkim(
"%s: headers EDDSA verification failure; "
"body length %d->%d; headers length %d; d=%s; s=%s; key_md5=%*xs; orig header: %s",
@@ -3155,30 +3112,29 @@ rspamd_dkim_sign_key_load(const char *key, gsize len,
}
if (type == RSPAMD_DKIM_KEY_RAW && (len == 32 ||
- len == rspamd_cryptobox_sk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519))) {
+ len == crypto_sign_secretkeybytes())) {
if (len == 32) {
/* Seeded key, need scalarmult */
unsigned char pk[32];
nkey->type = RSPAMD_DKIM_KEY_EDDSA;
- nkey->key.key_eddsa = g_malloc(
- rspamd_cryptobox_sk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519));
- crypto_sign_ed25519_seed_keypair(pk, nkey->key.key_eddsa, key);
- nkey->keylen = rspamd_cryptobox_sk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519);
+ nkey->specific.key_eddsa = g_malloc(crypto_sign_secretkeybytes());
+ crypto_sign_ed25519_seed_keypair(pk, nkey->specific.key_eddsa, key);
+ nkey->keylen = crypto_sign_secretkeybytes();
}
else {
/* Full ed25519 key */
- unsigned klen = rspamd_cryptobox_sk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519);
+ unsigned klen = crypto_sign_secretkeybytes();
nkey->type = RSPAMD_DKIM_KEY_EDDSA;
- nkey->key.key_eddsa = g_malloc(klen);
- memcpy(nkey->key.key_eddsa, key, klen);
+ nkey->specific.key_eddsa = g_malloc(klen);
+ memcpy(nkey->specific.key_eddsa, key, klen);
nkey->keylen = klen;
}
}
else {
- nkey->key_bio = BIO_new_mem_buf(key, len);
+ nkey->specific.key_ssl.key_bio = BIO_new_mem_buf(key, len);
if (type == RSPAMD_DKIM_KEY_RAW) {
- if (d2i_PrivateKey_bio(nkey->key_bio, &nkey->key_evp) == NULL) {
+ if (d2i_PrivateKey_bio(nkey->specific.key_ssl.key_bio, &nkey->specific.key_ssl.key_evp) == NULL) {
g_set_error(err, dkim_error_quark(), DKIM_SIGERROR_KEYFAIL,
"cannot parse raw private key: %s",
ERR_error_string(ERR_get_error(), NULL));
@@ -3190,7 +3146,7 @@ rspamd_dkim_sign_key_load(const char *key, gsize len,
}
}
else {
- if (!PEM_read_bio_PrivateKey(nkey->key_bio, &nkey->key_evp, NULL, NULL)) {
+ if (!PEM_read_bio_PrivateKey(nkey->specific.key_ssl.key_bio, &nkey->specific.key_ssl.key_evp, NULL, NULL)) {
g_set_error(err, dkim_error_quark(), DKIM_SIGERROR_KEYFAIL,
"cannot parse pem private key: %s",
ERR_error_string(ERR_get_error(), NULL));
@@ -3200,18 +3156,6 @@ rspamd_dkim_sign_key_load(const char *key, gsize len,
goto end;
}
}
- nkey->key.key_rsa = EVP_PKEY_get1_RSA(nkey->key_evp);
- if (nkey->key.key_rsa == NULL) {
- g_set_error(err,
- DKIM_ERROR,
- DKIM_SIGERROR_KEYFAIL,
- "cannot extract rsa key from evp key");
- rspamd_dkim_sign_key_free(nkey);
- nkey = NULL;
-
- goto end;
- }
- nkey->type = RSPAMD_DKIM_KEY_RSA;
}
REF_INIT_RETAIN(nkey, rspamd_dkim_sign_key_free);
@@ -3269,7 +3213,7 @@ rspamd_create_dkim_sign_context(struct rspamd_task *task,
return NULL;
}
- if (!priv_key || (!priv_key->key.key_rsa && !priv_key->key.key_eddsa)) {
+ if (!priv_key) {
g_set_error(err,
DKIM_ERROR,
DKIM_SIGERROR_KEYFAIL,
@@ -3536,12 +3480,34 @@ rspamd_dkim_sign(struct rspamd_task *task, const char *selector,
dlen = EVP_MD_CTX_size(ctx->common.headers_hash);
EVP_DigestFinal_ex(ctx->common.headers_hash, raw_digest, NULL);
+
if (ctx->key->type == RSPAMD_DKIM_KEY_RSA) {
- sig_len = RSA_size(ctx->key->key.key_rsa);
+ sig_len = EVP_PKEY_size(ctx->key->specific.key_ssl.key_evp);
sig_buf = g_alloca(sig_len);
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ctx->key->specific.key_ssl.key_evp, NULL);
+ if (EVP_PKEY_sign_init(pctx) <= 0) {
+ g_string_free(hdr, TRUE);
+ msg_err_task("rsa sign error: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+
+ return NULL;
+ }
+ if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) <= 0) {
+ g_string_free(hdr, TRUE);
+ msg_err_task("rsa sign error: %s",
+ ERR_error_string(ERR_get_error(), NULL));
- if (RSA_sign(NID_sha256, raw_digest, dlen, sig_buf, &sig_len,
- ctx->key->key.key_rsa) != 1) {
+ return NULL;
+ }
+ if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha256()) <= 0) {
+ g_string_free(hdr, TRUE);
+ msg_err_task("rsa sign error: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+
+ return NULL;
+ }
+ size_t sig_len_size_t = sig_len;
+ if (EVP_PKEY_sign(pctx, sig_buf, &sig_len_size_t, raw_digest, dlen) <= 0) {
g_string_free(hdr, TRUE);
msg_err_task("rsa sign error: %s",
ERR_error_string(ERR_get_error(), NULL));
@@ -3550,11 +3516,10 @@ rspamd_dkim_sign(struct rspamd_task *task, const char *selector,
}
}
else if (ctx->key->type == RSPAMD_DKIM_KEY_EDDSA) {
- sig_len = rspamd_cryptobox_signature_bytes(RSPAMD_CRYPTOBOX_MODE_25519);
+ sig_len = crypto_sign_bytes();
sig_buf = g_alloca(sig_len);
- rspamd_cryptobox_sign(sig_buf, NULL, raw_digest, dlen,
- ctx->key->key.key_eddsa, RSPAMD_CRYPTOBOX_MODE_25519);
+ rspamd_cryptobox_sign(sig_buf, NULL, raw_digest, dlen, ctx->key->specific.key_eddsa);
}
else {
g_string_free(hdr, TRUE);
@@ -3595,17 +3560,25 @@ rspamd_dkim_match_keys(rspamd_dkim_key_t *pk,
}
if (pk->type == RSPAMD_DKIM_KEY_EDDSA) {
- if (memcmp(sk->key.key_eddsa + 32, pk->key.key_eddsa, 32) != 0) {
+ if (memcmp(sk->specific.key_eddsa + 32, pk->specific.key_eddsa, 32) != 0) {
g_set_error(err, dkim_error_quark(), DKIM_SIGERROR_KEYHASHMISMATCH,
"pubkey does not match private key");
return FALSE;
}
}
- else if (EVP_PKEY_cmp(pk->key_evp, sk->key_evp) != 1) {
+#if OPENSSL_VERSION_MAJOR >= 3
+ else if (EVP_PKEY_eq(pk->specific.key_ssl.key_evp, sk->specific.key_ssl.key_evp) != 1) {
g_set_error(err, dkim_error_quark(), DKIM_SIGERROR_KEYHASHMISMATCH,
"pubkey does not match private key");
return FALSE;
}
+#else
+ else if (EVP_PKEY_cmp(pk->specific.key_ssl.key_evp, sk->specific.key_ssl.key_evp) != 1) {
+ g_set_error(err, dkim_error_quark(), DKIM_SIGERROR_KEYHASHMISMATCH,
+ "pubkey does not match private key");
+ return FALSE;
+ }
+#endif
return TRUE;
}
diff --git a/src/libserver/http/http_connection.c b/src/libserver/http/http_connection.c
index ef39e11e7..1ae9bb034 100644
--- a/src/libserver/http/http_connection.c
+++ b/src/libserver/http/http_connection.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -159,8 +159,7 @@ rspamd_http_parse_key(rspamd_ftok_t *data, struct rspamd_http_connection *conn,
if (decoded_id != NULL && id_len >= RSPAMD_KEYPAIR_SHORT_ID_LEN) {
pk = rspamd_pubkey_from_base32(eq_pos + 1,
data->begin + data->len - eq_pos - 1,
- RSPAMD_KEYPAIR_KEX,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ RSPAMD_KEYPAIR_KEX);
if (pk != NULL) {
if (memcmp(rspamd_keypair_get_id(priv->local_key),
decoded_id,
@@ -572,21 +571,18 @@ rspamd_http_decrypt_message(struct rspamd_http_connection *conn,
struct rspamd_http_header *hdr, *hcur, *hcurtmp;
struct http_parser decrypted_parser;
struct http_parser_settings decrypted_cb;
- enum rspamd_cryptobox_mode mode;
- mode = rspamd_keypair_alg(priv->local_key);
nonce = msg->body_buf.str;
- m = msg->body_buf.str + rspamd_cryptobox_nonce_bytes(mode) +
- rspamd_cryptobox_mac_bytes(mode);
- dec_len = msg->body_buf.len - rspamd_cryptobox_nonce_bytes(mode) -
- rspamd_cryptobox_mac_bytes(mode);
+ m = msg->body_buf.str + crypto_box_noncebytes() +
+ crypto_box_macbytes();
+ dec_len = msg->body_buf.len - crypto_box_noncebytes() - crypto_box_macbytes();
if ((nm = rspamd_pubkey_get_nm(peer_key, priv->local_key)) == NULL) {
nm = rspamd_pubkey_calculate_nm(peer_key, priv->local_key);
}
if (!rspamd_cryptobox_decrypt_nm_inplace(m, dec_len, nonce,
- nm, m - rspamd_cryptobox_mac_bytes(mode), mode)) {
+ nm, m - crypto_box_macbytes())) {
msg_err("cannot verify encrypted message, first bytes of the input: %*xs",
(int) MIN(msg->body_buf.len, 64), msg->body_buf.begin);
return -1;
@@ -640,7 +636,6 @@ rspamd_http_on_message_complete(http_parser *parser)
(struct rspamd_http_connection *) parser->data;
struct rspamd_http_connection_private *priv;
int ret = 0;
- enum rspamd_cryptobox_mode mode;
if (conn->finished) {
return 0;
@@ -655,11 +650,10 @@ rspamd_http_on_message_complete(http_parser *parser)
}
if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) == 0 && IS_CONN_ENCRYPTED(priv)) {
- mode = rspamd_keypair_alg(priv->local_key);
if (priv->local_key == NULL || priv->msg->peer_key == NULL ||
- priv->msg->body_buf.len < rspamd_cryptobox_nonce_bytes(mode) +
- rspamd_cryptobox_mac_bytes(mode)) {
+ priv->msg->body_buf.len < crypto_box_noncebytes() +
+ crypto_box_macbytes()) {
msg_err("cannot decrypt message");
return -1;
}
@@ -1576,10 +1570,8 @@ rspamd_http_connection_encrypt_message(
int i, cnt;
unsigned int outlen;
struct rspamd_http_header *hdr, *hcur;
- enum rspamd_cryptobox_mode mode;
- mode = rspamd_keypair_alg(priv->local_key);
- crlfp = mp + rspamd_cryptobox_mac_bytes(mode);
+ crlfp = mp + crypto_box_macbytes();
outlen = priv->out[0].iov_len + priv->out[1].iov_len;
/*
@@ -1632,7 +1624,7 @@ if ((nm = rspamd_pubkey_get_nm(peer_key, priv->local_key)) == NULL) {
nm = rspamd_pubkey_calculate_nm(peer_key, priv->local_key);
}
-rspamd_cryptobox_encryptv_nm_inplace(segments, cnt, np, nm, mp, mode);
+rspamd_cryptobox_encryptv_nm_inplace(segments, cnt, np, nm, mp);
/*
* iov[0] = base HTTP request
@@ -1642,12 +1634,12 @@ rspamd_cryptobox_encryptv_nm_inplace(segments, cnt, np, nm, mp, mode);
* iov[4..i] = encrypted HTTP request/reply
*/
priv->out[2].iov_base = np;
-priv->out[2].iov_len = rspamd_cryptobox_nonce_bytes(mode);
+priv->out[2].iov_len = crypto_box_noncebytes();
priv->out[3].iov_base = mp;
-priv->out[3].iov_len = rspamd_cryptobox_mac_bytes(mode);
+priv->out[3].iov_len = crypto_box_macbytes();
-outlen += rspamd_cryptobox_nonce_bytes(mode) +
- rspamd_cryptobox_mac_bytes(mode);
+outlen += crypto_box_noncebytes() +
+ crypto_box_macbytes();
for (i = 0; i < cnt; i++) {
priv->out[i + 4].iov_base = segments[i].data;
@@ -2027,7 +2019,6 @@ rspamd_http_connection_write_message_common(struct rspamd_http_connection *conn,
unsigned char nonce[rspamd_cryptobox_MAX_NONCEBYTES], mac[rspamd_cryptobox_MAX_MACBYTES];
unsigned char *np = NULL, *mp = NULL, *meth_pos = NULL;
struct rspamd_cryptobox_pubkey *peer_key = NULL;
- enum rspamd_cryptobox_mode mode;
GError *err;
conn->ud = ud;
@@ -2059,8 +2050,7 @@ rspamd_http_connection_write_message_common(struct rspamd_http_connection *conn,
if (msg->peer_key != NULL) {
if (priv->local_key == NULL) {
/* Automatically generate a temporary keypair */
- priv->local_key = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ priv->local_key = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX);
}
encrypted = TRUE;
@@ -2128,8 +2118,6 @@ rspamd_http_connection_write_message_common(struct rspamd_http_connection *conn,
}
if (encrypted) {
- mode = rspamd_keypair_alg(priv->local_key);
-
if (msg->body_buf.len == 0) {
pbody = NULL;
bodylen = 0;
@@ -2154,8 +2142,8 @@ rspamd_http_connection_write_message_common(struct rspamd_http_connection *conn,
* [iov[n + 2] = encrypted body]
*/
priv->outlen = 7;
- enclen = rspamd_cryptobox_nonce_bytes(mode) +
- rspamd_cryptobox_mac_bytes(mode) +
+ enclen = crypto_box_noncebytes() +
+ crypto_box_macbytes() +
4 + /* 2 * CRLF */
bodylen;
}
@@ -2197,8 +2185,8 @@ rspamd_http_connection_write_message_common(struct rspamd_http_connection *conn,
ENCRYPTED_VERSION);
}
- enclen = rspamd_cryptobox_nonce_bytes(mode) +
- rspamd_cryptobox_mac_bytes(mode) +
+ enclen = crypto_box_noncebytes() +
+ crypto_box_macbytes() +
preludelen + /* version [content-length] + 2 * CRLF */
bodylen;
}
@@ -2275,10 +2263,9 @@ priv->out[0].iov_len = buf->len;
/* Buf will be used eventually for encryption */
if (encrypted) {
int meth_offset, nonce_offset, mac_offset;
- mode = rspamd_keypair_alg(priv->local_key);
- ottery_rand_bytes(nonce, rspamd_cryptobox_nonce_bytes(mode));
- memset(mac, 0, rspamd_cryptobox_mac_bytes(mode));
+ ottery_rand_bytes(nonce, crypto_box_noncebytes());
+ memset(mac, 0, crypto_box_macbytes());
meth_offset = buf->len;
if (conn->type == RSPAMD_HTTP_SERVER) {
@@ -2292,11 +2279,9 @@ if (encrypted) {
}
nonce_offset = buf->len;
- buf = rspamd_fstring_append(buf, nonce,
- rspamd_cryptobox_nonce_bytes(mode));
+ buf = rspamd_fstring_append(buf, nonce, crypto_box_noncebytes());
mac_offset = buf->len;
- buf = rspamd_fstring_append(buf, mac,
- rspamd_cryptobox_mac_bytes(mode));
+ buf = rspamd_fstring_append(buf, mac, crypto_box_macbytes());
/* Need to be encrypted */
if (conn->type == RSPAMD_HTTP_SERVER) {
@@ -2365,44 +2350,44 @@ if (conn->opts & RSPAMD_HTTP_CLIENT_SSL) {
gpointer ssl_ctx = (msg->flags & RSPAMD_HTTP_FLAG_SSL_NOVERIFY) ? priv->ctx->ssl_ctx_noverify : priv->ctx->ssl_ctx;
if (!ssl_ctx) {
- err = g_error_new(HTTP_ERROR, 400, "ssl message requested "
- "with no ssl ctx");
- rspamd_http_connection_ref(conn);
- conn->error_handler(conn, err);
- rspamd_http_connection_unref(conn);
- g_error_free(err);
- return FALSE;
+ err = g_error_new(HTTP_ERROR, 400, "ssl message requested "
+ "with no ssl ctx");
+ rspamd_http_connection_ref(conn);
+ conn->error_handler(conn, err);
+ rspamd_http_connection_unref(conn);
+ g_error_free(err);
+ return FALSE;
}
else {
- if (!priv->ssl) {
- priv->ssl = rspamd_ssl_connection_new(ssl_ctx, priv->ctx->event_loop,
- !(msg->flags & RSPAMD_HTTP_FLAG_SSL_NOVERIFY),
- conn->log_tag);
- g_assert(priv->ssl != NULL);
-
- if (!rspamd_ssl_connect_fd(priv->ssl, conn->fd, host, &priv->ev,
- priv->timeout, rspamd_http_event_handler,
- rspamd_http_ssl_err_handler, conn)) {
-
- err = g_error_new(HTTP_ERROR, 400,
- "ssl connection error: ssl error=%s, errno=%s",
- ERR_error_string(ERR_get_error(), NULL),
- strerror(errno));
- rspamd_http_connection_ref(conn);
- conn->error_handler(conn, err);
- rspamd_http_connection_unref(conn);
- g_error_free(err);
- return FALSE;
- }
- }
- else {
- /* Just restore SSL handlers */
- rspamd_ssl_connection_restore_handlers(priv->ssl,
- rspamd_http_event_handler,
- rspamd_http_ssl_err_handler,
- conn,
- EV_WRITE);
+ if (!priv->ssl) {
+ priv->ssl = rspamd_ssl_connection_new(ssl_ctx, priv->ctx->event_loop,
+ !(msg->flags & RSPAMD_HTTP_FLAG_SSL_NOVERIFY),
+ conn->log_tag);
+ g_assert(priv->ssl != NULL);
+
+ if (!rspamd_ssl_connect_fd(priv->ssl, conn->fd, host, &priv->ev,
+ priv->timeout, rspamd_http_event_handler,
+ rspamd_http_ssl_err_handler, conn)) {
+
+ err = g_error_new(HTTP_ERROR, 400,
+ "ssl connection error: ssl error=%s, errno=%s",
+ ERR_error_string(ERR_get_error(), NULL),
+ strerror(errno));
+ rspamd_http_connection_ref(conn);
+ conn->error_handler(conn, err);
+ rspamd_http_connection_unref(conn);
+ g_error_free(err);
+ return FALSE;
}
+ }
+ else {
+ /* Just restore SSL handlers */
+ rspamd_ssl_connection_restore_handlers(priv->ssl,
+ rspamd_http_event_handler,
+ rspamd_http_ssl_err_handler,
+ conn,
+ EV_WRITE);
+ }
}
}
else {
@@ -2467,10 +2452,10 @@ rspamd_http_connection_get_peer_key(struct rspamd_http_connection *conn)
struct rspamd_http_connection_private *priv = conn->priv;
if (priv->peer_key) {
- return priv->peer_key;
+ return priv->peer_key;
}
else if (priv->msg) {
- return priv->msg->peer_key;
+ return priv->msg->peer_key;
}
return NULL;
@@ -2482,10 +2467,10 @@ rspamd_http_connection_is_encrypted(struct rspamd_http_connection *conn)
struct rspamd_http_connection_private *priv = conn->priv;
if (priv->peer_key != NULL) {
- return TRUE;
+ return TRUE;
}
else if (priv->msg) {
- return priv->msg->peer_key != NULL;
+ return priv->msg->peer_key != NULL;
}
return FALSE;
@@ -2512,103 +2497,103 @@ rspamd_http_message_parse_query(struct rspamd_http_message *msg)
rspamd_fstring_mapped_ftok_free);
if (msg->url && msg->url->len > 0) {
- http_parser_parse_url(msg->url->str, msg->url->len, TRUE, &u);
-
- if (u.field_set & (1 << UF_QUERY)) {
- p = msg->url->str + u.field_data[UF_QUERY].off;
- c = p;
- end = p + u.field_data[UF_QUERY].len;
-
- while (p <= end) {
- switch (state) {
- case parse_key:
- if ((p == end || *p == '&') && p > c) {
- /* We have a single parameter without a value */
- key = rspamd_fstring_new_init(c, p - c);
- key_tok = rspamd_ftok_map(key);
- key_tok->len = rspamd_url_decode(key->str, key->str,
- key->len);
-
- value = rspamd_fstring_new_init("", 0);
- value_tok = rspamd_ftok_map(value);
+ http_parser_parse_url(msg->url->str, msg->url->len, TRUE, &u);
+
+ if (u.field_set & (1 << UF_QUERY)) {
+ p = msg->url->str + u.field_data[UF_QUERY].off;
+ c = p;
+ end = p + u.field_data[UF_QUERY].len;
+
+ while (p <= end) {
+ switch (state) {
+ case parse_key:
+ if ((p == end || *p == '&') && p > c) {
+ /* We have a single parameter without a value */
+ key = rspamd_fstring_new_init(c, p - c);
+ key_tok = rspamd_ftok_map(key);
+ key_tok->len = rspamd_url_decode(key->str, key->str,
+ key->len);
+
+ value = rspamd_fstring_new_init("", 0);
+ value_tok = rspamd_ftok_map(value);
+
+ g_hash_table_replace(res, key_tok, value_tok);
+ state = parse_ampersand;
+ }
+ else if (*p == '=' && p > c) {
+ /* We have something like key=value */
+ key = rspamd_fstring_new_init(c, p - c);
+ key_tok = rspamd_ftok_map(key);
+ key_tok->len = rspamd_url_decode(key->str, key->str,
+ key->len);
+
+ state = parse_eqsign;
+ }
+ else {
+ p++;
+ }
+ break;
- g_hash_table_replace(res, key_tok, value_tok);
- state = parse_ampersand;
- }
- else if (*p == '=' && p > c) {
- /* We have something like key=value */
- key = rspamd_fstring_new_init(c, p - c);
- key_tok = rspamd_ftok_map(key);
- key_tok->len = rspamd_url_decode(key->str, key->str,
- key->len);
-
- state = parse_eqsign;
- }
- else {
- p++;
- }
- break;
+ case parse_eqsign:
+ if (*p != '=') {
+ c = p;
+ state = parse_value;
+ }
+ else {
+ p++;
+ }
+ break;
- case parse_eqsign:
- if (*p != '=') {
- c = p;
- state = parse_value;
- }
- else {
- p++;
- }
- break;
-
- case parse_value:
- if ((p == end || *p == '&') && p >= c) {
- g_assert(key != NULL);
- if (p > c) {
- value = rspamd_fstring_new_init(c, p - c);
- value_tok = rspamd_ftok_map(value);
- value_tok->len = rspamd_url_decode(value->str,
- value->str,
- value->len);
- /* Detect quotes for value */
- if (value_tok->begin[0] == '"') {
- memmove(value->str, value->str + 1,
- value_tok->len - 1);
- value_tok->len--;
- }
- if (value_tok->begin[value_tok->len - 1] == '"') {
- value_tok->len--;
- }
+ case parse_value:
+ if ((p == end || *p == '&') && p >= c) {
+ g_assert(key != NULL);
+ if (p > c) {
+ value = rspamd_fstring_new_init(c, p - c);
+ value_tok = rspamd_ftok_map(value);
+ value_tok->len = rspamd_url_decode(value->str,
+ value->str,
+ value->len);
+ /* Detect quotes for value */
+ if (value_tok->begin[0] == '"') {
+ memmove(value->str, value->str + 1,
+ value_tok->len - 1);
+ value_tok->len--;
}
- else {
- value = rspamd_fstring_new_init("", 0);
- value_tok = rspamd_ftok_map(value);
+ if (value_tok->begin[value_tok->len - 1] == '"') {
+ value_tok->len--;
}
-
- g_hash_table_replace(res, key_tok, value_tok);
- key = value = NULL;
- key_tok = value_tok = NULL;
- state = parse_ampersand;
}
else {
- p++;
+ value = rspamd_fstring_new_init("", 0);
+ value_tok = rspamd_ftok_map(value);
}
- break;
- case parse_ampersand:
- if (p != end && *p != '&') {
- c = p;
- state = parse_key;
- }
- else {
- p++;
- }
- break;
+ g_hash_table_replace(res, key_tok, value_tok);
+ key = value = NULL;
+ key_tok = value_tok = NULL;
+ state = parse_ampersand;
+ }
+ else {
+ p++;
+ }
+ break;
+
+ case parse_ampersand:
+ if (p != end && *p != '&') {
+ c = p;
+ state = parse_key;
+ }
+ else {
+ p++;
}
+ break;
}
}
+ }
- if (state != parse_ampersand && key != NULL) {
- rspamd_fstring_free(key);
- }
+ if (state != parse_ampersand && key != NULL) {
+ rspamd_fstring_free(key);
+ }
}
return res;
@@ -2635,15 +2620,15 @@ void rspamd_http_connection_disable_encryption(struct rspamd_http_connection *co
priv = conn->priv;
if (priv) {
- if (priv->local_key) {
- rspamd_keypair_unref(priv->local_key);
- }
- if (priv->peer_key) {
- rspamd_pubkey_unref(priv->peer_key);
- }
+ if (priv->local_key) {
+ rspamd_keypair_unref(priv->local_key);
+ }
+ if (priv->peer_key) {
+ rspamd_pubkey_unref(priv->peer_key);
+ }
- priv->local_key = NULL;
- priv->peer_key = NULL;
- priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
+ priv->local_key = NULL;
+ priv->peer_key = NULL;
+ priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
}
} \ No newline at end of file
diff --git a/src/libserver/http/http_context.c b/src/libserver/http/http_context.c
index fe9412fe2..df32a2258 100644
--- a/src/libserver/http/http_context.c
+++ b/src/libserver/http/http_context.c
@@ -77,8 +77,7 @@ rspamd_http_context_client_rotate_ev(struct ev_loop *loop, ev_timer *w, int reve
ev_timer_again(loop, w);
kp = ctx->client_kp;
- ctx->client_kp = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ ctx->client_kp = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX);
rspamd_keypair_unref(kp);
}
diff --git a/src/libserver/logger/logger.c b/src/libserver/logger/logger.c
index 13bac5cbe..25818e7a5 100644
--- a/src/libserver/logger/logger.c
+++ b/src/libserver/logger/logger.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Vsevolod Stakhov
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -277,8 +277,7 @@ rspamd_log_open_specific(rspamd_mempool_t *pool,
if (cfg->log_encryption_key) {
logger->pk = rspamd_pubkey_ref(cfg->log_encryption_key);
- logger->keypair = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ logger->keypair = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX);
rspamd_pubkey_calculate_nm(logger->pk, logger->keypair);
}
}
@@ -342,9 +341,9 @@ rspamd_log_encrypt_message(const char *begin, const char *end, gsize *enc_len,
g_assert(end > begin);
/* base64 (pubkey | nonce | message) */
- inlen = rspamd_cryptobox_nonce_bytes(RSPAMD_CRYPTOBOX_MODE_25519) +
- rspamd_cryptobox_pk_bytes(RSPAMD_CRYPTOBOX_MODE_25519) +
- rspamd_cryptobox_mac_bytes(RSPAMD_CRYPTOBOX_MODE_25519) +
+ inlen = crypto_box_noncebytes() +
+ crypto_box_publickeybytes() +
+ crypto_box_macbytes() +
(end - begin);
out = g_malloc(inlen);
@@ -352,16 +351,15 @@ rspamd_log_encrypt_message(const char *begin, const char *end, gsize *enc_len,
comp = rspamd_pubkey_get_pk(rspamd_log->pk, &len);
memcpy(p, comp, len);
p += len;
- ottery_rand_bytes(p, rspamd_cryptobox_nonce_bytes(RSPAMD_CRYPTOBOX_MODE_25519));
+ ottery_rand_bytes(p, crypto_box_noncebytes());
nonce = p;
- p += rspamd_cryptobox_nonce_bytes(RSPAMD_CRYPTOBOX_MODE_25519);
+ p += crypto_box_noncebytes();
mac = p;
- p += rspamd_cryptobox_mac_bytes(RSPAMD_CRYPTOBOX_MODE_25519);
+ p += crypto_box_macbytes();
memcpy(p, begin, end - begin);
comp = rspamd_pubkey_get_nm(rspamd_log->pk, rspamd_log->keypair);
g_assert(comp != NULL);
- rspamd_cryptobox_encrypt_nm_inplace(p, end - begin, nonce, comp, mac,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ rspamd_cryptobox_encrypt_nm_inplace(p, end - begin, nonce, comp, mac);
b64 = rspamd_encode_base64(out, inlen, 0, enc_len);
g_free(out);
diff --git a/src/libserver/maps/map.c b/src/libserver/maps/map.c
index 15fce7e9d..631455755 100644
--- a/src/libserver/maps/map.c
+++ b/src/libserver/maps/map.c
@@ -670,14 +670,14 @@ rspamd_map_check_sig_pk_mem(const unsigned char *sig,
GString *b32_key;
gboolean ret = TRUE;
- if (siglen != rspamd_cryptobox_signature_bytes(RSPAMD_CRYPTOBOX_MODE_25519)) {
+ if (siglen != crypto_sign_bytes()) {
msg_err_map("can't open signature for %s: invalid size: %z", map->name, siglen);
ret = FALSE;
}
if (ret && !rspamd_cryptobox_verify(sig, siglen, input, inlen,
- rspamd_pubkey_get_pk(pk, NULL), RSPAMD_CRYPTOBOX_MODE_25519)) {
+ rspamd_pubkey_get_pk(pk, NULL))) {
msg_err_map("can't verify signature for %s: incorrect signature", map->name);
ret = FALSE;
@@ -718,8 +718,7 @@ rspamd_map_check_file_sig(const char *fname,
return FALSE;
}
- pk = rspamd_pubkey_from_base32(data, len, RSPAMD_KEYPAIR_SIGN,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ pk = rspamd_pubkey_from_base32(data, len, RSPAMD_KEYPAIR_SIGN);
munmap(data, len);
if (pk == NULL) {
@@ -2414,8 +2413,7 @@ rspamd_map_check_proto(struct rspamd_config *cfg,
end_key = memchr(pos, '+', end - pos);
if (end_key != NULL) {
- bk->trusted_pubkey = rspamd_pubkey_from_base32(pos, end_key - pos,
- RSPAMD_KEYPAIR_SIGN, RSPAMD_CRYPTOBOX_MODE_25519);
+ bk->trusted_pubkey = rspamd_pubkey_from_base32(pos, end_key - pos, RSPAMD_KEYPAIR_SIGN);
if (bk->trusted_pubkey == NULL) {
msg_err_config("cannot read pubkey from map: %s",
@@ -2426,8 +2424,7 @@ rspamd_map_check_proto(struct rspamd_config *cfg,
}
else if (end - pos > 64) {
/* Try hex encoding */
- bk->trusted_pubkey = rspamd_pubkey_from_hex(pos, 64,
- RSPAMD_KEYPAIR_SIGN, RSPAMD_CRYPTOBOX_MODE_25519);
+ bk->trusted_pubkey = rspamd_pubkey_from_hex(pos, 64, RSPAMD_KEYPAIR_SIGN);
if (bk->trusted_pubkey == NULL) {
msg_err_config("cannot read pubkey from map: %s",
diff --git a/src/libserver/milter.c b/src/libserver/milter.c
index f35278a0e..94b0d6cc1 100644
--- a/src/libserver/milter.c
+++ b/src/libserver/milter.c
@@ -1465,10 +1465,16 @@ rspamd_milter_macro_http(struct rspamd_milter_session *session,
return;
}
+ /*
+ * When we get a queue-id we try to pass it to the backend, where possible
+ * We also need that for logging consistency
+ */
IF_MACRO("{i}")
{
rspamd_http_message_add_header_len(msg, QUEUE_ID_HEADER,
found->begin, found->len);
+ rspamd_http_message_add_header_len(msg, LOG_TAG_HEADER,
+ found->begin, found->len);
}
else
{
@@ -1476,6 +1482,8 @@ rspamd_milter_macro_http(struct rspamd_milter_session *session,
{
rspamd_http_message_add_header_len(msg, QUEUE_ID_HEADER,
found->begin, found->len);
+ rspamd_http_message_add_header_len(msg, LOG_TAG_HEADER,
+ found->begin, found->len);
}
}
diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c
index db83b0bfb..ee2192913 100644
--- a/src/libserver/protocol.c
+++ b/src/libserver/protocol.c
@@ -660,9 +660,9 @@ rspamd_protocol_handle_headers(struct rspamd_task *task,
IF_HEADER(USER_HEADER)
{
/*
- * We must ignore User header in case of spamc, as SA has
- * different meaning of this header
- */
+ * We must ignore User header in case of spamc, as SA has
+ * different meaning of this header
+ */
msg_debug_protocol("read user header, value: %T", hv_tok);
if (!RSPAMD_TASK_IS_SPAMC(task)) {
task->auth_user = rspamd_mempool_ftokdup(task->task_pool,
@@ -708,6 +708,15 @@ rspamd_protocol_handle_headers(struct rspamd_task *task,
task->flags |= RSPAMD_TASK_FLAG_NO_LOG;
}
}
+ IF_HEADER(LOG_TAG_HEADER)
+ {
+ msg_debug_protocol("read log-tag header, value: %T", hv_tok);
+ /* Ensure that a tag is valid */
+ if (rspamd_fast_utf8_validate(hv_tok->begin, hv_tok->len) == 0) {
+ memcpy(task->task_pool->tag.uid, hv_tok->begin,
+ MIN(hv_tok->len, sizeof(task->task_pool->tag.uid)));
+ }
+ }
break;
case 'm':
case 'M':
@@ -752,9 +761,9 @@ rspamd_protocol_handle_headers(struct rspamd_task *task,
default:
msg_debug_protocol("generic header: %T", hn_tok);
break;
- }
+ }
- rspamd_task_add_request_header (task, hn_tok, hv_tok);
+ rspamd_task_add_request_header (task, hn_tok, hv_tok);
}
}); /* End of kh_foreach_value */
diff --git a/src/libserver/protocol_internal.h b/src/libserver/protocol_internal.h
index 7a70ccef0..e55e54851 100644
--- a/src/libserver/protocol_internal.h
+++ b/src/libserver/protocol_internal.h
@@ -78,6 +78,7 @@ extern "C" {
#define HOSTNAME_HEADER "Hostname"
#define DELIVER_TO_HEADER "Deliver-To"
#define NO_LOG_HEADER "Log"
+#define LOG_TAG_HEADER "Log-Tag"
#define MLEN_HEADER "Message-Length"
#define USER_AGENT_HEADER "User-Agent"
#define MTA_TAG_HEADER "MTA-Tag"
diff --git a/src/libserver/spf.c b/src/libserver/spf.c
index 32c020bf3..562222042 100644
--- a/src/libserver/spf.c
+++ b/src/libserver/spf.c
@@ -451,6 +451,9 @@ rspamd_spf_process_reference(struct spf_resolved *target,
target->flags |= RSPAMD_SPF_RESOLVED_NA;
continue;
}
+ if (cur->flags & RSPAMD_SPF_FLAG_PLUSALL) {
+ target->flags |= RSPAMD_SPF_RESOLVED_PLUSALL;
+ }
if (cur->flags & RSPAMD_SPF_FLAG_INVALID) {
/* Ignore invalid elements */
continue;
@@ -1418,7 +1421,7 @@ parse_spf_all(struct spf_record *rec, struct spf_addr *addr)
/* Disallow +all */
if (addr->mech == SPF_PASS) {
- addr->flags |= RSPAMD_SPF_FLAG_INVALID;
+ addr->flags |= RSPAMD_SPF_FLAG_PLUSALL;
msg_notice_spf("domain %s allows any SPF (+all), ignore SPF record completely",
rec->sender_domain);
}
diff --git a/src/libserver/spf.h b/src/libserver/spf.h
index cc0ee4c05..b89dc4d0e 100644
--- a/src/libserver/spf.h
+++ b/src/libserver/spf.h
@@ -77,6 +77,7 @@ typedef enum spf_action_e {
#define RSPAMD_SPF_FLAG_PERMFAIL (1u << 10u)
#define RSPAMD_SPF_FLAG_RESOLVED (1u << 11u)
#define RSPAMD_SPF_FLAG_CACHED (1u << 12u)
+#define RSPAMD_SPF_FLAG_PLUSALL (1u << 13u)
/** Default SPF limits for avoiding abuse **/
#define SPF_MAX_NESTING 10
@@ -104,6 +105,7 @@ enum rspamd_spf_resolved_flags {
RSPAMD_SPF_RESOLVED_TEMP_FAILED = (1u << 0u),
RSPAMD_SPF_RESOLVED_PERM_FAILED = (1u << 1u),
RSPAMD_SPF_RESOLVED_NA = (1u << 2u),
+ RSPAMD_SPF_RESOLVED_PLUSALL = (1u << 3u),
};
struct spf_resolved {
diff --git a/src/libserver/symcache/symcache_runtime.cxx b/src/libserver/symcache/symcache_runtime.cxx
index dc7066b32..ddfbdf1ae 100644
--- a/src/libserver/symcache/symcache_runtime.cxx
+++ b/src/libserver/symcache/symcache_runtime.cxx
@@ -333,8 +333,8 @@ auto symcache_runtime::process_pre_postfilters(struct rspamd_task *task,
*/
if (stage != RSPAMD_TASK_STAGE_IDEMPOTENT &&
!(item->flags & SYMBOL_TYPE_IGNORE_PASSTHROUGH)) {
- if (check_metric_limit(task)) {
- msg_debug_cache_task_lambda("task has already the result being set, ignore further checks");
+ if (check_process_status(task) == check_status::passthrough) {
+ msg_debug_cache_task_lambda("task has already the passthrough result being set, ignore further checks");
return true;
}
@@ -407,13 +407,20 @@ auto symcache_runtime::process_filters(struct rspamd_task *task, symcache &cache
break;
}
+ auto check_result = check_process_status(task);
+
if (!(item->flags & (SYMBOL_TYPE_FINE | SYMBOL_TYPE_IGNORE_PASSTHROUGH))) {
- if (has_passtrough || check_metric_limit(task)) {
- msg_debug_cache_task_lambda("task has already the result being set, ignore further checks");
+ if (has_passtrough || check_result == check_status::passthrough) {
+ msg_debug_cache_task_lambda("task has already the passthrough result being set, ignore further checks");
has_passtrough = true;
/* Skip this item */
continue;
}
+ else if (check_result == check_status::limit_reached) {
+ msg_debug_cache_task_lambda("task has already the limit reached result being set, ignore further checks");
+ /* Skip this item */
+ continue;
+ }
}
auto dyn_item = &dynamic_items[idx];
@@ -531,19 +538,8 @@ auto symcache_runtime::process_symbol(struct rspamd_task *task, symcache &cache,
return true;
}
-auto symcache_runtime::check_metric_limit(struct rspamd_task *task) -> bool
+auto symcache_runtime::check_process_status(struct rspamd_task *task) -> symcache_runtime::check_status
{
- if (task->flags & RSPAMD_TASK_FLAG_PASS_ALL) {
- return false;
- }
-
- /* Check score limit */
- if (!std::isnan(lim)) {
- if (task->result->score > lim) {
- return true;
- }
- }
-
if (task->result->passthrough_result != nullptr) {
/* We also need to check passthrough results */
auto *pr = task->result->passthrough_result;
@@ -563,11 +559,22 @@ auto symcache_runtime::check_metric_limit(struct rspamd_task *task) -> bool
}
/* Immediately stop on non least passthrough action */
- return true;
+ return check_status::passthrough;
}
}
- return false;
+ if (task->flags & RSPAMD_TASK_FLAG_PASS_ALL) {
+ return check_status::allow;
+ }
+
+ /* Check score limit */
+ if (!std::isnan(lim)) {
+ if (task->result->score > lim) {
+ return check_status::limit_reached;
+ }
+ }
+
+ return check_status::allow;
}
auto symcache_runtime::check_item_deps(struct rspamd_task *task, symcache &cache, cache_item *item,
diff --git a/src/libserver/symcache/symcache_runtime.hxx b/src/libserver/symcache/symcache_runtime.hxx
index 7e4a41269..d1dc7ac24 100644
--- a/src/libserver/symcache/symcache_runtime.hxx
+++ b/src/libserver/symcache/symcache_runtime.hxx
@@ -60,6 +60,11 @@ class symcache_runtime {
enabled = 1,
disabled = 2,
} slow_status;
+ enum class check_status {
+ allow,
+ limit_reached,
+ passthrough,
+ };
bool profile;
double profile_start;
@@ -77,7 +82,7 @@ class symcache_runtime {
/* Specific stages of the processing */
auto process_pre_postfilters(struct rspamd_task *task, symcache &cache, int start_events, unsigned int stage) -> bool;
auto process_filters(struct rspamd_task *task, symcache &cache, int start_events) -> bool;
- auto check_metric_limit(struct rspamd_task *task) -> bool;
+ auto check_process_status(struct rspamd_task *task) -> check_status;
auto check_item_deps(struct rspamd_task *task, symcache &cache, cache_item *item,
cache_dynamic_item *dyn_item, bool check_only) -> bool;
diff --git a/src/libstat/stat_process.c b/src/libstat/stat_process.c
index ad976e713..5db3af6ce 100644
--- a/src/libstat/stat_process.c
+++ b/src/libstat/stat_process.c
@@ -509,6 +509,14 @@ rspamd_stat_classify(struct rspamd_task *task, lua_State *L, unsigned int stage,
return ret;
}
+ if (task->message == NULL) {
+ ret = RSPAMD_STAT_PROCESS_ERROR;
+ msg_err_task("trying to classify empty message");
+
+ task->processed_stages |= stage;
+ return ret;
+ }
+
if (stage == RSPAMD_TASK_STAGE_CLASSIFIERS_PRE) {
/* Preprocess tokens */
rspamd_stat_preprocess(st_ctx, task, FALSE, FALSE);
@@ -892,6 +900,18 @@ rspamd_stat_learn(struct rspamd_task *task,
return ret;
}
+
+ if (task->message == NULL) {
+ ret = RSPAMD_STAT_PROCESS_ERROR;
+ if (err && *err == NULL) {
+ g_set_error(err, rspamd_stat_quark(), 500,
+ "Trying to learn an empty message");
+ }
+
+ task->processed_stages |= stage;
+ return ret;
+ }
+
if (stage == RSPAMD_TASK_STAGE_LEARN_PRE) {
/* Process classifiers */
rspamd_stat_preprocess(st_ctx, task, TRUE, spam);
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index f5405f76d..e3f8b2e57 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -34,7 +34,11 @@
local function foo(task)
-- do something
end
-rspamd_config:register_symbol('SYMBOL', 1.0, foo)
+rspamd_config:register_symbol{
+ name = 'SYMBOL',
+ score = 1.0,
+ callback = foo
+}
-- Get configuration
local tab = rspamd_config:get_all_opt('module') -- get table for module's options
@@ -1965,210 +1969,454 @@ lua_config_get_symbol_flags(lua_State *L)
return 1;
}
-static int
-lua_config_register_symbol(lua_State *L)
+static bool
+lua_config_register_symbol_from_table(lua_State *L, struct rspamd_config *cfg,
+ const char *name, int tbl_idx, int *id_out)
{
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config(L, 1);
- const char *name = NULL, *type_str = NULL,
- *description = NULL, *group = NULL;
- double weight = 0, score = NAN, parent_float = NAN;
- gboolean one_shot = FALSE;
- int ret = -1, cbref = -1;
- unsigned int type = 0, flags = 0;
- int64_t parent = 0, priority = 0, nshots = 0;
+ unsigned int type = SYMBOL_TYPE_NORMAL, priority = 0;
+ double weight = 1.0, score = NAN;
+ const char *type_str, *group = NULL, *description = NULL;
GArray *allowed_ids = NULL, *forbidden_ids = NULL;
- GError *err = NULL;
- int prev_top = lua_gettop(L);
+ int id, nshots, cb_ref, parent = -1;
+ unsigned int flags = 0;
+ gboolean optional = FALSE;
- if (cfg) {
- if (!rspamd_lua_parse_table_arguments(L, 2, &err,
- RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
- "name=S;weight=N;callback=F;type=S;priority=I;parent=D;"
- "score=D;description=S;group=S;one_shot=B;nshots=I",
- &name, &weight, &cbref, &type_str,
- &priority, &parent_float,
- &score, &description, &group, &one_shot, &nshots)) {
- msg_err_config("bad arguments: %e", err);
- g_error_free(err);
- lua_settop(L, prev_top);
+ /*
+ * Table can have the following attributes:
+ * "callback" - should be a callback function
+ * "weight" - optional weight
+ * "priority" - optional priority
+ * "type" - optional type (normal, virtual, callback)
+ * "flags" - optional flags
+ * -- Metric options
+ * "score" - optional default score (overridden by metric)
+ * "group" - optional default group
+ * "one_shot" - optional one shot mode
+ * "description" - optional description
+ */
+ lua_pushvalue(L, tbl_idx); /* Push table on top of the stack */
- return luaL_error(L, "invalid arguments");
- }
+ if (name == NULL) {
+ /* Try to resolve name */
+ lua_pushstring(L, "name");
+ lua_gettable(L, -2);
- /* Deal with flags and ids */
- lua_pushstring(L, "flags");
- lua_gettable(L, 2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- flags = lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- flags |= lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- }
- lua_pop(L, 1); /* Clean flags */
+ if (lua_type(L, -1) != LUA_TSTRING) {
+ lua_pop(L, 2);
+ luaL_error(L, "name is not specified");
- lua_pushstring(L, "allowed_ids");
- lua_gettable(L, 2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- allowed_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ return false;
}
- else if (lua_type(L, -1) == LUA_TTABLE) {
- allowed_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(allowed_ids, v);
- }
+ else {
+ name = lua_tostring(L, -1);
}
+
lua_pop(L, 1);
+ }
- lua_pushstring(L, "forbidden_ids");
- lua_gettable(L, 2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- forbidden_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ lua_pushstring(L, "callback");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) != LUA_TFUNCTION) {
+ cb_ref = -1;
+ }
+ else {
+ cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ }
+ lua_pop(L, 1);
+
+ /* Optional fields */
+ lua_pushstring(L, "weight");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ weight = lua_tonumber(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "priority");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ priority = lua_tointeger(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "optional");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ optional = lua_toboolean(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "type");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ type_str = lua_tostring(L, -1);
+ }
+ else {
+ type_str = "normal";
+ }
+ lua_pop(L, 1);
+
+ type = lua_parse_symbol_type(type_str);
+
+ if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
+ luaL_error(L, "no symbol name but type is not callback");
+
+ return false;
+ }
+ else if (!(type & SYMBOL_TYPE_VIRTUAL) && cb_ref == -1) {
+ luaL_error(L, "no callback for symbol %s", name);
+
+ return false;
+ }
+
+ lua_pushstring(L, "parent");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ parent = lua_tointeger(L, -1);
+ }
+ lua_pop(L, 1);
+
+
+ /* Deal with flags and ids */
+ lua_pushstring(L, "flags");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ flags = lua_parse_symbol_flags(lua_tostring(L, -1));
+ }
+ else if (lua_type(L, -1) == LUA_TTABLE) {
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ flags |= lua_parse_symbol_flags(lua_tostring(L, -1));
}
- else if (lua_type(L, -1) == LUA_TTABLE) {
- forbidden_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(forbidden_ids, v);
- }
+ }
+ lua_pop(L, 1); /* Clean flags */
+
+ lua_pushstring(L, "allowed_ids");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ allowed_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ }
+ else if (lua_type(L, -1) == LUA_TTABLE) {
+ allowed_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
+ rspamd_lua_table_size(L, -1));
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ uint32_t v = lua_tointeger(L, -1);
+ g_array_append_val(allowed_ids, v);
}
- lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
- if (nshots == 0) {
- nshots = cfg->default_max_shots;
+ lua_pushstring(L, "forbidden_ids");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ forbidden_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ }
+ else if (lua_type(L, -1) == LUA_TTABLE) {
+ forbidden_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
+ rspamd_lua_table_size(L, -1));
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ uint32_t v = lua_tointeger(L, -1);
+ g_array_append_val(forbidden_ids, v);
}
+ }
+ lua_pop(L, 1);
- type = lua_parse_symbol_type(type_str);
+ id = rspamd_register_symbol_fromlua(L,
+ cfg,
+ name,
+ cb_ref,
+ weight,
+ priority,
+ type | flags,
+ parent,
+ allowed_ids, forbidden_ids,
+ optional);
- if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
- lua_settop(L, prev_top);
- return luaL_error(L, "no symbol name but type is not callback");
- }
- else if (!(type & SYMBOL_TYPE_VIRTUAL) && cbref == -1) {
- lua_settop(L, prev_top);
- return luaL_error(L, "no callback for symbol %s", name);
- }
+ if (allowed_ids) {
+ g_array_free(allowed_ids, TRUE);
+ }
+
+ if (forbidden_ids) {
+ g_array_free(forbidden_ids, TRUE);
+ }
+
+ if (id != -1) {
+ if (cb_ref != -1) {
+ /* Check for condition */
+ lua_pushstring(L, "condition");
+ lua_gettable(L, -2);
- if (isnan(parent_float)) {
- parent = -1;
+ if (lua_type(L, -1) == LUA_TFUNCTION) {
+ int condref;
+
+ /* Here we pop function from the stack, so no lua_pop is required */
+ condref = luaL_ref(L, LUA_REGISTRYINDEX);
+ g_assert(name != NULL);
+ rspamd_symcache_add_condition_delayed(cfg->cache,
+ name, L, condref);
+ }
+ else {
+ lua_pop(L, 1);
+ }
}
- else {
- parent = parent_float;
+
+ /* Check for augmentations */
+ lua_pushstring(L, "augmentations");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TTABLE) {
+
+ int aug_tbl_idx = lua_gettop(L);
+ for (lua_pushnil(L); lua_next(L, aug_tbl_idx); lua_pop(L, 1)) {
+ rspamd_symcache_add_symbol_augmentation(cfg->cache, id,
+ lua_tostring(L, -1), NULL);
+ }
}
- ret = rspamd_register_symbol_fromlua(L,
- cfg,
- name,
- cbref,
- weight == 0 ? 1.0 : weight,
- priority,
- type | flags,
- parent,
- allowed_ids, forbidden_ids,
- FALSE);
+ lua_pop(L, 1);
+ }
- if (allowed_ids) {
- g_array_free(allowed_ids, TRUE);
+ /*
+ * Now check if a symbol has not been registered in any metric and
+ * insert default value if applicable
+ */
+ struct rspamd_symbol *sym = g_hash_table_lookup(cfg->symbols, name);
+ if (sym == NULL || (sym->flags & RSPAMD_SYMBOL_FLAG_UNSCORED)) {
+ nshots = cfg->default_max_shots;
+
+ lua_pushstring(L, "score");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ score = lua_tonumber(L, -1);
+
+ if (sym) {
+ /* Reset unscored flag */
+ sym->flags &= ~RSPAMD_SYMBOL_FLAG_UNSCORED;
+ }
}
+ lua_pop(L, 1);
- if (forbidden_ids) {
- g_array_free(forbidden_ids, TRUE);
+ lua_pushstring(L, "group");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ group = lua_tostring(L, -1);
}
+ lua_pop(L, 1);
+
+ if (!isnan(score) || group != NULL) {
+ lua_pushstring(L, "description");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ description = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "one_shot");
+ lua_gettable(L, -2);
- if (ret != -1) {
- if (!isnan(score) || group) {
- if (one_shot) {
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ if (lua_toboolean(L, -1)) {
nshots = 1;
}
+ }
+ lua_pop(L, 1);
- rspamd_config_add_symbol(cfg, name,
- score, description, group, flags,
- 0, nshots);
+ lua_pushstring(L, "one_param");
+ lua_gettable(L, -2);
- lua_pushstring(L, "groups");
- lua_gettable(L, 2);
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ if (lua_toboolean(L, -1)) {
+ flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
+ }
+ }
+ lua_pop(L, 1);
- if (lua_istable(L, -1)) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- if (lua_isstring(L, -1)) {
- rspamd_config_add_symbol_group(cfg, name,
- lua_tostring(L, -1));
- }
- else {
- lua_settop(L, prev_top);
- return luaL_error(L, "invalid groups element");
- }
+ /*
+ * Do not override the existing symbols (using zero priority),
+ * since we are defining default values here
+ */
+ if (!isnan(score)) {
+ rspamd_config_add_symbol(cfg, name, score,
+ description, group, flags, 0, nshots);
+ }
+ else if (group) {
+ /* Add with zero score */
+ rspamd_config_add_symbol(cfg, name, NAN,
+ description, group, flags, 0, nshots);
+ }
+
+ lua_pushstring(L, "groups");
+ lua_gettable(L, -2);
+
+ if (lua_istable(L, -1)) {
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ if (lua_isstring(L, -1)) {
+ rspamd_config_add_symbol_group(cfg, name,
+ lua_tostring(L, -1));
+ }
+ else {
+ lua_pop(L, 2);
+ luaL_error(L, "invalid groups element");
+
+ return false;
}
}
+ }
- lua_pop(L, 1);
+ lua_pop(L, 1);
+ }
+ }
+ else {
+ /* Fill in missing fields from lua definition if they are not set */
+ if (sym->description == NULL) {
+ lua_pushstring(L, "description");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ description = lua_tostring(L, -1);
}
+ lua_pop(L, 1);
- lua_pushstring(L, "augmentations");
- lua_gettable(L, 2);
+ if (description) {
+ sym->description = rspamd_mempool_strdup(cfg->cfg_pool, description);
+ }
+ }
- if (lua_type(L, -1) == LUA_TTABLE) {
- int tbl_idx = lua_gettop(L);
- for (lua_pushnil(L); lua_next(L, tbl_idx); lua_pop(L, 1)) {
- size_t len;
- const char *augmentation = lua_tolstring(L, -1, &len), *eqsign_pos;
+ /* If ungrouped and there is a group defined in lua, change the primary group
+ * Otherwise, add to the list of groups for this symbol. */
+ lua_pushstring(L, "group");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ group = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+ if (group) {
+ if (sym->flags & RSPAMD_SYMBOL_FLAG_UNGROUPED) {
+ /* Unset the "ungrouped" group */
+ sym->gr = NULL;
+ }
+ /* Add the group. If the symbol was ungrouped, this will
+ * clear RSPAMD_SYMBOL_FLAG_UNGROUPED from the flags. */
+ rspamd_config_add_symbol_group(cfg, name, group);
+ }
+ }
- /* Find `=` symbol and use it as a separator */
- eqsign_pos = memchr(augmentation, '=', len);
- if (eqsign_pos != NULL && eqsign_pos + 1 < augmentation + len) {
- rspamd_ftok_t tok;
+ /* Remove table from stack */
+ lua_pop(L, 1);
- tok.begin = augmentation;
- tok.len = eqsign_pos - augmentation;
- char *augentation_name = rspamd_ftokdup(&tok);
+ *id_out = id;
- tok.begin = eqsign_pos + 1;
- tok.len = (augmentation + len) - tok.begin;
+ return true;
+}
- char *augmentation_value = rspamd_ftokdup(&tok);
+/* Legacy symbol registration */
+static bool
+lua_config_register_symbol_legacy(lua_State *L, struct rspamd_config *cfg, int pos, int *id_out)
+{
+ const char *name = NULL, *type_str = NULL,
+ *description = NULL, *group = NULL;
+ double weight = 0, score = NAN, parent_float = NAN;
+ gboolean one_shot = FALSE;
+ int ret, cbref = -1;
+ unsigned int type = 0, flags = 0;
+ int64_t parent = 0, priority = 0, nshots = 0;
- if (!rspamd_symcache_add_symbol_augmentation(cfg->cache, ret,
- augentation_name, augmentation_value)) {
- lua_settop(L, prev_top);
- g_free(augmentation_value);
- g_free(augentation_name);
+ GError *err = NULL;
+ if (!rspamd_lua_parse_table_arguments(L, pos, &err,
+ RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
+ "name=S;weight=N;callback=F;type=S;priority=I;parent=D;"
+ "score=D;description=S;group=S;one_shot=B;nshots=I",
+ &name, &weight, &cbref, &type_str,
+ &priority, &parent_float,
+ &score, &description, &group, &one_shot, &nshots)) {
+ msg_err_config("bad arguments: %e", err);
+ g_error_free(err);
- return luaL_error(L, "unknown or invalid augmentation %s in symbol %s",
- augmentation, name);
- }
+ return false;
+ }
- g_free(augmentation_value);
- g_free(augentation_name);
- }
- else {
- /* Just a value */
- if (!rspamd_symcache_add_symbol_augmentation(cfg->cache, ret,
- augmentation, NULL)) {
- lua_settop(L, prev_top);
+ type = lua_parse_symbol_type(type_str);
- return luaL_error(L, "unknown augmentation %s in symbol %s",
- augmentation, name);
- }
- }
- }
+ if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
+ luaL_error(L, "no symbol name but type is not callback");
+
+ return false;
+ }
+ else if (!(type & SYMBOL_TYPE_VIRTUAL) && cbref == -1) {
+ luaL_error(L, "no callback for symbol %s", name);
+
+ return false;
+ }
+
+ if (isnan(parent_float)) {
+ parent = -1;
+ }
+ else {
+ parent = parent_float;
+ }
+
+ ret = rspamd_register_symbol_fromlua(L,
+ cfg,
+ name,
+ cbref,
+ weight == 0 ? 1.0 : weight,
+ priority,
+ type | flags,
+ parent,
+ NULL, NULL,
+ FALSE);
+
+ if (ret != -1) {
+ if (!isnan(score) || group) {
+ if (one_shot) {
+ nshots = 1;
+ }
+ if (nshots == 0) {
+ nshots = cfg->default_max_shots;
}
+
+ rspamd_config_add_symbol(cfg, name, score,
+ description, group, flags, 0, nshots);
}
+
+ *id_out = ret;
+
+ return true;
}
- else {
- lua_settop(L, prev_top);
- return luaL_error(L, "invalid arguments");
+ return false;
+}
+
+static int
+lua_config_register_symbol(lua_State *L)
+{
+ LUA_TRACE_POINT;
+ struct rspamd_config *cfg = lua_check_config(L, 1);
+ int id = -1;
+
+ if (lua_type(L, 2) == LUA_TSTRING) {
+ if (lua_config_register_symbol_legacy(L, cfg, 2, &id)) {
+ lua_pushinteger(L, id);
+
+ return 1;
+ }
+ else {
+ return luaL_error(L, "bad arguments");
+ }
}
+ else if (lua_config_register_symbol_from_table(L, cfg, NULL, 2, &id)) {
+ lua_pushinteger(L, id);
- lua_settop(L, prev_top);
- lua_pushinteger(L, ret);
+ return 1;
+ }
- return 1;
+ return 0;
}
static int
@@ -2655,10 +2903,7 @@ lua_config_newindex(lua_State *L)
LUA_TRACE_POINT;
struct rspamd_config *cfg = lua_check_config(L, 1);
const char *name;
- GArray *allowed_ids = NULL, *forbidden_ids = NULL;
- int id, nshots;
- unsigned int flags = 0;
- gboolean optional = FALSE;
+ int id = -1;
name = luaL_checkstring(L, 2);
@@ -2679,291 +2924,14 @@ lua_config_newindex(lua_State *L)
FALSE);
}
else if (lua_type(L, 3) == LUA_TTABLE) {
- unsigned int type = SYMBOL_TYPE_NORMAL, priority = 0;
- int idx;
- double weight = 1.0, score = NAN;
- const char *type_str, *group = NULL, *description = NULL;
-
- /*
- * Table can have the following attributes:
- * "callback" - should be a callback function
- * "weight" - optional weight
- * "priority" - optional priority
- * "type" - optional type (normal, virtual, callback)
- * "flags" - optional flags
- * -- Metric options
- * "score" - optional default score (overridden by metric)
- * "group" - optional default group
- * "one_shot" - optional one shot mode
- * "description" - optional description
- */
- lua_pushvalue(L, 3);
- lua_pushstring(L, "callback");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) != LUA_TFUNCTION) {
- lua_pop(L, 2);
- msg_info_config("cannot find callback definition for %s",
- name);
- return 0;
- }
- idx = luaL_ref(L, LUA_REGISTRYINDEX);
-
- /* Optional fields */
- lua_pushstring(L, "weight");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TNUMBER) {
- weight = lua_tonumber(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "priority");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TNUMBER) {
- priority = lua_tointeger(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "optional");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
- optional = lua_toboolean(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "type");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TSTRING) {
- type_str = lua_tostring(L, -1);
- type = lua_parse_symbol_type(type_str);
- }
- lua_pop(L, 1);
-
- /* Deal with flags and ids */
- lua_pushstring(L, "flags");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- flags = lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- flags |= lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- }
- lua_pop(L, 1); /* Clean flags */
-
- lua_pushstring(L, "allowed_ids");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- allowed_ids = rspamd_process_id_list(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- allowed_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(allowed_ids, v);
- }
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "forbidden_ids");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- forbidden_ids = rspamd_process_id_list(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- forbidden_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(forbidden_ids, v);
- }
- }
- lua_pop(L, 1);
-
- id = rspamd_register_symbol_fromlua(L,
- cfg,
- name,
- idx,
- weight,
- priority,
- type | flags,
- -1,
- allowed_ids, forbidden_ids,
- optional);
-
- if (allowed_ids) {
- g_array_free(allowed_ids, TRUE);
- }
-
- if (forbidden_ids) {
- g_array_free(forbidden_ids, TRUE);
- }
-
- if (id != -1) {
- /* Check for condition */
- lua_pushstring(L, "condition");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TFUNCTION) {
- int condref;
-
- /* Here we pop function from the stack, so no lua_pop is required */
- condref = luaL_ref(L, LUA_REGISTRYINDEX);
- g_assert(name != NULL);
- rspamd_symcache_add_condition_delayed(cfg->cache,
- name, L, condref);
- }
- else {
- lua_pop(L, 1);
- }
-
- /* Check for augmentations */
- lua_pushstring(L, "augmentations");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TTABLE) {
-
- int tbl_idx = lua_gettop(L);
- for (lua_pushnil(L); lua_next(L, tbl_idx); lua_pop(L, 1)) {
- rspamd_symcache_add_symbol_augmentation(cfg->cache, id,
- lua_tostring(L, -1), NULL);
- }
- }
-
- lua_pop(L, 1);
- }
-
- /*
- * Now check if a symbol has not been registered in any metric and
- * insert default value if applicable
- */
- struct rspamd_symbol *sym = g_hash_table_lookup(cfg->symbols, name);
- if (sym == NULL || (sym->flags & RSPAMD_SYMBOL_FLAG_UNSCORED)) {
- nshots = cfg->default_max_shots;
-
- lua_pushstring(L, "score");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TNUMBER) {
- score = lua_tonumber(L, -1);
-
- if (sym) {
- /* Reset unscored flag */
- sym->flags &= ~RSPAMD_SYMBOL_FLAG_UNSCORED;
- }
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "group");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- group = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
-
- if (!isnan(score) || group != NULL) {
- lua_pushstring(L, "description");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TSTRING) {
- description = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "one_shot");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
- if (lua_toboolean(L, -1)) {
- nshots = 1;
- }
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "one_param");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
- if (lua_toboolean(L, -1)) {
- flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
- }
- }
- lua_pop(L, 1);
-
- /*
- * Do not override the existing symbols (using zero priority),
- * since we are defining default values here
- */
- if (!isnan(score)) {
- rspamd_config_add_symbol(cfg, name, score,
- description, group, flags, 0, nshots);
- }
- else if (group) {
- /* Add with zero score */
- rspamd_config_add_symbol(cfg, name, NAN,
- description, group, flags, 0, nshots);
- }
-
- lua_pushstring(L, "groups");
- lua_gettable(L, -2);
-
- if (lua_istable(L, -1)) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- if (lua_isstring(L, -1)) {
- rspamd_config_add_symbol_group(cfg, name,
- lua_tostring(L, -1));
- }
- else {
- return luaL_error(L, "invalid groups element");
- }
- }
- }
-
- lua_pop(L, 1);
- }
- }
- else {
- /* Fill in missing fields from lua definition if they are not set */
- if (sym->description == NULL) {
- lua_pushstring(L, "description");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TSTRING) {
- description = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
-
- if (description) {
- sym->description = rspamd_mempool_strdup(cfg->cfg_pool, description);
- }
- }
-
- /* If ungrouped and there is a group defined in lua, change the primary group
- * Otherwise, add to the list of groups for this symbol. */
- lua_pushstring(L, "group");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- group = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
- if (group) {
- if (sym->flags & RSPAMD_SYMBOL_FLAG_UNGROUPED) {
- /* Unset the "ungrouped" group */
- sym->gr = NULL;
- }
- /* Add the group. If the symbol was ungrouped, this will
- * clear RSPAMD_SYMBOL_FLAG_UNGROUPED from the flags. */
- rspamd_config_add_symbol_group(cfg, name, group);
- }
+ /* Table symbol */
+ if (lua_config_register_symbol_from_table(L, cfg, name, 3, &id)) {
+ lua_pushinteger(L, id);
+ return 1;
}
-
- /* Remove table from stack */
- lua_pop(L, 1);
+ }
+ else {
+ return luaL_error(L, "invalid value for symbol");
}
}
else {
@@ -3941,6 +3909,8 @@ lua_config_get_groups(lua_State *L)
lua_setfield(L, -2, "description");
lua_pushnumber(L, gr->max_score);
lua_setfield(L, -2, "max_score");
+ lua_pushnumber(L, gr->min_score);
+ lua_setfield(L, -2, "min_score");
lua_pushboolean(L, (gr->flags & RSPAMD_SYMBOL_GROUP_PUBLIC) != 0);
lua_setfield(L, -2, "is_public");
/* TODO: maybe push symbols as well */
diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c
index bad7d7024..1b9074f58 100644
--- a/src/lua/lua_cryptobox.c
+++ b/src/lua/lua_cryptobox.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -257,7 +257,6 @@ lua_check_cryptobox_secretbox(lua_State *L, int pos)
* Loads public key from base32 encoded file
* @param {string} file filename to load
* @param {string} type optional 'sign' or 'kex' for signing and encryption
- * @param {string} alg optional 'default' or 'nist' for curve25519/nistp256 keys
* @return {cryptobox_pubkey} new public key
*/
static int
@@ -267,7 +266,6 @@ lua_cryptobox_pubkey_load(lua_State *L)
struct rspamd_cryptobox_pubkey *pkey = NULL, **ppkey;
const char *filename, *arg;
int type = RSPAMD_KEYPAIR_SIGN;
- int alg = RSPAMD_CRYPTOBOX_MODE_25519;
unsigned char *map;
gsize len;
@@ -293,19 +291,8 @@ lua_cryptobox_pubkey_load(lua_State *L)
type = RSPAMD_KEYPAIR_KEX;
}
}
- if (lua_type(L, 3) == LUA_TSTRING) {
- /* algorithm */
- arg = lua_tostring(L, 3);
-
- if (strcmp(arg, "default") == 0 || strcmp(arg, "curve25519") == 0) {
- type = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else if (strcmp(arg, "nist") == 0) {
- type = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- }
- pkey = rspamd_pubkey_from_base32(map, len, type, alg);
+ pkey = rspamd_pubkey_from_base32(map, len, type);
if (pkey == NULL) {
msg_err("cannot open pubkey from file: %s", filename);
@@ -333,7 +320,6 @@ lua_cryptobox_pubkey_load(lua_State *L)
* Loads public key from base32 encoded string
* @param {base32 string} base32 string with the key
* @param {string} type optional 'sign' or 'kex' for signing and encryption
- * @param {string} alg optional 'default' or 'nist' for curve25519/nistp256 keys
* @return {cryptobox_pubkey} new public key
*/
static int
@@ -344,7 +330,6 @@ lua_cryptobox_pubkey_create(lua_State *L)
const char *buf, *arg;
gsize len;
int type = RSPAMD_KEYPAIR_SIGN;
- int alg = RSPAMD_CRYPTOBOX_MODE_25519;
buf = luaL_checklstring(L, 1, &len);
if (buf != NULL) {
@@ -359,19 +344,8 @@ lua_cryptobox_pubkey_create(lua_State *L)
type = RSPAMD_KEYPAIR_KEX;
}
}
- if (lua_type(L, 3) == LUA_TSTRING) {
- /* algorithm */
- arg = lua_tostring(L, 3);
-
- if (strcmp(arg, "default") == 0 || strcmp(arg, "curve25519") == 0) {
- type = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else if (strcmp(arg, "nist") == 0) {
- type = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- }
- pkey = rspamd_pubkey_from_base32(buf, len, type, alg);
+ pkey = rspamd_pubkey_from_base32(buf, len, type);
if (pkey == NULL) {
msg_err("cannot load pubkey from string");
@@ -477,7 +451,6 @@ lua_cryptobox_keypair_load(lua_State *L)
* @function rspamd_cryptobox_keypair.create([type='encryption'[, alg='curve25519']])
* Generates new keypair
* @param {string} type type of keypair: 'encryption' (default) or 'sign'
- * @param {string} alg algorithm of keypair: 'curve25519' (default) or 'nist'
* @return {cryptobox_keypair} new keypair
*/
static int
@@ -486,7 +459,6 @@ lua_cryptobox_keypair_create(lua_State *L)
LUA_TRACE_POINT;
struct rspamd_cryptobox_keypair *kp, **pkp;
enum rspamd_cryptobox_keypair_type type = RSPAMD_KEYPAIR_KEX;
- enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
if (lua_isstring(L, 1)) {
const char *str = lua_tostring(L, 1);
@@ -502,21 +474,7 @@ lua_cryptobox_keypair_create(lua_State *L)
}
}
- if (lua_isstring(L, 2)) {
- const char *str = lua_tostring(L, 2);
-
- if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else {
- return luaL_error(L, "invalid keypair algorithm: %s", str);
- }
- }
-
- kp = rspamd_keypair_new(type, alg);
+ kp = rspamd_keypair_new(type);
pkp = lua_newuserdata(L, sizeof(gpointer));
*pkp = kp;
@@ -606,12 +564,7 @@ lua_cryptobox_keypair_get_alg(lua_State *L)
struct rspamd_cryptobox_keypair *kp = lua_check_cryptobox_keypair(L, 1);
if (kp) {
- if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
- lua_pushstring(L, "curve25519");
- }
- else {
- lua_pushstring(L, "nist");
- }
+ lua_pushstring(L, "curve25519");
}
else {
return luaL_error(L, "invalid arguments");
@@ -636,7 +589,7 @@ lua_cryptobox_keypair_get_pk(lua_State *L)
if (kp) {
data = rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_PK, &dlen);
- pk = rspamd_pubkey_from_bin(data, dlen, kp->type, kp->alg);
+ pk = rspamd_pubkey_from_bin(data, dlen, kp->type);
if (pk == NULL) {
return luaL_error(L, "invalid keypair");
@@ -654,7 +607,7 @@ lua_cryptobox_keypair_get_pk(lua_State *L)
}
/***
- * @function rspamd_cryptobox_signature.load(file, [alg = 'curve25519'])
+ * @function rspamd_cryptobox_signature.load(file)
* Loads signature from raw file
* @param {string} file filename to load
* @return {cryptobox_signature} new signature
@@ -668,7 +621,6 @@ lua_cryptobox_signature_load(lua_State *L)
gpointer data;
int fd;
struct stat st;
- enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
filename = luaL_checkstring(L, 1);
if (filename != NULL) {
@@ -686,22 +638,6 @@ lua_cryptobox_signature_load(lua_State *L)
lua_pushnil(L);
}
else {
- if (lua_isstring(L, 2)) {
- const char *str = lua_tostring(L, 2);
-
- if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else {
- munmap(data, st.st_size);
- close(fd);
-
- return luaL_error(L, "invalid keypair algorithm: %s", str);
- }
- }
if (st.st_size > 0) {
sig = rspamd_fstring_new_init(data, st.st_size);
psig = lua_newuserdata(L, sizeof(rspamd_fstring_t *));
@@ -711,7 +647,7 @@ lua_cryptobox_signature_load(lua_State *L)
else {
msg_err("size of %s mismatches: %d while %d is expected",
filename, (int) st.st_size,
- rspamd_cryptobox_signature_bytes(alg));
+ crypto_sign_bytes());
lua_pushnil(L);
}
@@ -821,7 +757,7 @@ lua_cryptobox_signature_create(lua_State *L)
}
if (data != NULL) {
- if (dlen == rspamd_cryptobox_signature_bytes(RSPAMD_CRYPTOBOX_MODE_25519)) {
+ if (dlen == crypto_sign_bytes()) {
sig = rspamd_fstring_new_init(data, dlen);
psig = lua_newuserdata(L, sizeof(rspamd_fstring_t *));
rspamd_lua_setclass(L, rspamd_cryptobox_signature_classname, -1);
@@ -1723,7 +1659,7 @@ lua_cryptobox_hash_gc(lua_State *L)
}
/***
- * @function rspamd_cryptobox.verify_memory(pk, sig, data, [alg = 'curve25519'])
+ * @function rspamd_cryptobox.verify_memory(pk, sig, data)
* Check memory using specified cryptobox key and signature
* @param {pubkey} pk public key to verify
* @param {sig} signature to check
@@ -1738,7 +1674,6 @@ lua_cryptobox_verify_memory(lua_State *L)
rspamd_fstring_t *signature;
struct rspamd_lua_text *t;
const char *data;
- enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
gsize len;
int ret;
@@ -1759,23 +1694,9 @@ lua_cryptobox_verify_memory(lua_State *L)
data = luaL_checklstring(L, 3, &len);
}
- if (lua_isstring(L, 4)) {
- const char *str = lua_tostring(L, 4);
-
- if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else {
- return luaL_error(L, "invalid algorithm: %s", str);
- }
- }
-
if (pk != NULL && signature != NULL && data != NULL) {
ret = rspamd_cryptobox_verify(signature->str, signature->len, data, len,
- rspamd_pubkey_get_pk(pk, NULL), alg);
+ rspamd_pubkey_get_pk(pk, NULL));
if (ret) {
lua_pushboolean(L, 1);
@@ -1792,7 +1713,7 @@ lua_cryptobox_verify_memory(lua_State *L)
}
/***
- * @function rspamd_cryptobox.verify_file(pk, sig, file, [alg = 'curve25519'])
+ * @function rspamd_cryptobox.verify_file(pk, sig, file)
* Check file using specified cryptobox key and signature
* @param {pubkey} pk public key to verify
* @param {sig} signature to check
@@ -1807,7 +1728,6 @@ lua_cryptobox_verify_file(lua_State *L)
struct rspamd_cryptobox_pubkey *pk;
rspamd_fstring_t *signature;
unsigned char *map = NULL;
- enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
gsize len;
int ret;
@@ -1815,26 +1735,12 @@ lua_cryptobox_verify_file(lua_State *L)
signature = lua_check_cryptobox_sign(L, 2);
fname = luaL_checkstring(L, 3);
- if (lua_isstring(L, 4)) {
- const char *str = lua_tostring(L, 4);
-
- if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else {
- return luaL_error(L, "invalid algorithm: %s", str);
- }
- }
-
map = rspamd_file_xmap(fname, PROT_READ, &len, TRUE);
if (map != NULL && pk != NULL && signature != NULL) {
ret = rspamd_cryptobox_verify(signature->str, signature->len,
map, len,
- rspamd_pubkey_get_pk(pk, NULL), alg);
+ rspamd_pubkey_get_pk(pk, NULL));
if (ret) {
lua_pushboolean(L, 1);
@@ -1896,12 +1802,11 @@ lua_cryptobox_sign_memory(lua_State *L)
return luaL_error(L, "invalid arguments");
}
- sig = rspamd_fstring_sized_new(rspamd_cryptobox_signature_bytes(
- rspamd_keypair_alg(kp)));
+ sig = rspamd_fstring_sized_new(crypto_sign_bytes());
unsigned long long siglen = sig->len;
rspamd_cryptobox_sign(sig->str, &siglen, data,
- len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL), rspamd_keypair_alg(kp));
+ len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL));
sig->len = siglen;
psig = lua_newuserdata(L, sizeof(void *));
@@ -1942,13 +1847,12 @@ lua_cryptobox_sign_file(lua_State *L)
lua_pushnil(L);
}
else {
- sig = rspamd_fstring_sized_new(rspamd_cryptobox_signature_bytes(
- rspamd_keypair_alg(kp)));
+ sig = rspamd_fstring_sized_new(crypto_sign_bytes());
unsigned long long siglen = sig->len;
rspamd_cryptobox_sign(sig->str, &siglen, data,
- len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL), rspamd_keypair_alg(kp));
+ len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL));
sig->len = siglen;
psig = lua_newuserdata(L, sizeof(void *));
@@ -1961,7 +1865,7 @@ lua_cryptobox_sign_file(lua_State *L)
}
/***
- * @function rspamd_cryptobox.encrypt_memory(kp, data[, nist=false])
+ * @function rspamd_cryptobox.encrypt_memory(kp, data)
* Encrypt data using specified keypair/pubkey
* @param {keypair|string} kp keypair or pubkey in base32 to use
* @param {string|text} data
@@ -1993,8 +1897,7 @@ lua_cryptobox_encrypt_memory(lua_State *L)
gsize blen;
b32 = lua_tolstring(L, 1, &blen);
- pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX,
- lua_toboolean(L, 3) ? RSPAMD_CRYPTOBOX_MODE_NIST : RSPAMD_CRYPTOBOX_MODE_25519);
+ pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX);
owned_pk = true;
}
@@ -2063,7 +1966,7 @@ err:
}
/***
- * @function rspamd_cryptobox.encrypt_file(kp|pk_string, filename[, nist=false])
+ * @function rspamd_cryptobox.encrypt_file(kp|pk_string, filename)
* Encrypt data using specified keypair/pubkey
* @param {keypair|string} kp keypair or pubkey in base32 to use
* @param {string} filename
@@ -2096,8 +1999,7 @@ lua_cryptobox_encrypt_file(lua_State *L)
gsize blen;
b32 = lua_tolstring(L, 1, &blen);
- pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX,
- lua_toboolean(L, 3) ? RSPAMD_CRYPTOBOX_MODE_NIST : RSPAMD_CRYPTOBOX_MODE_25519);
+ pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX);
own_pk = true;
}
@@ -2658,11 +2560,11 @@ lua_cryptobox_gen_dkim_keypair(lua_State *L)
char *b64_data;
gsize b64_len;
- rspamd_cryptobox_keypair_sig(pk, sk, RSPAMD_CRYPTOBOX_MODE_25519);
+ rspamd_cryptobox_keypair_sig(pk, sk);
/* Process private key */
b64_data = rspamd_encode_base64(sk,
- rspamd_cryptobox_sk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519),
+ crypto_sign_secretkeybytes(),
-1, &b64_len);
priv_out = lua_newuserdata(L, sizeof(*priv_out));
@@ -2673,7 +2575,7 @@ lua_cryptobox_gen_dkim_keypair(lua_State *L)
/* Process public key */
b64_data = rspamd_encode_base64(pk,
- rspamd_cryptobox_pk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519),
+ crypto_sign_publickeybytes(),
-1, &b64_len);
pub_out = lua_newuserdata(L, sizeof(*pub_out));
@@ -2691,7 +2593,7 @@ lua_cryptobox_gen_dkim_keypair(lua_State *L)
char *b64_data;
gsize b64_len;
- rspamd_cryptobox_keypair_sig(pk, sk, RSPAMD_CRYPTOBOX_MODE_25519);
+ rspamd_cryptobox_keypair_sig(pk, sk);
/* Process private key */
b64_data = rspamd_encode_base64(sk,
@@ -2706,7 +2608,7 @@ lua_cryptobox_gen_dkim_keypair(lua_State *L)
/* Process public key */
b64_data = rspamd_encode_base64(pk,
- rspamd_cryptobox_pk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519),
+ crypto_sign_publickeybytes(),
-1, &b64_len);
pub_out = lua_newuserdata(L, sizeof(*pub_out));
diff --git a/src/lua/lua_http.c b/src/lua/lua_http.c
index 2032f7dc1..8ba612c1b 100644
--- a/src/lua/lua_http.c
+++ b/src/lua/lua_http.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Vsevolod Stakhov
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -907,8 +907,7 @@ lua_http_request(lua_State *L)
gsize inlen;
in = lua_tolstring(L, -1, &inlen);
- peer_key = rspamd_pubkey_from_base32(in, inlen,
- RSPAMD_KEYPAIR_KEX, RSPAMD_CRYPTOBOX_MODE_25519);
+ peer_key = rspamd_pubkey_from_base32(in, inlen, RSPAMD_KEYPAIR_KEX);
}
lua_pop(L, 1);
diff --git a/src/lua/lua_map.c b/src/lua/lua_map.c
index cce78ff2c..1cc2ce1bd 100644
--- a/src/lua/lua_map.c
+++ b/src/lua/lua_map.c
@@ -1293,8 +1293,7 @@ lua_map_set_sign_key(lua_State *L)
pk_str = lua_tolstring(L, 2, &len);
if (map && pk_str) {
- pk = rspamd_pubkey_from_base32(pk_str, len, RSPAMD_KEYPAIR_SIGN,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ pk = rspamd_pubkey_from_base32(pk_str, len, RSPAMD_KEYPAIR_SIGN);
if (!pk) {
return luaL_error(L, "invalid pubkey string");
diff --git a/src/lua/lua_redis.c b/src/lua/lua_redis.c
index f95abb577..d20c496ed 100644
--- a/src/lua/lua_redis.c
+++ b/src/lua/lua_redis.c
@@ -104,7 +104,7 @@ struct lua_redis_userdata {
char *server;
char log_tag[RSPAMD_LOG_ID_LEN + 1];
struct lua_redis_request_specific_userdata *specific;
- double timeout;
+ ev_tstamp timeout;
uint16_t port;
uint16_t terminated;
};
@@ -280,16 +280,23 @@ lua_redis_fin(void *arg)
* @param code
* @param ud
*/
+#ifdef __GNUC__
+__attribute__((format(printf, 1, 5)))
+#endif
static void
lua_redis_push_error(const char *err,
struct lua_redis_ctx *ctx,
struct lua_redis_request_specific_userdata *sp_ud,
- gboolean connected)
+ gboolean connected,
+ ...)
{
struct lua_redis_userdata *ud = sp_ud->c;
struct lua_callback_state cbs;
lua_State *L;
+ va_list ap;
+ va_start(ap, connected);
+
if (!(sp_ud->flags & (LUA_REDIS_SPECIFIC_REPLIED | LUA_REDIS_SPECIFIC_FINISHED))) {
if (sp_ud->cbref != -1) {
@@ -302,7 +309,7 @@ lua_redis_push_error(const char *err,
lua_rawgeti(cbs.L, LUA_REGISTRYINDEX, sp_ud->cbref);
/* String of error */
- lua_pushstring(cbs.L, err);
+ lua_pushvfstring(cbs.L, err, ap);
/* Data is nil */
lua_pushnil(cbs.L);
@@ -331,6 +338,8 @@ lua_redis_push_error(const char *err,
lua_redis_fin(sp_ud);
}
}
+
+ va_end(ap);
}
static void
@@ -479,7 +488,7 @@ lua_redis_callback(redisAsyncContext *c, gpointer r, gpointer priv)
lua_redis_push_data(reply, ctx, sp_ud);
}
else {
- lua_redis_push_error(reply->str, ctx, sp_ud, TRUE);
+ lua_redis_push_error("%s", ctx, sp_ud, TRUE, reply->str);
}
}
else {
@@ -488,10 +497,10 @@ lua_redis_callback(redisAsyncContext *c, gpointer r, gpointer priv)
}
else {
if (c->err == REDIS_ERR_IO) {
- lua_redis_push_error(strerror(errno), ctx, sp_ud, TRUE);
+ lua_redis_push_error("%s", ctx, sp_ud, TRUE, strerror(errno));
}
else {
- lua_redis_push_error(c->errstr, ctx, sp_ud, TRUE);
+ lua_redis_push_error("%s", ctx, sp_ud, TRUE, c->errstr);
}
}
}
@@ -750,7 +759,7 @@ lua_redis_timeout(EV_P_ ev_timer *w, int revents)
REDIS_RETAIN(ctx);
msg_debug_lua_redis("timeout while querying redis server: %p, redis: %p", sp_ud,
sp_ud->c->ctx);
- lua_redis_push_error("timeout while connecting the server", ctx, sp_ud, TRUE);
+ lua_redis_push_error("timeout while connecting the server (%.2f sec)", ctx, sp_ud, TRUE, ud->timeout);
if (sp_ud->c->ctx) {
ac = sp_ud->c->ctx;
diff --git a/src/lua/lua_rsa.c b/src/lua/lua_rsa.c
index 0f67e91d1..0c56b223b 100644
--- a/src/lua/lua_rsa.c
+++ b/src/lua/lua_rsa.c
@@ -91,22 +91,22 @@ static const struct luaL_reg rsasignlib_m[] = {
{"__gc", lua_rsa_signature_gc},
{NULL, NULL}};
-static RSA *
+static EVP_PKEY *
lua_check_rsa_pubkey(lua_State *L, int pos)
{
void *ud = rspamd_lua_check_udata(L, pos, rspamd_rsa_pubkey_classname);
luaL_argcheck(L, ud != NULL, 1, "'rsa_pubkey' expected");
- return ud ? *((RSA **) ud) : NULL;
+ return ud ? *((EVP_PKEY **) ud) : NULL;
}
-static RSA *
+static EVP_PKEY *
lua_check_rsa_privkey(lua_State *L, int pos)
{
void *ud = rspamd_lua_check_udata(L, pos, rspamd_rsa_privkey_classname);
luaL_argcheck(L, ud != NULL, 1, "'rsa_privkey' expected");
- return ud ? *((RSA **) ud) : NULL;
+ return ud ? *((EVP_PKEY **) ud) : NULL;
}
static rspamd_fstring_t *
@@ -121,7 +121,7 @@ lua_check_rsa_sign(lua_State *L, int pos)
static int
lua_rsa_pubkey_load(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
const char *filename;
FILE *f;
@@ -135,15 +135,15 @@ lua_rsa_pubkey_load(lua_State *L)
lua_pushnil(L);
}
else {
- if (!PEM_read_RSA_PUBKEY(f, &rsa, NULL, NULL)) {
+ if (!PEM_read_PUBKEY(f, &pkey, NULL, NULL)) {
msg_err("cannot open pubkey from file: %s, %s", filename,
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_pubkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
fclose(f);
}
@@ -161,15 +161,14 @@ lua_rsa_privkey_save(lua_State *L)
const char *type = "pem";
FILE *f;
int ret;
-
- RSA *rsa = lua_check_rsa_privkey(L, 1);
+ EVP_PKEY *pkey = lua_check_rsa_privkey(L, 1);
filename = luaL_checkstring(L, 2);
if (lua_gettop(L) > 2) {
type = luaL_checkstring(L, 3);
}
- if (rsa != NULL && filename != NULL) {
+ if (pkey != NULL && filename != NULL) {
if (strcmp(filename, "-") == 0) {
f = stdout;
}
@@ -189,10 +188,10 @@ lua_rsa_privkey_save(lua_State *L)
}
if (strcmp(type, "der") == 0) {
- ret = i2d_RSAPrivateKey_fp(f, rsa);
+ ret = i2d_PrivateKey_fp(f, pkey);
}
else {
- ret = PEM_write_RSAPrivateKey(f, rsa, NULL, NULL, 0, NULL, NULL);
+ ret = PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL);
}
if (!ret) {
@@ -223,7 +222,7 @@ lua_rsa_privkey_save(lua_State *L)
static int
lua_rsa_pubkey_create(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey, **ppkey;
const char *buf;
BIO *bp;
@@ -231,15 +230,15 @@ lua_rsa_pubkey_create(lua_State *L)
if (buf != NULL) {
bp = BIO_new_mem_buf((void *) buf, -1);
- if (!PEM_read_bio_RSA_PUBKEY(bp, &rsa, NULL, NULL)) {
+ if (!PEM_read_bio_PUBKEY(bp, &pkey, NULL, NULL)) {
msg_err("cannot parse pubkey: %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_pubkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
BIO_free(bp);
}
@@ -252,10 +251,10 @@ lua_rsa_pubkey_create(lua_State *L)
static int
lua_rsa_pubkey_gc(lua_State *L)
{
- RSA *rsa = lua_check_rsa_pubkey(L, 1);
+ EVP_PKEY *pkey = lua_check_rsa_pubkey(L, 1);
- if (rsa != NULL) {
- RSA_free(rsa);
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
}
return 0;
@@ -264,18 +263,18 @@ lua_rsa_pubkey_gc(lua_State *L)
static int
lua_rsa_pubkey_tostring(lua_State *L)
{
- RSA *rsa = lua_check_rsa_pubkey(L, 1);
+ EVP_PKEY *pkey = lua_check_rsa_pubkey(L, 1);
- if (rsa != NULL) {
+ if (pkey != NULL) {
BIO *pubout = BIO_new(BIO_s_mem());
const char *pubdata;
gsize publen;
- int rc = i2d_RSA_PUBKEY_bio(pubout, rsa);
+ int rc = i2d_PUBKEY_bio(pubout, pkey);
if (rc != 1) {
BIO_free(pubout);
- return luaL_error(L, "i2d_RSA_PUBKEY_bio failed");
+ return luaL_error(L, "i2d_PUBKEY_bio failed");
}
publen = BIO_get_mem_data(pubout, &pubdata);
@@ -292,7 +291,7 @@ lua_rsa_pubkey_tostring(lua_State *L)
static int
lua_rsa_privkey_load_file(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
const char *filename;
FILE *f;
@@ -306,15 +305,15 @@ lua_rsa_privkey_load_file(lua_State *L)
lua_pushnil(L);
}
else {
- if (!PEM_read_RSAPrivateKey(f, &rsa, NULL, NULL)) {
+ if (!PEM_read_PrivateKey(f, &pkey, NULL, NULL)) {
msg_err("cannot open private key from file: %s, %s", filename,
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
fclose(f);
}
@@ -328,7 +327,7 @@ lua_rsa_privkey_load_file(lua_State *L)
static int
lua_rsa_privkey_load_pem(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
BIO *b;
struct rspamd_lua_text *t;
const char *data;
@@ -351,15 +350,15 @@ lua_rsa_privkey_load_pem(lua_State *L)
if (data != NULL) {
b = BIO_new_mem_buf(data, len);
- if (!PEM_read_bio_RSAPrivateKey(b, &rsa, NULL, NULL)) {
+ if (!PEM_read_bio_PrivateKey(b, &pkey, NULL, NULL)) {
msg_err("cannot open private key from data, %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
BIO_free(b);
@@ -374,7 +373,7 @@ lua_rsa_privkey_load_pem(lua_State *L)
static int
lua_rsa_privkey_load_raw(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
BIO *b;
struct rspamd_lua_text *t;
const char *data;
@@ -396,17 +395,17 @@ lua_rsa_privkey_load_raw(lua_State *L)
if (data != NULL) {
b = BIO_new_mem_buf(data, len);
- rsa = d2i_RSAPrivateKey_bio(b, NULL);
+ pkey = d2i_PrivateKey_bio(b, NULL);
- if (rsa == NULL) {
+ if (pkey == NULL) {
msg_err("cannot open private key from data, %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
BIO_free(b);
@@ -421,9 +420,8 @@ lua_rsa_privkey_load_raw(lua_State *L)
static int
lua_rsa_privkey_load_base64(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
BIO *b;
- EVP_PKEY *evp = NULL;
struct rspamd_lua_text *t;
const char *data;
unsigned char *decoded;
@@ -454,21 +452,18 @@ lua_rsa_privkey_load_base64(lua_State *L)
b = BIO_new_mem_buf(decoded, dec_len);
- if (d2i_PrivateKey_bio(b, &evp) != NULL) {
- rsa = EVP_PKEY_get1_RSA(evp);
-
- if (rsa == NULL) {
+ if (d2i_PrivateKey_bio(b, &pkey) != NULL) {
+ if (pkey == NULL) {
msg_err("cannot open RSA private key from data, %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
- EVP_PKEY_free(evp);
}
else {
msg_err("cannot open EVP private key from data, %s",
@@ -489,7 +484,7 @@ lua_rsa_privkey_load_base64(lua_State *L)
static int
lua_rsa_privkey_create(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
const char *buf;
BIO *bp;
@@ -497,15 +492,15 @@ lua_rsa_privkey_create(lua_State *L)
if (buf != NULL) {
bp = BIO_new_mem_buf((void *) buf, -1);
- if (!PEM_read_bio_RSAPrivateKey(bp, &rsa, NULL, NULL)) {
+ if (!PEM_read_bio_PrivateKey(bp, &pkey, NULL, NULL)) {
msg_err("cannot parse private key: %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
BIO_free(bp);
}
@@ -518,10 +513,10 @@ lua_rsa_privkey_create(lua_State *L)
static int
lua_rsa_privkey_gc(lua_State *L)
{
- RSA *rsa = lua_check_rsa_privkey(L, 1);
+ EVP_PKEY *pkey = lua_check_rsa_privkey(L, 1);
- if (rsa != NULL) {
- RSA_free(rsa);
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
}
return 0;
@@ -699,19 +694,22 @@ lua_rsa_signature_base64(lua_State *L)
static int
lua_rsa_verify_memory(lua_State *L)
{
- RSA *rsa;
+ EVP_PKEY *pkey;
rspamd_fstring_t *signature;
const char *data;
gsize sz;
int ret;
- rsa = lua_check_rsa_pubkey(L, 1);
+ pkey = lua_check_rsa_pubkey(L, 1);
signature = lua_check_rsa_sign(L, 2);
data = luaL_checklstring(L, 3, &sz);
- if (rsa != NULL && signature != NULL && data != NULL) {
- ret = RSA_verify(NID_sha256, data, sz,
- signature->str, signature->len, rsa);
+ if (pkey != NULL && signature != NULL && data != NULL) {
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ g_assert(pctx != NULL);
+ g_assert(EVP_PKEY_verify_init(pctx) == 1);
+
+ ret = EVP_PKEY_verify(pctx, signature->str, signature->len, data, sz);
if (ret == 0) {
lua_pushboolean(L, FALSE);
@@ -722,6 +720,7 @@ lua_rsa_verify_memory(lua_State *L)
else {
lua_pushboolean(L, TRUE);
}
+ EVP_PKEY_CTX_free(pctx);
}
else {
lua_pushnil(L);
@@ -743,22 +742,26 @@ lua_rsa_verify_memory(lua_State *L)
static int
lua_rsa_sign_memory(lua_State *L)
{
- RSA *rsa;
+ EVP_PKEY *pkey;
rspamd_fstring_t *signature, **psig;
const char *data;
gsize sz;
int ret;
- rsa = lua_check_rsa_privkey(L, 1);
+ pkey = lua_check_rsa_privkey(L, 1);
data = luaL_checklstring(L, 2, &sz);
- if (rsa != NULL && data != NULL) {
- signature = rspamd_fstring_sized_new(RSA_size(rsa));
+ if (pkey != NULL && data != NULL) {
+ signature = rspamd_fstring_sized_new(EVP_PKEY_get_size(pkey));
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ g_assert(pctx != NULL);
- unsigned int siglen = signature->len;
- ret = RSA_sign(NID_sha256, data, sz,
- signature->str, &siglen, rsa);
+ g_assert(EVP_PKEY_sign_init(pctx) == 1);
+ size_t slen = signature->allocated;
+ ret = EVP_PKEY_sign(pctx, signature->str, &slen, data, sz);
+ EVP_PKEY_CTX_free(pctx);
if (ret != 1) {
rspamd_fstring_free(signature);
@@ -766,7 +769,7 @@ lua_rsa_sign_memory(lua_State *L)
ERR_error_string(ERR_get_error(), NULL));
}
else {
- signature->len = siglen;
+ signature->len = slen;
psig = lua_newuserdata(L, sizeof(rspamd_fstring_t *));
rspamd_lua_setclass(L, rspamd_rsa_signature_classname, -1);
*psig = signature;
@@ -783,7 +786,7 @@ static int
lua_rsa_keypair(lua_State *L)
{
BIGNUM *e;
- RSA *rsa, *pub_rsa, *priv_rsa, **prsa;
+ EVP_PKEY *pkey = NULL, *pub_pkey, *priv_pkey, **ppkey;
int bits = lua_gettop(L) > 0 ? lua_tointeger(L, 1) : 1024;
if (bits > 4096 || bits < 512) {
@@ -791,21 +794,30 @@ lua_rsa_keypair(lua_State *L)
}
e = BN_new();
- rsa = RSA_new();
+
g_assert(BN_set_word(e, RSA_F4) == 1);
- g_assert(RSA_generate_key_ex(rsa, bits, e, NULL) == 1);
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
+ g_assert(pctx != NULL);
+ g_assert(EVP_PKEY_keygen_init(pctx) == 1);
+
+ g_assert(EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, bits) == 1);
+ g_assert(EVP_PKEY_CTX_set1_rsa_keygen_pubexp(pctx, e) == 1);
+
+ g_assert(EVP_PKEY_keygen(pctx, &pkey) == 1);
+ g_assert(pkey != NULL);
- priv_rsa = RSAPrivateKey_dup(rsa);
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ priv_pkey = EVP_PKEY_dup(pkey);
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = priv_rsa;
+ *ppkey = priv_pkey;
- pub_rsa = RSAPublicKey_dup(rsa);
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ pub_pkey = EVP_PKEY_dup(pkey);
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_pubkey_classname, -1);
- *prsa = pub_rsa;
+ *ppkey = pub_pkey;
- RSA_free(rsa);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(pctx);
BN_free(e);
return 2;
diff --git a/src/lua/lua_spf.c b/src/lua/lua_spf.c
index 46e72202f..850ce2120 100644
--- a/src/lua/lua_spf.c
+++ b/src/lua/lua_spf.c
@@ -89,6 +89,8 @@ lua_load_spf(lua_State *L)
lua_setfield(L, -2, "perm_fail");
lua_pushinteger(L, RSPAMD_SPF_FLAG_CACHED);
lua_setfield(L, -2, "cached");
+ lua_pushinteger(L, RSPAMD_SPF_RESOLVED_PLUSALL);
+ lua_setfield(L, -2, "plusall");
lua_setfield(L, -2, "flags");
@@ -368,6 +370,11 @@ spf_check_element(lua_State *L, struct spf_resolved *rec, struct spf_addr *addr,
lua_pushinteger(L, RSPAMD_SPF_RESOLVED_TEMP_FAILED);
lua_pushfstring(L, "%cany", spf_mech_char(addr->mech));
}
+ else if (rec->flags & RSPAMD_SPF_RESOLVED_PLUSALL) {
+ lua_pushboolean(L, false);
+ lua_pushinteger(L, RSPAMD_SPF_RESOLVED_PLUSALL);
+ lua_pushfstring(L, "%cany", spf_mech_char(addr->mech));
+ }
else {
lua_pushboolean(L, true);
lua_pushinteger(L, addr->mech);
diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c
index 21e24fc45..3968c01eb 100644
--- a/src/lua/lua_task.c
+++ b/src/lua/lua_task.c
@@ -1318,6 +1318,7 @@ static const struct luaL_reg tasklib_m[] = {
LUA_INTERFACE_DEF(task, get_metric_threshold),
LUA_INTERFACE_DEF(task, set_metric_score),
LUA_INTERFACE_DEF(task, set_metric_subject),
+ {"set_subject", lua_task_set_metric_subject},
LUA_INTERFACE_DEF(task, learn),
LUA_INTERFACE_DEF(task, set_settings),
LUA_INTERFACE_DEF(task, get_settings),
diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c
index a035eeaae..91b77c702 100644
--- a/src/plugins/fuzzy_check.c
+++ b/src/plugins/fuzzy_check.c
@@ -543,15 +543,13 @@ fuzzy_parse_rule(struct rspamd_config *cfg, const ucl_object_t *obj,
k = ucl_object_tostring(value);
if (k == NULL || (rule->peer_key =
- rspamd_pubkey_from_base32(k, 0, RSPAMD_KEYPAIR_KEX,
- RSPAMD_CRYPTOBOX_MODE_25519)) == NULL) {
+ rspamd_pubkey_from_base32(k, 0, RSPAMD_KEYPAIR_KEX)) == NULL) {
msg_err_config("bad encryption key value: %s",
k);
return -1;
}
- rule->local_key = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ rule->local_key = rspamd_keypair_new(RSPAMD_KEYPAIR_KEX);
}
if ((value = ucl_object_lookup(obj, "learn_condition")) != NULL) {
@@ -1334,8 +1332,7 @@ fuzzy_encrypt_cmd(struct fuzzy_rule *rule,
rule->local_key, rule->peer_key);
rspamd_cryptobox_encrypt_nm_inplace(data, datalen,
hdr->nonce, rspamd_pubkey_get_nm(rule->peer_key, rule->local_key),
- hdr->mac,
- rspamd_pubkey_alg(rule->peer_key));
+ hdr->mac);
}
static struct fuzzy_cmd_io *
@@ -2209,8 +2206,7 @@ fuzzy_process_reply(unsigned char **pos, int *r, GPtrArray *req,
sizeof(encrep.rep),
encrep.hdr.nonce,
rspamd_pubkey_get_nm(rule->peer_key, rule->local_key),
- encrep.hdr.mac,
- rspamd_pubkey_alg(rule->peer_key))) {
+ encrep.hdr.mac)) {
msg_info("cannot decrypt reply");
return NULL;
}
@@ -2299,6 +2295,8 @@ fuzzy_insert_result(struct fuzzy_client_session *session,
* Otherwise `value` means error code
*/
+ msg_debug_fuzzy_check("got reply with probability %.2f and value %.2f",
+ (double) rep->v1.prob, (double) rep->v1.value);
nval = fuzzy_normalize(rep->v1.value, weight);
if (io) {
diff --git a/src/plugins/lua/arc.lua b/src/plugins/lua/arc.lua
index ff19aef4c..90e254e78 100644
--- a/src/plugins/lua/arc.lua
+++ b/src/plugins/lua/arc.lua
@@ -635,11 +635,21 @@ local function prepare_arc_selector(task, sel)
end
end
+ local function arc_result_from_ar(ar_header)
+ ar_header = ar_header or ""
+ for k, v in string.gmatch(ar_header, "(%w+)=(%w+)") do
+ if k == 'arc' then
+ return v
+ end
+ end
+ return nil
+ end
+
if settings.reuse_auth_results then
local ar_header = task:get_header('Authentication-Results')
if ar_header then
- local arc_match = string.match(ar_header, 'arc=(%w+)')
+ local arc_match = arc_result_from_ar(ar_header)
if arc_match then
if arc_match == 'none' or arc_match == 'pass' then
diff --git a/src/plugins/lua/gpt.lua b/src/plugins/lua/gpt.lua
index 6adbce3bf..823dbd045 100644
--- a/src/plugins/lua/gpt.lua
+++ b/src/plugins/lua/gpt.lua
@@ -27,13 +27,11 @@ gpt {
# Your key to access the API
api_key = "xxx";
# Model name
- model = "gpt-3.5-turbo";
+ model = "gpt-4o-mini";
# Maximum tokens to generate
max_tokens = 1000;
# Temperature for sampling
- temperature = 0.7;
- # Top p for sampling
- top_p = 0.9;
+ temperature = 0.0;
# Timeout for requests
timeout = 10s;
# Prompt for the model (use default if not set)
@@ -71,10 +69,9 @@ local default_symbols_to_except = {
local settings = {
type = 'openai',
api_key = nil,
- model = 'gpt-3.5-turbo',
+ model = 'gpt-4o-mini',
max_tokens = 1000,
- temperature = 0.7,
- top_p = 0.9,
+ temperature = 0.0,
timeout = 10,
prompt = nil,
condition = nil,
@@ -97,11 +94,11 @@ local function default_condition(task)
local action = result.action
if action == 'reject' and result.npositive > 1 then
- return true, 'already decided as spam'
+ return false, 'already decided as spam'
end
if action == 'no action' and score < 0 then
- return true, 'negative score, already decided as ham'
+ return false, 'negative score, already decided as ham'
end
end
-- We also exclude some symbols
@@ -109,10 +106,12 @@ local function default_condition(task)
if task:has_symbol(s) then
if required_weight > 0 then
-- Also check score
- local sym = task:get_symbol(s)
+ local sym = task:get_symbol(s) or E
-- Must exist as we checked it before with `has_symbol`
- if math.abs(sym.weight) >= required_weight then
- return false, 'skip as "' .. s .. '" is found (weight: ' .. sym.weight .. ')'
+ if sym.weight then
+ if math.abs(sym.weight) >= required_weight then
+ return false, 'skip as "' .. s .. '" is found (weight: ' .. sym.weight .. ')'
+ end
end
lua_util.debugm(N, task, 'symbol %s has weight %s, but required %s', s,
sym.weight, required_weight)
@@ -195,6 +194,18 @@ local function default_conversion(task, input)
if type(reply) == 'table' and reply.probability then
local spam_score = tonumber(reply.probability)
+
+ if not spam_score then
+ -- Maybe we need GPT to convert GPT reply here?
+ if reply.probability == "high" then
+ spam_score = 0.9
+ elseif reply.probability == "low" then
+ spam_score = 0.1
+ else
+ rspamd_logger.infox("cannot convert to spam probability: %s", reply.probability)
+ end
+ end
+
if type(reply.usage) == 'table' then
rspamd_logger.infox(task, 'usage: %s tokens', reply.usage.total_tokens)
end
@@ -276,7 +287,7 @@ local function openai_gpt_check(task)
model = settings.model,
max_tokens = settings.max_tokens,
temperature = settings.temperature,
- top_p = settings.top_p,
+ response_format = { type = "json_object" },
messages = {
{
role = 'system',
@@ -348,8 +359,8 @@ if opts then
end
if not settings.prompt then
- settings.prompt = "You will be provided with the email message, " ..
- "and your task is to classify its probability to be spam, " ..
+ settings.prompt = "You will be provided with the email message, subject, from and url domains, " ..
+ "and your task is to evaluate the probability to be spam as number from 0 to 1, " ..
"output result as JSON with 'probability' field."
end
diff --git a/src/plugins/lua/history_redis.lua b/src/plugins/lua/history_redis.lua
index 3365b30cd..fff9f46b3 100644
--- a/src/plugins/lua/history_redis.lua
+++ b/src/plugins/lua/history_redis.lua
@@ -21,8 +21,8 @@ if confighelp then
redis_history {
# History key name
key_prefix = 'rs_history{{HOSTNAME}}{{COMPRESS}}';
- # History expire in seconds
- expire = 0;
+ # Expire in seconds for inactive keys, default to 5 days
+ expire = 432000;
# History rows limit
nrows = 200;
# Use zstd compression when storing data in redis
diff --git a/src/plugins/lua/known_senders.lua b/src/plugins/lua/known_senders.lua
index 6d57acea3..5cb2ddcf5 100644
--- a/src/plugins/lua/known_senders.lua
+++ b/src/plugins/lua/known_senders.lua
@@ -18,6 +18,7 @@ limitations under the License.
local rspamd_logger = require "rspamd_logger"
local N = 'known_senders'
+local E = {}
local lua_util = require "lua_util"
local lua_redis = require "lua_redis"
local lua_maps = require "lua_maps"
@@ -258,7 +259,7 @@ local function verify_local_replies_set(task)
return nil
end
- local replies_recipients = task:get_recipients('mime')
+ local replies_recipients = task:get_recipients('mime') or E
local replies_sender_string = lua_util.maybe_obfuscate_string(tostring(replies_sender), settings,
settings.sender_prefix)
diff --git a/src/plugins/lua/once_received.lua b/src/plugins/lua/once_received.lua
index 2a5552ab9..5c5ff7986 100644
--- a/src/plugins/lua/once_received.lua
+++ b/src/plugins/lua/once_received.lua
@@ -19,10 +19,7 @@ if confighelp then
end
-- 0 or 1 received: = spam
-
local symbol = 'ONCE_RECEIVED'
-local symbol_rdns = 'RDNS_NONE'
-local symbol_rdns_dnsfail = 'RDNS_DNSFAIL'
local symbol_mx = 'DIRECT_TO_MX'
-- Symbol for strict checks
local symbol_strict = nil
@@ -47,54 +44,6 @@ local function check_quantity_received (task)
return not h['flags']['artificial']
end, recvh))
- local function recv_dns_cb(_, to_resolve, results, err)
- if err and (err ~= 'requested record is not found' and err ~= 'no records with this name') then
- rspamd_logger.errx(task, 'error looking up %s: %s', to_resolve, err)
- task:insert_result(symbol_rdns_dnsfail, 1.0)
- end
-
- if not results then
- if nreceived <= 1 then
- task:insert_result(symbol, 1)
- -- Avoid strict symbol inserting as the remaining symbols have already
- -- quote a significant weight, so a message could be rejected by just
- -- this property.
- --task:insert_result(symbol_strict, 1)
- -- Check for MUAs
- local ua = task:get_header('User-Agent')
- local xm = task:get_header('X-Mailer')
- if (ua or xm) then
- task:insert_result(symbol_mx, 1, (ua or xm))
- end
- end
- task:insert_result(symbol_rdns, 1)
- else
- rspamd_logger.infox(task, 'source hostname has not been passed to Rspamd from MTA, ' ..
- 'but we could resolve source IP address PTR %s as "%s"',
- to_resolve, results[1])
- task:set_hostname(results[1])
-
- if good_hosts then
- for _, gh in ipairs(good_hosts) do
- if string.find(results[1], gh) then
- return
- end
- end
- end
-
- if nreceived <= 1 then
- task:insert_result(symbol, 1)
- for _, h in ipairs(bad_hosts) do
- if string.find(results[1], h) then
-
- task:insert_result(symbol_strict, 1, h)
- return
- end
- end
- end
- end
- end
-
local task_ip = task:get_ip()
if ((not check_authed and task:get_user()) or
@@ -110,13 +59,39 @@ local function check_quantity_received (task)
local hn = task:get_hostname()
-- Here we don't care about received
- if (not hn) and task_ip and task_ip:is_valid() then
- task:get_resolver():resolve_ptr({ task = task,
- name = task_ip:to_string(),
- callback = recv_dns_cb,
- forced = true
- })
+ if not hn then
+ if nreceived <= 1 then
+ task:insert_result(symbol, 1)
+ -- Avoid strict symbol inserting as the remaining symbols have already
+ -- quote a significant weight, so a message could be rejected by just
+ -- this property.
+ --task:insert_result(symbol_strict, 1)
+ -- Check for MUAs
+ local ua = task:get_header('User-Agent')
+ local xm = task:get_header('X-Mailer')
+ if (ua or xm) then
+ task:insert_result(symbol_mx, 1, (ua or xm))
+ end
+ end
return
+ else
+ if good_hosts then
+ for _, gh in ipairs(good_hosts) do
+ if string.find(hn, gh) then
+ return
+ end
+ end
+ end
+
+ if nreceived <= 1 then
+ task:insert_result(symbol, 1)
+ for _, h in ipairs(bad_hosts) do
+ if string.find(hn, h) then
+ task:insert_result(symbol_strict, 1, h)
+ break
+ end
+ end
+ end
end
if nreceived <= 1 then
@@ -181,10 +156,6 @@ if opts then
for n, v in pairs(opts) do
if n == 'symbol_strict' then
symbol_strict = v
- elseif n == 'symbol_rdns' then
- symbol_rdns = v
- elseif n == 'symbol_rdns_dnsfail' then
- symbol_rdns_dnsfail = v
elseif n == 'bad_host' then
if type(v) == 'string' then
bad_hosts[1] = v
@@ -207,16 +178,6 @@ if opts then
end
rspamd_config:register_symbol({
- name = symbol_rdns,
- type = 'virtual',
- parent = id
- })
- rspamd_config:register_symbol({
- name = symbol_rdns_dnsfail,
- type = 'virtual',
- parent = id
- })
- rspamd_config:register_symbol({
name = symbol_strict,
type = 'virtual',
parent = id
diff --git a/src/plugins/lua/spf.lua b/src/plugins/lua/spf.lua
index 48f3c17be..356507250 100644
--- a/src/plugins/lua/spf.lua
+++ b/src/plugins/lua/spf.lua
@@ -56,6 +56,7 @@ local symbols = {
dnsfail = "R_SPF_DNSFAIL",
permfail = "R_SPF_PERMFAIL",
na = "R_SPF_NA",
+ plusall = "R_SPF_PLUSALL",
}
local default_config = {
@@ -118,6 +119,8 @@ local function spf_check_callback(task)
local function flag_to_symbol(fl)
if bit.band(fl, rspamd_spf.flags.temp_fail) ~= 0 then
return local_config.symbols.dnsfail
+ elseif bit.band(fl, rspamd_spf.flags.plusall) ~= 0 then
+ return local_config.symbols.plusall
elseif bit.band(fl, rspamd_spf.flags.perm_fail) ~= 0 then
return local_config.symbols.permfail
elseif bit.band(fl, rspamd_spf.flags.na) ~= 0 then
diff --git a/src/rspamadm/configdump.c b/src/rspamadm/configdump.c
index 167b4c891..456875cf2 100644
--- a/src/rspamadm/configdump.c
+++ b/src/rspamadm/configdump.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Vsevolod Stakhov
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -445,6 +445,9 @@ rspamadm_configdump(int argc, char **argv, const struct rspamadm_command *cmd)
ucl_object_fromdouble(gr->max_score),
"max_score", strlen("max_score"), false);
ucl_object_insert_key(gr_ucl,
+ ucl_object_fromdouble(gr->min_score),
+ "min_score", strlen("min_score"), false);
+ ucl_object_insert_key(gr_ucl,
ucl_object_fromstring(gr->description),
"description", strlen("description"), false);
diff --git a/src/rspamadm/signtool.c b/src/rspamadm/signtool.c
index 612a67c83..ddc3d45df 100644
--- a/src/rspamadm/signtool.c
+++ b/src/rspamadm/signtool.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,7 +27,6 @@
#include <sys/wait.h>
#endif
-static gboolean openssl = FALSE;
static gboolean verify = FALSE;
static gboolean quiet = FALSE;
static char *suffix = NULL;
@@ -37,7 +36,6 @@ static char *pubout = NULL;
static char *keypair_file = NULL;
static char *editor = NULL;
static gboolean edit = FALSE;
-enum rspamd_cryptobox_mode mode = RSPAMD_CRYPTOBOX_MODE_25519;
static void rspamadm_signtool(int argc, char **argv,
const struct rspamadm_command *cmd);
@@ -53,8 +51,6 @@ struct rspamadm_command signtool_command = {
};
static GOptionEntry entries[] = {
- {"openssl", 'o', 0, G_OPTION_ARG_NONE, &openssl,
- "Generate openssl nistp256 keypair not curve25519 one", NULL},
{"verify", 'v', 0, G_OPTION_ARG_NONE, &verify,
"Verify signatures and not sign", NULL},
{"suffix", 'S', 0, G_OPTION_ARG_STRING, &suffix,
@@ -327,11 +323,8 @@ rspamadm_sign_file(const char *fname, struct rspamd_cryptobox_keypair *kp)
exit(EXIT_FAILURE);
}
- g_assert(rspamd_cryptobox_MAX_SIGBYTES >=
- rspamd_cryptobox_signature_bytes(mode));
-
sk = rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL);
- rspamd_cryptobox_sign(sig, NULL, map, st.st_size, sk, mode);
+ rspamd_cryptobox_sign(sig, NULL, map, st.st_size, sk);
if (edit) {
/* We also need to rename .new file */
@@ -348,7 +341,7 @@ rspamadm_sign_file(const char *fname, struct rspamd_cryptobox_keypair *kp)
rspamd_snprintf(sigpath, sizeof(sigpath), "%s%s", fname, suffix);
- if (write(fd_sig, sig, rspamd_cryptobox_signature_bytes(mode)) == -1) {
+ if (write(fd_sig, sig, crypto_sign_bytes()) == -1) {
rspamd_fprintf(stderr, "cannot write signature to %s: %s\n", sigpath,
strerror(errno));
exit(EXIT_FAILURE);
@@ -400,9 +393,6 @@ rspamadm_verify_file(const char *fname, const unsigned char *pk)
struct stat st, st_sig;
bool ret;
- g_assert(rspamd_cryptobox_MAX_SIGBYTES >=
- rspamd_cryptobox_signature_bytes(mode));
-
if (suffix == NULL) {
suffix = ".sig";
}
@@ -439,7 +429,7 @@ rspamadm_verify_file(const char *fname, const unsigned char *pk)
g_assert(fstat(fd_sig, &st_sig) != -1);
- if (st_sig.st_size != rspamd_cryptobox_signature_bytes(mode)) {
+ if (st_sig.st_size != crypto_sign_bytes()) {
close(fd_sig);
rspamd_fprintf(stderr, "invalid signature size %s: %ud\n", fname,
(unsigned int) st_sig.st_size);
@@ -458,7 +448,7 @@ rspamadm_verify_file(const char *fname, const unsigned char *pk)
}
ret = rspamd_cryptobox_verify(map_sig, st_sig.st_size,
- map, st.st_size, pk, mode);
+ map, st.st_size, pk);
munmap(map, st.st_size);
munmap(map_sig, st_sig.st_size);
@@ -503,10 +493,6 @@ rspamadm_signtool(int argc, char **argv, const struct rspamadm_command *cmd)
g_option_context_free(context);
- if (openssl) {
- mode = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
-
if (verify && (!pubkey && !pubkey_file)) {
rspamd_fprintf(stderr, "no pubkey for verification\n");
exit(EXIT_FAILURE);
@@ -549,14 +535,13 @@ rspamadm_signtool(int argc, char **argv, const struct rspamadm_command *cmd)
flen--;
}
- pk = rspamd_pubkey_from_base32(map, flen,
- RSPAMD_KEYPAIR_SIGN, mode);
+ pk = rspamd_pubkey_from_base32(map, flen, RSPAMD_KEYPAIR_SIGN);
if (pk == NULL) {
rspamd_fprintf(stderr, "bad size %s: %ud, %ud expected\n",
pubkey_file,
(unsigned int) flen,
- rspamd_cryptobox_pk_sig_bytes(mode));
+ crypto_sign_publickeybytes());
exit(EXIT_FAILURE);
}
@@ -564,13 +549,13 @@ rspamadm_signtool(int argc, char **argv, const struct rspamadm_command *cmd)
}
else {
pk = rspamd_pubkey_from_base32(pubkey, strlen(pubkey),
- RSPAMD_KEYPAIR_SIGN, mode);
+ RSPAMD_KEYPAIR_SIGN);
if (pk == NULL) {
rspamd_fprintf(stderr, "bad size %s: %ud, %ud expected\n",
pubkey_file,
(unsigned int) strlen(pubkey),
- rspamd_cryptobox_pk_sig_bytes(mode));
+ crypto_sign_publickeybytes());
exit(EXIT_FAILURE);
}
}
diff --git a/src/rspamd_proxy.c b/src/rspamd_proxy.c
index 4f08e81b9..dbdd2e5a7 100644
--- a/src/rspamd_proxy.c
+++ b/src/rspamd_proxy.c
@@ -395,7 +395,7 @@ rspamd_proxy_parse_upstream(rspamd_mempool_t *pool,
elt = ucl_object_lookup(obj, "key");
if (elt != NULL) {
up->key = rspamd_pubkey_from_base32(ucl_object_tostring(elt), 0,
- RSPAMD_KEYPAIR_KEX, RSPAMD_CRYPTOBOX_MODE_25519);
+ RSPAMD_KEYPAIR_KEX);
if (up->key == NULL) {
g_set_error(err, rspamd_proxy_quark(), 100,
@@ -571,7 +571,7 @@ rspamd_proxy_parse_mirror(rspamd_mempool_t *pool,
elt = ucl_object_lookup(obj, "key");
if (elt != NULL) {
up->key = rspamd_pubkey_from_base32(ucl_object_tostring(elt), 0,
- RSPAMD_KEYPAIR_KEX, RSPAMD_CRYPTOBOX_MODE_25519);
+ RSPAMD_KEYPAIR_KEX);
if (up->key == NULL) {
g_set_error(err, rspamd_proxy_quark(), 100,
@@ -1398,7 +1398,8 @@ proxy_backend_mirror_finish_handler(struct rspamd_http_connection *conn,
bk_conn->err = "cannot parse ucl";
}
- msg_info_session("finished mirror connection to %s", bk_conn->name);
+ msg_info_session("finished mirror connection to %s; HTTP code: %d",
+ bk_conn->name, msg->code);
rspamd_upstream_ok(bk_conn->up);
proxy_backend_close_connection(bk_conn);
@@ -2203,6 +2204,8 @@ proxy_client_finish_handler(struct rspamd_http_connection *conn,
rspamd_http_message_remove_header(msg, "Keep-Alive");
rspamd_http_message_remove_header(msg, "Connection");
rspamd_http_message_remove_header(msg, "Key");
+ rspamd_http_message_add_header_len(msg, LOG_TAG_HEADER, session->pool->tag.uid,
+ sizeof(session->pool->tag.uid));
proxy_open_mirror_connections(session);
rspamd_http_connection_reset(session->client_conn);
@@ -2210,7 +2213,10 @@ proxy_client_finish_handler(struct rspamd_http_connection *conn,
proxy_send_master_message(session);
}
else {
- msg_info_session("finished master connection");
+ msg_info_session("finished master connection to %s; HTTP code: %d",
+ rspamd_inet_address_to_string_pretty(
+ rspamd_upstream_addr_cur(session->master_conn->up)),
+ msg->code);
proxy_backend_close_connection(session->master_conn);
REF_RELEASE(session);
}