From e29268da5a75e63a9dc2efbabfc9f461e3ee42b2 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 9 Dec 2017 22:05:03 +0000 Subject: [PATCH] [Feature] Allow to generate DKIM keys from rspamadm API --- src/rspamadm/dkim_keygen.c | 123 ++++++++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 28 deletions(-) diff --git a/src/rspamadm/dkim_keygen.c b/src/rspamadm/dkim_keygen.c index b29621978..e32f7bf05 100644 --- a/src/rspamadm/dkim_keygen.c +++ b/src/rspamadm/dkim_keygen.c @@ -17,6 +17,7 @@ #include "rspamadm.h" #include "printf.h" #include "str_util.h" +#include "lua/lua_common.h" #include #include #include @@ -28,13 +29,14 @@ static guint bits = 1024; static void rspamadm_dkim_keygen (gint argc, gchar **argv); static const char *rspamadm_dkim_keygen_help (gboolean full_help); +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 = NULL, + .lua_subrs = rspamadm_dkim_keygen_lua_subrs, }; static GOptionEntry entries[] = { @@ -72,10 +74,9 @@ rspamadm_dkim_keygen_help (gboolean full_help) } static void -rspamadm_dkim_keygen (gint argc, gchar **argv) +rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector, + const gchar *priv_fname, const gchar *pub_fname, guint keylen) { - GOptionContext *context; - GError *error = NULL; BIGNUM *e; RSA *r; BIO *pubout, *privout; @@ -84,21 +85,7 @@ rspamadm_dkim_keygen (gint argc, gchar **argv) glong publen; gsize b64_len; gchar *pubdata, *b64_data; - - 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); - exit (1); - } + FILE *pubfile = NULL; if (bits > 4096 || bits < 512) { fprintf (stderr, "Bits number must be in the interval 512...4096\n"); @@ -112,12 +99,12 @@ rspamadm_dkim_keygen (gint argc, gchar **argv) g_assert (RSA_generate_key_ex (r, bits, e, NULL) == 1); g_assert (EVP_PKEY_set1_RSA (pk, r) == 1); - if (privkey_file) { - privout = BIO_new_file (privkey_file, "w"); + if (priv_fname) { + privout = BIO_new_file (priv_fname, "w"); if (privout == NULL) { rspamd_fprintf (stderr, "cannot open output file %s: %s\n", - privkey_file, strerror (errno)); + priv_fname, strerror (errno)); exit (EXIT_FAILURE); } } @@ -129,7 +116,7 @@ rspamadm_dkim_keygen (gint argc, gchar **argv) if (rc != 1) { rspamd_fprintf (stderr, "cannot write key to the output file %s: %s\n", - privkey_file ? privkey_file : "stdout", strerror (errno)); + priv_fname ? priv_fname : "stdout", strerror (errno)); exit (EXIT_FAILURE); } @@ -144,8 +131,21 @@ rspamadm_dkim_keygen (gint argc, gchar **argv) 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_printf ("%s._domainkey IN TXT ( \"v=DKIM1; k=rsa; \"\n" + rspamd_fprintf (pubfile, "%s._domainkey IN TXT ( \"v=DKIM1; k=rsa; \"\n" "\t\"p=%s\" ) ;\n", selector ? selector : "selector", b64_data); @@ -154,20 +154,24 @@ rspamadm_dkim_keygen (gint argc, gchar **argv) guint i; gint step = 253, remain = b64_len; - rspamd_printf ("%s._domainkey IN TXT ( \"v=DKIM1; k=rsa; \"\n", + 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_printf ("\t\"p=%*s\"\n", MIN(step, remain), &b64_data[i]); + rspamd_fprintf (pubfile, "\t\"p=%*s\"\n", MIN(step, remain), &b64_data[i]); } else { step = 255; - rspamd_printf ("\t\"%*s\"\n", MIN(step, remain), &b64_data[i]); + rspamd_fprintf (pubfile, "\t\"%*s\"\n", MIN(step, remain), &b64_data[i]); } } - rspamd_printf (") ; \n"); + rspamd_fprintf (pubfile, ") ; \n"); + } + + if (pubfile != stdout) { + fclose (pubfile); } g_free (b64_data); @@ -176,3 +180,66 @@ rspamadm_dkim_keygen (gint argc, gchar **argv) RSA_free (r); BN_free (e); } + +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) +{ + 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); + exit (1); + } + + rspamadm_dkim_generate_keypair (domain, selector, privkey_file, NULL, bits); +} -- 2.39.5