diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2023-04-07 16:38:50 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rspamd.com> | 2023-04-07 16:39:22 +0100 |
commit | a070e5a10a3084bf75472177bedfacc612c25071 (patch) | |
tree | 347823c471e0fd3ae2c88c9d0b5ded83a3cd3212 /src | |
parent | 58bd6be3f7f9302e51ae4031658311f9cc9842d8 (diff) | |
download | rspamd-a070e5a10a3084bf75472177bedfacc612c25071.tar.gz rspamd-a070e5a10a3084bf75472177bedfacc612c25071.zip |
[Feature] Finish all features of dkim_keygen in Lua
Diffstat (limited to 'src')
-rw-r--r-- | src/lua/lua_cryptobox.c | 33 | ||||
-rw-r--r-- | src/lua/lua_text.c | 4 | ||||
-rw-r--r-- | src/rspamadm/dkim_keygen.c | 385 |
3 files changed, 35 insertions, 387 deletions
diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c index e342610ce..2a7b0c202 100644 --- a/src/lua/lua_cryptobox.c +++ b/src/lua/lua_cryptobox.c @@ -2700,6 +2700,39 @@ lua_cryptobox_gen_dkim_keypair (lua_State *L) rspamd_explicit_memzero (pk, sizeof (pk)); rspamd_explicit_memzero (sk, sizeof (sk)); } + else if (strcmp (alg_str, "ed25519-seed") == 0) { + rspamd_sig_pk_t pk; + rspamd_sig_sk_t sk; + gchar *b64_data; + gsize b64_len; + + rspamd_cryptobox_keypair_sig (pk, sk, RSPAMD_CRYPTOBOX_MODE_25519); + + /* Process private key */ + b64_data = rspamd_encode_base64 (sk, + 32, + -1, &b64_len); + + priv_out = lua_newuserdata (L, sizeof (*priv_out)); + rspamd_lua_setclass (L, "rspamd{text}", -1); + priv_out->start = b64_data; + priv_out->len = b64_len; + priv_out->flags = RSPAMD_TEXT_FLAG_OWN|RSPAMD_TEXT_FLAG_WIPE; + + /* Process public key */ + b64_data = rspamd_encode_base64 (pk, + rspamd_cryptobox_pk_sig_bytes (RSPAMD_CRYPTOBOX_MODE_25519), + -1, &b64_len); + + pub_out = lua_newuserdata (L, sizeof (*pub_out)); + rspamd_lua_setclass (L, "rspamd{text}", -1); + pub_out->start = b64_data; + pub_out->len = b64_len; + pub_out->flags = RSPAMD_TEXT_FLAG_OWN; + + rspamd_explicit_memzero (pk, sizeof (pk)); + rspamd_explicit_memzero (sk, sizeof (sk)); + } else { return luaL_error (L, "invalid algorithm %s", alg_str); } diff --git a/src/lua/lua_text.c b/src/lua/lua_text.c index b6f0948c3..bafab3c08 100644 --- a/src/lua/lua_text.c +++ b/src/lua/lua_text.c @@ -1118,12 +1118,12 @@ lua_text_save_in_file (lua_State *L) fname = luaL_checkstring (L, 2); if (lua_type (L, 3) == LUA_TNUMBER) { - mode = lua_tonumber (L, 3); + mode = lua_tointeger(L, 3); } } else if (lua_type (L, 2) == LUA_TNUMBER) { /* Created fd */ - fd = lua_tonumber (L, 2); + fd = lua_tointeger (L, 2); } if (fd == -1) { diff --git a/src/rspamadm/dkim_keygen.c b/src/rspamadm/dkim_keygen.c deleted file mode 100644 index 1bbb71775..000000000 --- a/src/rspamadm/dkim_keygen.c +++ /dev/null @@ -1,385 +0,0 @@ -/*- - * Copyright 2016 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "config.h" -#include "rspamadm.h" -#include "printf.h" -#include "str_util.h" -#include "libcryptobox/cryptobox.h" -#include "contrib/libottery/ottery.h" -#include "lua/lua_common.h" -#include "unix-std.h" - -#include <openssl/rsa.h> -#include <openssl/bn.h> -#include <openssl/pem.h> - -static gchar *privkey_file = NULL; -static gchar *selector = NULL; -static gchar *domain = NULL; -static guint bits = 1024; -static gchar *type = "rsa"; - -static void rspamadm_dkim_keygen (gint argc, gchar **argv, - const struct rspamadm_command *cmd); -static const char *rspamadm_dkim_keygen_help (gboolean full_help, - const struct rspamadm_command *cmd); -static void rspamadm_dkim_keygen_lua_subrs (gpointer pL); - -struct rspamadm_command dkim_keygen_command = { - .name = "dkim_keygen", - .flags = 0, - .help = rspamadm_dkim_keygen_help, - .run = rspamadm_dkim_keygen, - .lua_subrs = rspamadm_dkim_keygen_lua_subrs, -}; - -static GOptionEntry entries[] = { - {"domain", 'd', 0, G_OPTION_ARG_STRING, &domain, - "Use the specified domain", NULL}, - {"selector", 's', 0, G_OPTION_ARG_STRING, &selector, - "Use the specified selector", NULL}, - {"privkey", 'k', 0, G_OPTION_ARG_STRING, &privkey_file, - "Save private key in the specified file", NULL}, - {"bits", 'b', 0, G_OPTION_ARG_INT, &bits, - "Set key length to N bits (1024 by default)", NULL}, - {"type", 't', 0, G_OPTION_ARG_STRING, &type, - "Key type: rsa or ed25519 (rsa by default)", NULL}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} -}; - -static const char * -rspamadm_dkim_keygen_help (gboolean full_help, const struct rspamadm_command *cmd) -{ - const char *help_str; - - if (full_help) { - help_str = "Create key pairs for dkim signing\n\n" - "Usage: rspamadm dkim_keygen -s selector -d domain [-k privkey] [-b bits]\n" - "Where options are:\n\n" - "-d: use the specified domain\n" - "-s: use the specified selector\n" - "-k: save private key to file instead of printing it to stdout\n" - "-b: set number of bits instead of 1024\n" - "--help: shows available options and commands"; - } - else { - help_str = "Create dkim key pairs"; - } - - return help_str; -} - -static void -rspamd_dkim_generate_rsa_keypair (const gchar *domain, const gchar *selector, - const gchar *priv_fname, const gchar *pub_fname, - guint keylen) -{ - BIGNUM *e; - RSA *r; - BIO *pubout, *privout; - EVP_PKEY *pk; - gint rc; - glong publen; - gsize b64_len; - gchar *pubdata, *b64_data; - FILE *pubfile = NULL; - - if (bits > 4096 || bits < 512) { - fprintf (stderr, "Bits number must be in the interval 512...4096\n"); - exit (EXIT_FAILURE); - } - - e = BN_new (); - r = RSA_new (); - pk = EVP_PKEY_new (); - g_assert (BN_set_word (e, RSA_F4) == 1); - g_assert (RSA_generate_key_ex (r, bits, e, NULL) == 1); - g_assert (EVP_PKEY_set1_RSA (pk, r) == 1); - - if (priv_fname) { - int fd = open (priv_fname, O_WRONLY | O_CREAT | O_TRUNC, 0640); - - if (fd < 0) { - rspamd_fprintf (stderr, "cannot open output file %s: %s\n", - priv_fname, strerror (errno)); - exit (EXIT_FAILURE); - } - - FILE *fp = fdopen (fd, "w"); - - if (fp == NULL) { - close (fd); - rspamd_fprintf (stderr, "cannot open output file %s: %s\n", - priv_fname, strerror (errno)); - exit (EXIT_FAILURE); - } - - privout = BIO_new_fp (fp, BIO_CLOSE); - - if (privout == NULL) { - fclose (fp); - rspamd_fprintf (stderr, "cannot open output file %s: %s\n", - priv_fname, strerror (errno)); - exit (EXIT_FAILURE); - } - } else { - privout = BIO_new_fp (stdout, BIO_NOCLOSE); - } - - rc = PEM_write_bio_PrivateKey (privout, pk, NULL, NULL, 0, NULL, NULL); - - if (rc != 1) { - rspamd_fprintf (stderr, "cannot write key to the output file %s: %s\n", - priv_fname ? priv_fname : "stdout", strerror (errno)); - exit (EXIT_FAILURE); - } - - BIO_free (privout); - fflush (stdout); - - pubout = BIO_new (BIO_s_mem ()); - - rc = i2d_RSA_PUBKEY_bio (pubout, r); - publen = BIO_get_mem_data (pubout, &pubdata); - - g_assert (publen > 0); - b64_data = rspamd_encode_base64 (pubdata, publen, -1, &b64_len); - - if (pub_fname) { - pubfile = fopen (pub_fname, "w"); - - if (pubfile == NULL) { - rspamd_fprintf (stderr, "cannot open output file %s: %s\n", - pub_fname, strerror (errno)); - exit (EXIT_FAILURE); - } - } else { - pubfile = stdout; - } - - if (b64_len < 255 - 2) { - rspamd_fprintf (pubfile, "%s._domainkey IN TXT ( \"v=DKIM1; k=rsa; \"\n" - "\t\"p=%s\" ) ;\n", - selector ? selector : "selector", - b64_data); - } else { - guint i; - gint step = 253, remain = b64_len; - - rspamd_fprintf (pubfile, "%s._domainkey IN TXT ( \"v=DKIM1; k=rsa; \"\n", - selector ? selector : "selector"); - - for (i = 0; i < b64_len; i += step, remain -= step) { - if (i == 0) { - rspamd_fprintf (pubfile, "\t\"p=%*s\"\n", MIN(step, remain), &b64_data[i]); - } else { - step = 255; - rspamd_fprintf (pubfile, "\t\"%*s\"\n", MIN(step, remain), &b64_data[i]); - } - } - - rspamd_fprintf (pubfile, ") ; \n"); - } - - if (pubfile != stdout) { - fclose (pubfile); - } - - g_free (b64_data); - BIO_free (pubout); - EVP_PKEY_free (pk); - RSA_free (r); - BN_free (e); -} - -static void -rspamd_dkim_generate_ed25519_keypair (const gchar *domain, const gchar *selector, - const gchar *priv_fname, const gchar *pub_fname, - guint keylen, gboolean seeded) -{ - rspamd_sig_sk_t ed_sk; - rspamd_sig_pk_t ed_pk; - gchar *base64_pk, *base64_sk; - FILE *pubfile = NULL, *privfile = NULL; - - rspamd_cryptobox_keypair_sig (ed_pk, ed_sk, RSPAMD_CRYPTOBOX_MODE_25519); - if (seeded) { - /* Just encode seed, not the full sk */ - base64_sk = rspamd_encode_base64_common (ed_sk, 32, 0, NULL, FALSE, - RSPAMD_TASK_NEWLINES_LF); - } - else { - base64_sk = rspamd_encode_base64_common (ed_sk, - rspamd_cryptobox_sk_sig_bytes (RSPAMD_CRYPTOBOX_MODE_25519), - 0, NULL, FALSE, - RSPAMD_TASK_NEWLINES_LF); - } - base64_pk = rspamd_encode_base64_common (ed_pk, sizeof (ed_pk), 0, NULL, FALSE, - RSPAMD_TASK_NEWLINES_LF); - - /* Cleanup sensitive data */ - rspamd_explicit_memzero (ed_sk, sizeof (ed_sk)); - - if (priv_fname) { - privfile = fopen (priv_fname, "w"); - - if (privfile == NULL) { - rspamd_fprintf (stderr, "cannot open output file %s: %s\n", - priv_fname, strerror (errno)); - rspamd_explicit_memzero (base64_sk, strlen (base64_sk)); - g_free (base64_sk); - g_free (base64_pk); - exit (EXIT_FAILURE); - } - } - else { - privfile = stdout; - } - - if (rspamd_fprintf (privfile, "%s\n", base64_sk) == -1) { - rspamd_fprintf (stderr, "cannot write to output file %s: %s\n", - priv_fname, strerror (errno)); - rspamd_explicit_memzero (base64_sk, strlen (base64_sk)); - g_free (base64_sk); - g_free (base64_pk); - - if (privfile != stdout) { - fclose (privfile); - } - - exit (EXIT_FAILURE); - } - - if (privfile != stdout) { - fclose (privfile); - } - - if (pub_fname) { - pubfile = fopen (pub_fname, "w"); - - if (pubfile == NULL) { - rspamd_fprintf (stderr, "cannot open output file %s: %s\n", - pub_fname, strerror (errno)); - rspamd_explicit_memzero (base64_sk, strlen (base64_sk)); - g_free (base64_sk); - g_free (base64_pk); - exit (EXIT_FAILURE); - } - } - else { - pubfile = stdout; - } - - rspamd_fprintf (pubfile, "%s._domainkey IN TXT ( \"v=DKIM1; k=ed25519; \"\n" - "\t\"p=%s\" ) ;\n", - selector ? selector : "selector", - base64_pk); - - if (pubfile != stdout) { - fclose (pubfile); - } - - rspamd_explicit_memzero (base64_sk, strlen (base64_sk)); - g_free (base64_sk); - g_free (base64_pk); -} - -static void -rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector, - const gchar *priv_fname, const gchar *pub_fname, guint keylen) -{ - if (strcmp (type, "rsa") == 0) { - rspamd_dkim_generate_rsa_keypair (domain, selector, priv_fname, - pub_fname, keylen); - } - else if (strcmp (type, "ed25519") == 0) { - rspamd_dkim_generate_ed25519_keypair (domain, selector, priv_fname, - pub_fname, keylen, FALSE); - } - else if (strcmp (type, "ed25519-seed") == 0) { - rspamd_dkim_generate_ed25519_keypair (domain, selector, priv_fname, - pub_fname, keylen, TRUE); - } - else { - fprintf (stderr, "invalid key type: %s\n", type); - exit (EXIT_FAILURE); - } -} - -static gint -rspamadm_dkim_keygen_lua_generate (lua_State *L) -{ - const gchar *domain = luaL_checkstring (L, 1); - const gchar *selector = luaL_checkstring (L, 2); - const gchar *privfile = NULL, *pubfile = NULL; - guint key_bits = 1024; - - if (domain == NULL || selector == NULL) { - return luaL_error (L, "invalid arguments"); - } - - if (lua_type (L, 3) == LUA_TSTRING) { - privfile = lua_tostring (L, 3); - } - - if (lua_type (L, 4) == LUA_TSTRING) { - pubfile = lua_tostring (L, 4); - } - - if (lua_type (L, 5) == LUA_TNUMBER) { - key_bits = lua_tonumber (L, 5); - } - - rspamadm_dkim_generate_keypair (domain, selector, privfile, pubfile, key_bits); - - return 0; -} - -static void -rspamadm_dkim_keygen_lua_subrs (gpointer pL) -{ - lua_State *L = pL; - - lua_pushstring (L, "dkim_keygen"); - lua_pushcfunction (L, rspamadm_dkim_keygen_lua_generate); - lua_settable (L, -3); -} - -static void -rspamadm_dkim_keygen (gint argc, gchar **argv, const struct rspamadm_command *cmd) -{ - GOptionContext *context; - GError *error = NULL; - - context = g_option_context_new ( - "dkim_keygen - create dkim keys"); - g_option_context_set_summary (context, - "Summary:\n Rspamd administration utility version " - RVERSION - "\n Release id: " - RID); - g_option_context_add_main_entries (context, entries, NULL); - - if (!g_option_context_parse (context, &argc, &argv, &error)) { - fprintf (stderr, "option parsing failed: %s\n", error->message); - g_error_free (error); - g_option_context_free (context); - exit (EXIT_FAILURE); - } - - g_option_context_free (context); - rspamadm_dkim_generate_keypair (domain, selector, privkey_file, NULL, bits); -} |